utimensat truncates timestamp to whole second granularity
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
eCryptfs |
Confirmed
|
Undecided
|
Unassigned |
Bug Description
The utimensat(2) system call should set a file's modification timestamp with nanosecond resolution (or the best resolution supported by the filesystem).
With a Linux kernel 5.4 and ecryptfs, the resolution is actually one second, i.e. the fractions of a second are truncted when the touch(1) utility is used with a reference file
$ touch foo
$ touch -m -r foo bar
The result is
$ ls -l --full-time foo bar
-rw-rw-r-- 1 stephan stephan 0 2020-08-03 11:26:13.000000000 -0400 bar
-rw-rw-r-- 1 stephan stephan 0 2020-08-03 11:26:13.272034647 -0400 foo
which also shows that the first "touch foo" did the right thing.
This happens only
* in an ecryptfs directory
* with a Linux kernel >= 5.4
The bug does not occur
* on the same ext4 filesystem (outside the ecryptfs directory)
* or with ecryptfs but with a kernel version below 5.4
I also verified it in a freshly created ecryptfs directory: with encryption I get a truncated timestamp; without encryption everything is fine.
Other commands, like "cp -a" and "rsync -a" are affected, as well.
$ cp -a foo baz
$ ls -l --full-time foo bar baz
-rw-rw-r-- 1 stephan stephan 0 2020-08-03 11:26:13.000000000 -0400 bar
-rw-rw-r-- 1 stephan stephan 0 2020-08-03 11:26:13.000000000 -0400 baz
-rw-rw-r-- 1 stephan stephan 0 2020-08-03 11:26:13.272034647 -0400 foo
The strace(1) utility shows that utimensat() was called with correct values.
$ strace touch -m -r foo bar
...
utimensat(0, NULL, [UTIME_OMIT, {tv_sec=1596468373, tv_nsec=272034647} /* 2020-08-
Note: I found this Changelog entry on https:/
"VFS: adds a per-superblock minimum/maximum timestamp limit for a file system, and clamps timestamps as they are written, to avoid random behavior from integer overflow as well as having different time stamps on disk vs in memory. This helps futimens(), utimensat() and utimes() syscalls to conform to POSIX defined behavior when the time being set is outside of the corresponding filesystem's supported limits"
My best guess is that ecryptfs does not correctly report 1 ns as the "supported limit".
Can confirm and I am able to repro on Linux 5.4 on ecryptfs. Interestingly if you pass `NULL` in both of the time fields to `utimensat`, as `touch` does, full timestamp resolution is maintained.
This causes breakage with utilities such as `rclone`, which try to synchronize partly based on information such as mtime.