Re: making test(1)'s -nt/-ot ignore nanosecond fractions

From: Bruce Evans (bde_at_zeta.org.au)
Date: 05/09/04

  • Next message: Tim Robbins: "Re: "Fatal trap 12: page fault while in kernel mode" in mmap()"
    Date: Sun, 9 May 2004 18:24:47 +1000 (EST)
    To: Akinori MUSHA <knu@iDaemons.org>
    
    

    On Sun, 9 May 2004, Akinori MUSHA wrote:

    > At Sun, 9 May 2004 00:48:27 +1000 (EST),
    > Bruce Evans wrote:
    > > 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.
    >
    > Hm, I never changed vfs.timestamp_precision to anything other than the
    > default (nor even knew of it), but I acutually observed some files
    > having ...032 and ...256 nanoseconds on an NFS exported FFS on
    > 4-STABLE. I'm not sure if the files were created directly on FFS or
    > via NFS.
    >
    > Does that mean there could be a bug somewhere around nanotime() calls?

    The most obvious bug is that nfsclient has no reference to VA_UTIMES_NULL.
    I think this cause it to use stack garbage for tv_nsec. This seems to be
    fixed in NetBSD.

    Demonstration of the bug:

    %%%
    Script started on Sun May 9 17:29:21 2004
    ttyv2:bde@gamplex:/c/z> cat foo.c
    main(int argc, char **argv) { utimes(argv[1], 0); }
    ttyv2:bde@gamplex:/c/z> cc -o foo foo.c
    ttyv2:bde@gamplex:/c/z> /usr/bin/stat -f "%N %Fm" foo
    foo 1084087769.000000000
    ttyv2:bde@gamplex:/c/z> ./foo foo
    ttyv2:bde@gamplex:/c/z> /usr/bin/stat -f "%N %Fm" foo
    foo 1084087802.503363000
    ttyv2:bde@gamplex:/c/z> ./foo foo
    ttyv2:bde@gamplex:/c/z> /usr/bin/stat -f "%N %Fm" foo
    foo 1084087824.912722647
    ttyv2:bde@gamplex:/c/z> exit

    Script done on Sun May 9 17:30:36 2004
    %%%

    After cc -o foo, foo has a normal mtime set by writing on the server
    (-current nfsv3 server with vfs.timestamp_precision=0). Then running
    utimes("foo", 0) on the client messes up foo's st_mtime.tv_nsec.
    Somehow it avoids messing up foo's st_mtime.tv_sec, and on the first
    run it rounds to the nearest usec (this behaviour seems to be consistent).

    I think utimes("foo", 0) should run on the client and set the times to
    the current time on the client just like utimes("foo", non_null) would
    set to times obtained from somewhere on the client. However, I think
    the times should always be rounded (by the server) according to the
    server's vfs.timestamp_precision. Clients can't be expected to do this
    since they might not support a timestamp precision. More precision than
    the server would set for writes would be less than useful.

    Here is part of the NetBSD code for supporting VA_UTIMES_NULL (atimes are
    handled similarly for TOSERVER, but not for TOCLIENT -- VA_UTIMES_NULL Is
    not used then):

    nfsm_subs.h 1.36:
    % #define nfsm_srvsattr(a) \
    % ... \
    % switch (fxdr_unsigned(int, *tl)) { \
    % case NFSV3SATTRTIME_TOCLIENT: \
    % nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
    % fxdr_nfsv3time(tl, &(a)->va_mtime); \
    % (a)->va_vaflags &= ~VA_UTIMES_NULL; \
    % break; \
    % case NFSV3SATTRTIME_TOSERVER: \
    % (a)->va_mtime.tv_sec = time.tv_sec; \
    % (a)->va_mtime.tv_nsec = time.tv_usec * 1000; \
    % (a)->va_vaflags |= VA_UTIMES_NULL; \
    % break; \
    % }; }

    The corresponding code in -current is:

    nfs_srvsubs.c:
    % int
    % nfsm_srvsattr_xx(struct vattr *a, struct mbuf **md, caddr_t *dpos)
    % ...
    % switch (fxdr_unsigned(int, *tl)) {
    % case NFSV3SATTRTIME_TOCLIENT:
    % tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
    % if (tl == NULL)
    % return EBADRPC;
    % fxdr_nfsv3time(tl, &(a)->va_mtime);
    % break;
    % case NFSV3SATTRTIME_TOSERVER:
    % getnanotime(&(a)->va_mtime);
    % break;
    % }

    Looks like I was wrong about the client handling VA_UTIMES_NULL -- the
    above seems to run on the server. I don't understand what it is doing
    with VA_UTIMES_NULL.

    Other aspects of the bug are clearer: using getnanotime() instead of
    vfs_timestamp() breaks the policy set in vfs.timestamp_precision. It
    wrong anyway since it gives excessive precision -- getnanotime() has
    at most 1/HZ accuracy. `time' used to have the same accuracy and
    perhaps still does in NetBSD, but using it gives 3 fewer digits of
    excessive precision and is friendlier with utimes().

    THe quick fix is to replace the above getnanotime() with vfs_timestamp().
    Unfortunately, nfs has 16 other calls to getnanotime(), 2 calls to
    microtime() and 3 calls to getmicrotime() that need to be checked.

    Bruce
    _______________________________________________
    freebsd-current@freebsd.org mailing list
    http://lists.freebsd.org/mailman/listinfo/freebsd-current
    To unsubscribe, send any mail to "freebsd-current-unsubscribe@freebsd.org"


  • Next message: Tim Robbins: "Re: "Fatal trap 12: page fault while in kernel mode" in mmap()"

    Relevant Pages

    • Re: Synchronized objects
      ... > proxies to remote objects and the appropriate one to use depends on how ... > plan to use the object in your clients and on your server. ... > 1) Does every client that connects need to access the same Foo instance ...
      (microsoft.public.dotnet.framework.remoting)
    • Re: How to listen out for a stream of data coming from (web)server
      ... I have an applet that connects to a server and ... This saves having to open a listening port on the client side, something that can hurt when it bangs into a firewall. ... get a "READY FOR INSTRUCTION" connection from client foo ...
      (comp.lang.java.programmer)
    • Re: Concurrency violation and DateTime
      ... the server side and client side precision doesn't match for datetime values. ...
      (microsoft.public.dotnet.framework.adonet)
    • Re: MessageFilter - phase 2 (client side)
      ... now the COM client suppose to do so... ... if i wanna call Foo() in the server, i have to call Fooof the ... It's a server, by definition. ... then the client::Foosuppose to create the worker thread. ...
      (microsoft.public.win32.programmer.ole)
    • Re: Post processing of NTP data...
      ... results more or less reliably, in my own experience I have not seen ntp regulate time of a stratum 2 server without occasional excursions in the 100's of ms range. ... application configuration might be able to achieve long-term stability that is accurate to less than a millisecond, but that's accuracy and not precision. ... CERN to pre-process their data they were collecting for their particle accelerator, and they weren't using NTP to try to maintain a high stability clock with good long-term accuracy. ... All that mattered was that they could tell very precisely that particle track X preceded or followed particle track Y by exactly a certain time interval Z. ...
      (comp.protocols.time.ntp)