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>