Increase timestamp precision?
Bruce Evans
brde at optusnet.com.au
Sat Feb 11 02:10:35 UTC 2012
PS:
On Sat, 11 Feb 2012, Bruce Evans wrote:
> On Fri, 10 Feb 2012, Sergey Kandaurov wrote:
>
>> On 10 February 2012 17:55, Ed Schouten <ed at 80386.nl> wrote:
>>> Hi all,
>>>
>>> It seems the default timestamp precision sysctl
>>> (vfs.timestamp_precision) is currently set to 0 by default, meaning we
>>> don't do any sub-second timestamps on files. Looking at the code, it
>>> seems that vfs.timestamp_precision=1 will let it use a cached value with
>>> 1 / HZ precision and it looks like it should have little overhead.
>>>
>>> Would anyone object if I were to change the default from 0 to 1?
>
> Sure. The setting of 1 is too buggy to use in its current implementation.
> I don't know of any fixed version, so there is little experience with
> a usable version. I also wouldn't use getnanotime() for anything.
> But I like nanotime().
[ ... the bugs are that it gives nanoseconds precision with garbage in the
low bits, and shares an old bug with a setting of 0 (TSP_SEC) ]
Other bugs near here:
- vfs.timestamp_precision is still global, so you can't change the default
for individual mount points or even for individual vfs's. The global
is only good enough for a quick hack.
- touch(1) normally uses gettimeofday() and utimes(). Thus it normally
gives microseconds precision and hopefully close to microseconds
accuracy (if you are using ntpd). But when utimes() fails due to
insufficient security and the user didn't specify a time, touch(1)
falls back to using utimes() with a null timeptr, to ask the kernel
to use the current time. The kernel uses vfs_timestamp() for this,
so it sets times incompatibitly with touch(1) unless
vfs.timestamp_precision=2 (TSP_USEC). The kernel used to use
microtime() for this, but it was changed in 2009 to use
vfs_timestamp(), with no reason given in its log message except a
cryptic pointer to a Debian PR. The bug is mostly in touch(1).
- the recently-removed fallback to setting times by writing in touch(1)
gave another incompatible way of setting times.
Timstamping bugs not so near here:
- POSIX.1-1988 avoided the design error and unportability of timevals
by inventing timespecs. It failed to invent an interfaces to set
these. It only has utime(), which only sets times in seconds.
- POSIX.1-2001 restored the design error of timevals, and utimes()
to set them (but utimes() was marked as legacy). It still failed to
invent an interface to set its own timespecs.
- POSIX is apparently inventing futimesat(). This only sets timevals.
POSIX is apparently still failing to invent an interface to set its
own timespecs. Any utime()-like interface invented after timespecs
should support timespecs, with setting timevals only supported by
compatibility cruft in this interface.
- FreeBSD also has birthtimes, but no way to set them. Any utime()-like
interface invented after birthtimes should support them. FreeBSD's
man page says essentially this. futimesat() is unfortunately being
standardized, so it can't be this syscall.
- in the man page, the times arg is declared as "*times" for everything
except futimesat(). For the latter, it is declared as times[2]. This
is a further regression in the spelling of the arg. utime(2) has
a better API (struct instead of array) and a better spelling of the
arg (timep). POSIX.1-2001 uses "times" for the utime() and times[2]
for utimes().
- I also wish for a way to set ctimes. Without this, metadata cannot
be restored from backups. I use a hack to restore ctimes by abusing
utime*().
Bruce
More information about the freebsd-fs
mailing list