From nobody@FreeBSD.org  Thu Jun 21 03:40:33 2012
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 3E82B1065673
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 21 Jun 2012 03:40:33 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from red.freebsd.org (red.freebsd.org [IPv6:2001:4f8:fff6::22])
	by mx1.freebsd.org (Postfix) with ESMTP id 0FDD68FC17
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 21 Jun 2012 03:40:33 +0000 (UTC)
Received: from red.freebsd.org (localhost [127.0.0.1])
	by red.freebsd.org (8.14.4/8.14.4) with ESMTP id q5L3eW45081665
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 21 Jun 2012 03:40:32 GMT
	(envelope-from nobody@red.freebsd.org)
Received: (from nobody@localhost)
	by red.freebsd.org (8.14.4/8.14.4/Submit) id q5L3eWPn081664;
	Thu, 21 Jun 2012 03:40:32 GMT
	(envelope-from nobody)
Message-Id: <201206210340.q5L3eWPn081664@red.freebsd.org>
Date: Thu, 21 Jun 2012 03:40:32 GMT
From: Shinji KOBAYASHI <skoba@moss.gr.jp>
To: freebsd-gnats-submit@FreeBSD.org
Subject: utimes does not update st_mtim.tv_nsec when utimes(file, NULL)
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         169282
>Category:       kern
>Synopsis:       [libc] utimes(2) does not update st_mtim.tv_nsec when utimes(file, NULL)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jun 21 03:50:09 UTC 2012
>Closed-Date:    
>Last-Modified:  Sat Jun 23 00:46:26 UTC 2012
>Originator:     Shinji KOBAYASHI
>Release:        FreeBSD 9.0-STABLE
>Organization:
Ehime University
>Environment:
FreeBSD shuttle 9.0-STABLE FreeBSD 9.0-STABLE #28: Sat Jun 16 15:11:09 JST 2012     skoba@shuttle:/usr/obj/usr/src/sys/shuttle  amd64

>Description:
man utimes 2 shows that utimes(file, NULL) updates file modified time to current time. But the sample code shows tv_mtim.tv_nsec equals 0, after utimes(file, NULL).

filetest.c
----
include <sys/time.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>

int main(void) {
  char *name;
  struct stat filestatus;
  int fd;
  int second;
  int nanosecond;
  name = "t.log";
  
  fd = creat(name, 0666);
  fstat(fd, &filestatus);
  second = filestatus.st_mtim.tv_sec;
  nanosecond = filestatus.st_mtim.tv_nsec;
  printf("File created time %d sec,%d nsec\n", second, nanosecond);
  usleep(1000100);
  utimes(name, NULL);
  fstat(fd, &filestatus);
  printf("File modified time %d sec, %dnsec\n", filestatus.st_mtim.tv_sec, filestatus.st_mtim.tv_nsec);
  usleep(1000100);
  creat(name);
  fstat(fd, &filestatus);
  printf("File modified time %d sec, %dnsec\n", filestatus.st_mtim.tv_sec, filestatus.st_mtim.tv_nsec);
  return 0;
}
---
The result:
shuttle% ./filetest                                                       ~/src
File created time 1340243920 sec,662186384 nsec
File modified time 1340243921 sec, 0nsec
File modified time 1340243922 sec, 666190831nsec

>How-To-Repeat:
filetest.c
----
include <sys/time.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>

int main(void) {
  char *name;
  struct stat filestatus;
  int fd;
  int second;
  int nanosecond;
  name = "t.log";
  
  fd = creat(name, 0666);
  fstat(fd, &filestatus);
  second = filestatus.st_mtim.tv_sec;
  nanosecond = filestatus.st_mtim.tv_nsec;
  printf("File created time %d sec,%d nsec\n", second, nanosecond);
  usleep(1000100);
  utimes(name, NULL);
  fstat(fd, &filestatus);
  printf("File modified time %d sec, %dnsec\n", filestatus.st_mtim.tv_sec, filestatus.st_mtim.tv_nsec);
  usleep(1000100);
  creat(name);
  fstat(fd, &filestatus);
  printf("File modified time %d sec, %dnsec\n", filestatus.st_mtim.tv_sec, filestatus.st_mtim.tv_nsec);
  return 0;
}
---
The result:
shuttle% cc -o filetest filetest.c
shuttle% ./filetest                                                       ~/src
File created time 1340243920 sec,662186384 nsec
File modified time 1340243921 sec, 0nsec
File modified time 1340243922 sec, 666190831nsec

>Fix:


>Release-Note:
>Audit-Trail:

From: Bruce Evans <brde@optusnet.com.au>
To: Shinji KOBAYASHI <skoba@moss.gr.jp>
Cc: freebsd-gnats-submit@FreeBSD.org, freebsd-bugs@FreeBSD.org
Subject: Re: kern/169282: utimes does not update st_mtim.tv_nsec when
 utimes(file, NULL)
Date: Fri, 22 Jun 2012 02:10:19 +1000 (EST)

 On Thu, 21 Jun 2012, Shinji KOBAYASHI wrote:
 
 >> Description:
 > man utimes 2 shows that utimes(file, NULL) updates file modified time to current time. But the sample code shows tv_mtim.tv_nsec equals 0, after utimes(file, NULL).
 
 It sets tv_mtim to the current time in the current timestamp precision.
 The default timestamp precision is 1 second, and you apparently didn't
 change this, so tv_nsec should be 0 for all times.  See vfs_timestamp(9).
 The correct man page (a user one for the vfs.timestamp_precision sysctl)
 unfortunately doesn't exist.
 
 > filetest.c
 > ----
 > include <sys/time.h>
 > #include <sys/stat.h>
 > #include <stdio.h>
 > #include <unistd.h>
 >
 > int main(void) {
 >  char *name;
 >  struct stat filestatus;
 >  int fd;
 >  int second;
 >  int nanosecond;
 >  name = "t.log";
 >
 >  fd = creat(name, 0666);
 >  fstat(fd, &filestatus);
 >  second = filestatus.st_mtim.tv_sec;
 >  nanosecond = filestatus.st_mtim.tv_nsec;
 >  printf("File created time %d sec,%d nsec\n", second, nanosecond);
 >  usleep(1000100);
 >  utimes(name, NULL);
 >  fstat(fd, &filestatus);
 >  printf("File modified time %d sec, %dnsec\n", filestatus.st_mtim.tv_sec, filestatus.st_mtim.tv_nsec);
 >  usleep(1000100);
 >  creat(name);
 >  fstat(fd, &filestatus);
 >  printf("File modified time %d sec, %dnsec\n", filestatus.st_mtim.tv_sec, filestatus.st_mtim.tv_nsec);
 >  return 0;
 > }
 > ---
 > The result:
 > shuttle% ./filetest                                                       ~/src
 > File created time 1340243920 sec,662186384 nsec
 > File modified time 1340243921 sec, 0nsec
 > File modified time 1340243922 sec, 666190831nsec
 >
 >> How-To-Repeat:
 > filetest.c
 > ----
 > include <sys/time.h>
 > #include <sys/stat.h>
 > #include <stdio.h>
 > #include <unistd.h>
 >
 > int main(void) {
 >  char *name;
 >  struct stat filestatus;
 >  int fd;
 >  int second;
 >  int nanosecond;
 >  name = "t.log";
 >
 >  fd = creat(name, 0666);
 >  fstat(fd, &filestatus);
 >  second = filestatus.st_mtim.tv_sec;
 >  nanosecond = filestatus.st_mtim.tv_nsec;
 >  printf("File created time %d sec,%d nsec\n", second, nanosecond);
 >  usleep(1000100);
 >  utimes(name, NULL);
 >  fstat(fd, &filestatus);
 >  printf("File modified time %d sec, %dnsec\n", filestatus.st_mtim.tv_sec, filestatus.st_mtim.tv_nsec);
 >  usleep(1000100);
 >  creat(name);
 >  fstat(fd, &filestatus);
 >  printf("File modified time %d sec, %dnsec\n", filestatus.st_mtim.tv_sec, filestatus.st_mtim.tv_nsec);
 >  return 0;
 > }
 > ---
 > The result:
 > shuttle% cc -o filetest filetest.c
 > shuttle% ./filetest                                                       ~/src
 > File created time 1340243920 sec,662186384 nsec
 > File modified time 1340243921 sec, 0nsec
 > File modified time 1340243922 sec, 666190831nsec
 
 The bug is in the other times.  They should have a nanoseconds part that
 is consistently 0.
 
 You didn't say which file system you run these test on, but I don't
 know of any except zfs and maybe msdosfs which would give this bug.
 
 zfs seems to hard-code the timestamp precision as index 1, by using
 gethrestime() to get the time, where gethrestime() is implemented as
 getnanotime().  It should be implemented as vfs_timestamp() (at least
 if it is only used for file times).
 
 msdosfs harder-codes timestamp calls as getnanotime(), but usually the
 problem isn't noticeable with it since its timestamp resolution is
 usually even less than 1 second.
 
 Related bugs:
 
 1. vfs_timestamp(9) documents precision index 1 as being accurate to
     within 1/HZ.  Precision index 1 actually gives accuraty of $(sysctl
     kern.timecounter.tick)/hz.  This is about 1/hz or 1 msec, whichever
     is least.  The sysctl description and the comments and enum names
     in the source code for vfs.timestamp_precision have the same bug.)
 
 2. vfs_timestamp() with precision index 1 gives garbage in the low
     digits of the nanoseconds part.  Since its precision with this
     index is at most 1 msec, at least 6 of the 9 digits are garbage.
     The garbage might be useful in some contexts, but not for file
     times.  File times can't even be written without clearing the 3
     low digits in the nanoseconds part.  All other indexes give
     rounding of the nanoseconds part down to a multiple of the
     precision.  For example, index 2 gives a precision of 1 usec with
     rounding down, so although it is much more precise and accurate
     than index 1, the garbage makes index 1 look more precise and
     accurate.
 
 Bruce

From: Shinji KOBAYASHI <skoba@moss.gr.jp>
To: bug-followup@FreeBSD.org, skoba@moss.gr.jp
Cc:  
Subject: Re: kern/169282: utimes does not update st_mtim.tv_nsec when
 utimes(file, NULL)
Date: Fri, 22 Jun 2012 05:00:27 +0900

 Thank you Bruce,
 Your explanation made just sense for me.
 I use zfs and met this bug. I am happy to know
 my report had some meanings, because I am not
 sure to report this. I have used FreeBSD in these
 15 years, and would be happier if FreeBSD would
 be more reliable by my report.
 
 Best regards,
 Shinji Kobayashi
>Unformatted:
