[BUG] NFSv4.2: futimens() returns success without sending SETATTR
Michael <[email protected]> Mon, 20 Jul 2026 03:18:30 +0000
| Newsgroups | gmane.linux.nfs |
|---|---|
| Message-ID | <nMlXgkbm-9ZP_fFN16OpzFd4kwNlyXq169-6CoOE4nuHyTsmGaFeJgzuhj3grRboJKg9RapKov2_FJ1E3BCL0oZ7UNzF0pgwwhVC6VOVJYQ=@proton.me> |
Hello,
I am seeing a reproducible NFSv4.2 timestamp issue where an fd-based timestamp update returns success but does not appear to send an NFS SETATTR operation or update the server-side inode.
Client environment:
Distribution: Fedora 44
Kernel version: 7.1.3 x86_64
GNU coreutils version: 9.10
NFS utilities version: 2.8.7
Reproducible with both 7.1.3-cachyos1.lto.fc44.x86_64 and the stock Fedora 7.1.3-201.fc44.x86_64 kernel.
NFS mount options:
home:/tank on /mnt/tank type nfs4 (rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,fatal_neterrors=none,proto=tcp,timeo=50,retrans=2,sec=sys,clientaddr=169.254.87.187,local_lock=none,addr=169.254.42.42,_netdev,x-systemd.automount,x-systemd.mount-timeout=5,x-systemd.idle-timeout=15min)
Also reproducible with the noac option.
NFS server export options:
/tank 169.254.0.0/16(rw)
The failing case is the fd-based form (futimens) used by GNU touch:
touch -d '2004-02-29 16:21:42' /mnt/tank/test
Relevant strace output:
openat(AT_FDCWD, "/mnt/tank/test",
O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666)
= 3</mnt/tank/test>
utimensat(0</mnt/tank/test>, NULL,
[{tv_sec=1078032102, tv_nsec=0},
{tv_sec=1078032102, tv_nsec=0}], 0)
= 0
The file descriptor has been duplicated to fd 0 by coreutils before the utimensat() call.
Observed behaviour:
1. utimensat() returns success.
2. stat on the NFS client temporarily shows the requested atime and mtime.
3. The server-side backing inode remains unchanged.
4. The NFS client SETATTR counter does not increment.
5. After client attribute revalidation, the client timestamp reverts to the unchanged server timestamp.
6. sync and a clean unmount do not propagate the timestamp change.
Example client-side result immediately after touch:
Access: 2004-02-29 16:21:42.000000000 +1100
Modify: 2004-02-29 16:21:42.000000000 +1100
Change: 2026-07-20 09:54:29.303441484 +1000
At the same time, the server-side inode still shows:
Access: 2026-07-20 09:50:16.502885123 +1000
Modify: 2026-07-20 09:50:16.502885123 +1000
Change: 2026-07-20 09:50:16.502885123 +1000
The client and server report the same inode number and birth timestamp, so they appear to be referring to the same file.
As a control, a pathname-based utimensat() works correctly:
utimensat(AT_FDCWD, "/mnt/tank/test",
[{tv_sec=1078032102, tv_nsec=0},
{tv_sec=1078032102, tv_nsec=0}], 0)
= 0
For the pathname-based call:
1. The NFS client SETATTR counter increments.
2. The server-side inode timestamp is updated immediately.
This therefore appears specific to the fd-based futimens() / utimensat(fd, NULL, ...) path.
The minimal distinction is:
fd-based timestamp update:
returns success
no SETATTR observed
server inode unchanged
update later disappears
pathname-based timestamp update:
returns success
SETATTR observed
server inode updated
Please let me know if further information or testing is required.
Regards,
Michael Yang