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
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "[email protected]"