Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 9 May 2004 00:48:27 +1000 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        Akinori MUSHA <knu@iDaemons.org>
Cc:        audit@freebsd.org
Subject:   Re: making test(1)'s -nt/-ot ignore nanosecond fractions
Message-ID:  <20040509000147.U4217@gamplex.bde.org>
In-Reply-To: <86smebgjsb.knu@iDaemons.org>
References:  <86smebgjsb.knu@iDaemons.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sat, 8 May 2004, Akinori MUSHA wrote:

> I faced an odd situation regarding file timestamps:
>
>     knu@archon[2]% sh
>     $ ls a b
>     a	b
>     $ touch -r a b
>     $ [ a -nt b ] && echo "D'oh!"
>     D'oh!
>     $ touch -r a a
>     $ [ a -nt b ] || echo "Nah, how did it fix?"
>     Nah, how did it fix?
>
> (Note that this is only rarely reproducible)

Hopefully never if the reference file was created by ffs and
vfs.timestamp_precision is the default.

> I tracked it down and found out some facts:
>
>     - File timestamps are recorded in nanoseconds on a UFS, and
>       sometimes a file's timestamp actually has >1000 nanosecond
>       (= >1 microsecond) value.

ffs uses vfs_timestamp() which gives a timestamp with the precision
specified by vfs.timestamp_precision.  The default is 0 (TSP_SEC),
which means that timestamps on files are normally in seconds with
nanoseconds part 0.  This can be changed easily using sysctl, but
changing the precision to the highest (nanoseconds) gives the bugs
being discussed.  Changing it to microseconds precision is safer,
since utimes(2) (but not utime(2) supports this precision.

The only other way to get ffs timestamps with a nonzero nanseconds
part is to use utimes(), but this gives microseconds precision which
utimes() can copy later.

> [... details deleted]
>     - Which means touch(1) or any other userland tool can only set a
>       file's mtime in microseconds at most.
> ...
> In order to fix this, we could consider adding a syscall or extend
> utimes(2) to take nanoseconds, but I'm afraid it would take a long
> time before it becomes available on -STABLE and the API spread over
> third-party applications.  So, I'd suggest the following simple fix to
> make test(1) ignore such nanosecond fractions as a temporary measure:

It's already taken more than 10 years for for the API to make null
progress matching the nanoseconds filesystem timestamps :(.

I think timestamps with a precision smaller than 1 microsecond should
just not be made (don't support it in vfs_timestamp(), and fix all the
file systems that use nanotime() directly).

Another problem with file times is that they can be older than the
time at which they are made, due to shortcuts in time_second and
getnanotime().  E.g., if the current time is N.009999 seconds so that
time(3) returns N, then time_second may be (N-1) seconds, so file times
may be 1 second older than the time at which they were made if
vfs.timestamp_precision is the default.  Similarly, if
vfs.timestamp_precision is 1 (TSP_HZ), then file times may be 1/HZ
seconds older than the time at which they were made.  These bugs are
missing if vfs.timestamp_precision is 2 (TSP_USEC) or 3 (TSP_NSEC).
I've never needed more that seconds resolution AFAIK, but I sometimes
use vfs.timestamp_precision=3 to avoid the bugs.

A vfs.timestamp_precision of 1 (TSP_HZ) is more broken than I remembered.
It doesn't round the nanoseconds part to a multiple of 1/HZ or a multiple
of 1000, so it gives timestamps that utimes() can't preserve for no
benefit.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040509000147.U4217>