* test-fdutimensat failures after 7.0.6-200.fc44.x86_64 kernel update
@ 2026-05-16 5:14 Collin Funk
0 siblings, 0 replies; only message in thread
From: Collin Funk @ 2026-05-16 5:14 UTC (permalink / raw)
To: bug-gnulib
Cc: Christoph Hellwig, linux-kernel, linux-btrfs, linux-fsdevel,
Jan Kara, Christian Brauner
Hi,
After updating my Fedora system to kernel version 7.0.6-200.fc44.x86_64,
I noticed that the Gnulib 'test-fdutimensat' test fails a majority of
the time in my GNU coreutils checkout:
$ seq 100 | xargs -n 1 sh -c '
./test-fdutimensat >/dev/null 2>&1
echo $?
' | LC_ALL=C sort | LC_ALL=C uniq -c
14 0
86 134
Here is the section of code where it fails [1]:
/* Play with UTIME_OMIT, UTIME_NOW. */
{
struct stat st3;
struct timespec ts[2];
ts[0].tv_sec = BILLION;
ts[0].tv_nsec = UTIME_OMIT;
ts[1].tv_sec = 0;
ts[1].tv_nsec = UTIME_NOW;
nap ();
ASSERT (func (BASE "link", ts) == 0);
ASSERT (lstat (BASE "link", &st3) == 0);
if (check_atime_on_symlinks)
{
/* The first assertion fails. */
ASSERT (st3.st_atime == Y2K);
ASSERT (0 <= get_stat_atime_ns (&st3));
ASSERT (get_stat_atime_ns (&st3) < BILLION / 2);
}
Adding some print statements in place of the comment:
fprintf (stderr, "%jd\n", (intmax_t) st3.st_atime);
fprintf (stderr, "%jd\n", (intmax_t) Y2K);
fprintf (stderr, "----------------\n");
Here is an example of what is seen when the test fails:
$ ./test-fdutimensat
----------------
1778905091
946684800
test-lutimens.h:192: assertion 'st3.st_atime == Y2K' failed
Here is an example of what is seen when the test passes:
$ ./test-fdutimensat
----------------
946684800
946684800
----------------
946684800
946684800
----------------
946684800
946684800
So, it looks like the atime is being updated sometimes despite the use
of UTIME_OMIT.
Interestingly, in my Gnulib checkout residing in a separate directory
the test passes:
$ git clone https://github.com/coreutils/gnulib.git
$ cd gnulib
$ ./gnulib-tool --create-testdir --dir testdir1 fdutimensat
$ cd testdir1
$ ./configure && make -j $(nproc)
$ cd gltests
$ seq 100 | xargs -n 1 sh -c '
./test-fdutimensat >/dev/null 2>&1
echo $?
' | LC_ALL=C sort | LC_ALL=C uniq -c
100 0
All of this testing was performed on the same BTRFS subvolume:
/dev/mapper/nvme0n1p3_encrypted on /home type btrfs (rw,relatime,seclabel,ssd,space_cache=v2,subvolid=257,subvol=/root/home)
I could only find one commit since 6.19.14-300.fc44, which I never
experienced this error on, that looked like it may be related [2]. I am
very much unfamiliar with this code, so anything after this sentence
should be taken with a grain of salt.
Looking at the new inode_update_atime function that was added in that
commit:
> +static int inode_update_atime(struct inode *inode)
> +{
> + struct timespec64 atime = inode_get_atime(inode);
> + struct timespec64 now = current_time(inode);
> +
> + if (timespec64_equal(&now, &atime))
> + return 0;
> +
> + inode_set_atime_to_ts(inode, now);
> + return inode_time_dirty_flag(inode);
> +}
Compared to the old inode_update_timestamps function:
> -int inode_update_timestamps(struct inode *inode, int flags)
> +int inode_update_time(struct inode *inode, enum fs_update_time type,
> + unsigned int flags)
> {
> - int updated = 0;
> - struct timespec64 now;
> -
> - if (flags & (S_MTIME|S_CTIME|S_VERSION)) {
> - struct timespec64 ctime = inode_get_ctime(inode);
> - struct timespec64 mtime = inode_get_mtime(inode);
> -
> - now = inode_set_ctime_current(inode);
> - if (!timespec64_equal(&now, &ctime))
> - updated |= S_CTIME;
> - if (!timespec64_equal(&now, &mtime)) {
> - inode_set_mtime_to_ts(inode, now);
> - updated |= S_MTIME;
> - }
> - if (IS_I_VERSION(inode) && inode_maybe_inc_iversion(inode, updated))
> - updated |= S_VERSION;
> - } else {
> - now = current_time(inode);
> - }
> -
> - if (flags & S_ATIME) {
> - struct timespec64 atime = inode_get_atime(inode);
> -
> - if (!timespec64_equal(&now, &atime)) {
> - inode_set_atime_to_ts(inode, now);
> - updated |= S_ATIME;
> - }
> + switch (type) {
> + case FS_UPD_ATIME:
> + return inode_update_atime(inode);
> + case FS_UPD_CMTIME:
> + return inode_update_cmtime(inode);
> + default:
> + WARN_ON_ONCE(1);
> + return -EIO;
> }
> - return updated;
> }
The behavior looks a bit different in the case of flags having S_MTIME,
S_CTIME, and S_VERSION being set. Before that commit it would use the
following to compare to atime:
now = inode_set_ctime_current(inode);
However, now it will always use:
struct timespec64 now = current_time(inode);
Could that be the cause of this behavior?
Let me know if there is any other useful information that I can share.
Thanks,
Collin
[1] https://github.com/coreutils/gnulib/blob/master/tests/test-lutimens.h#L176-L192
[2] https://github.com/torvalds/linux/commit/761475268fa8e322fe6b80bcf557dc65517df71e#diff-325e7194d6fde054508f3ab689c05b774e0755b85d5639dc92c19a2230bbcc2f
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-05-16 5:14 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-16 5:14 test-fdutimensat failures after 7.0.6-200.fc44.x86_64 kernel update Collin Funk
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox