Fix integer overflows when handling objects >= 2G

Fix a series of overflows that caused objects larger than two gigabytes
to be mishandled. Since kernel_object_store is 4G on amd64, this is
slightly worrying.

OK oga@
Fix 7ad4a38e

7ad4a38e destroyed tmpfs performance for small writes; repair it.

The tmpfs code keeps one page worth of data cached for files which are
open. The idea is to avoid the heavy penalty involved in mapping the
page for tiny I/Os (< PAGE_SIZE). This used to work fine until I
rendered the cache useless in 7ad4a38e, with devasting effects on
performance.

Before:

% time dd if=/dev/zero of=x bs=1 count=4194304
0.24s user 2.59s system 99% cpu 2.834 total

After:

% time dd if=/dev/zero of=x bs=1 count=4194304
0.29s user 33.55s system 99% cpu 33.840 total

The purpose of 7ad4a38e was to address the case where a file needs to be
partly zero'd due to its size being reduced by less than a page and then
later extended. The commit mistakenly tried to handle this case in the
extension path, forcing the file to be unnecessarily uncached so the
remaning bytes on the current page could be zero'd.

A smarter approach is to handle this case when truncation first happens,
*while* keeping the current page cached. This brings us back to the old
performance numbers while fixing the bug addressed by 7ad4a38e.

OK oga@

For the record, here are some silly test programs I used to a) assess
performance impact; b) check that file contents are correctly zero'd
when the size of the file is reduced.

cat >r.c <<EOF

/* check for truncation/extension bug */
int
main(int argc, char **argv)
{
	char temp[] = "/tmp/ftruncateXXXXXXXX";

	int fd = mkstemp(temp);
	if (fd < 0)
		err(1, "mkstemp");

	remove(temp);

	char *p = malloc(CHUNKSIZ);
	if (p == NULL)
		err(1, NULL);

	memset(p, 0xff, CHUNKSIZ);

	if (write(fd, p, CHUNKSIZ) != CHUNKSIZ)
		err(1, "write");

	if (ftruncate(fd, CHUNKSIZ - 128) < 0)
		err(1, "ftruncate");

	if (ftruncate(fd, CHUNKSIZ) < 0)
		err(1, "ftruncate");

	char *q = malloc(128);
	if (q == NULL)
		err(1, NULL);

	if (pread(fd, q, 128, CHUNKSIZ - 128) != 128)
		err(1, "pread");

	int i;

	for (i = 0; i < 128; i++)
		if (q[i]) {
			printf("got 0x%02x\n", (unsigned char)q[i]);
			exit(1);
		}

	exit(0);
}
EOF

cat >t.c <<EOF

/* truncate a file one byte at a time */
int
main(int argc, char **argv)
{
	if (argc != 2)
		exit(1);

	int fd = open(argv[1], O_WRONLY);
	if (fd < 0)
		err(1, "open");

	for (;;) {
		off_t p = lseek(fd, 0, SEEK_END);
		if (p == 0)
			break;
		if (ftruncate(fd, p - 1) < 0)
			err(1, "ftruncate");
	}

	exit(0);
}
EOF
Correctly fill 'va_bytes' for sparse files.
Bump ps column widths.

Adjust column widths for common memory usage scenarios and for systems
which are actually up for more than 41 days.

dsiz, maxrss, rss, rsz, vsz: 6 chars (max ~1GB)
lim: 7 chars (max ~10GB)
time: 10 chars (max ~400 days)

Cut STARTED down to 7 chars to save some space. The format never
produced wider values anyways.

ok pedro@ drahn@
no objections from oga@