All of lore.kernel.org
 help / color / mirror / Atom feed
* 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.