public inbox for linux-nfs@vger.kernel.org
 help / color / mirror / Atom feed
From: Tom Haynes <loghyr@gmail.com>
To: linux-nfs@vger.kernel.org
Cc: trondmy@kernel.org, anna@kernel.org, jlayton@kernel.org,
	chuck.lever@oracle.com
Subject: [PATCH 0/1] nfs: fix directory mtime staleness under directory delegation after local mutations
Date: Sat, 18 Apr 2026 12:03:00 -0700	[thread overview]
Message-ID: <20260418190301.3661-1-loghyr@gmail.com> (raw)

Hi all,

A cross-parent rename(2) against a Linux NFSv4.2 server leaves the
client's cached mtime on both parent directories stale, even though
the server's in-memory inode mtime is updated correctly.  The bug is
entirely on the client side in the directory-delegation + mutation
interaction.

Server instrumentation (bpftrace on vfs_getattr + xfs_trans_ichgtime)
showed the backing XFS and knfsd path both advance mtime correctly
through vfs_rename -> xfs_dir_rename_children -> xfs_trans_ichgtime.
Subsequent vfs_getattr calls on the parent dirs on the server side
return the fresh mtime.

On the client:

 1. The local rename path calls nfs4_update_changeattr_locked() and
    marks NFS_INO_INVALID_NLINK | NFS_INO_INVALID_DATA on each parent.
 2. The next stat(2) enters __nfs_revalidate_inode() which early-exits
    on a held directory delegation, returning the cached (stale) mtime
    without sending a GETATTR RPC.

The delegation early-exit unconditionally trusts cached attrs, but the
rename/create/unlink paths have already flagged some attrs as stale.
This patch keeps the early-exit for the fast path but takes the
RPC when CHANGE/MTIME/CTIME is already marked invalid.

Minimal reproducer (client):

  mount -t nfs -o vers=4.2 SERVER:/export /mnt/x
  cd /mnt/x
  rm -rf src dst && mkdir src dst && touch src/f
  stat -c 'src_before: %y' src
  sleep 3
  mv src/f dst/f
  stat -c 'src_after:  %y' src

Before: src_after == src_before (stale).
After:  src_after advances by the sleep interval.

Verification
------------

 - Loopback (client and server on the same Linux 7.0 host): test
   passes after the patch with default directory_delegations=Y.
 - Separate physical client (Linux 7.0 with the patch) against
   a Linux 7.0 server: test passes with default settings.
 - Disabling directory_delegations on the client (echo N >
   /sys/module/nfsv4/parameters/directory_delegations) is a known
   workaround that also makes the test pass -- which is what led to
   the diagnosis.  The patch removes the need for the workaround.

Reproduces against every NFSv4 server we tested (multiple Linux knfsd
versions, reffs, FreeBSD NFS) which is consistent with a client-only
bug.

Test that surfaced it
---------------------

nfs-conformance op_rename_nlink case_parent_timestamps:
https://github.com/loghyr/nfs-conformance/blob/main/op_rename_nlink.c

Alternative fixes considered
----------------------------

An alternative would be to call nfs_update_delegated_mtime_locked() on
the directory from the rename_done path, treating the client as
authoritative for the delegated mtime (similar to what the write path
does for files via nfs_update_mtime).  That's more invasive and only
addresses the rename path; the __nfs_revalidate_inode fix in this
patch is defense-in-depth for any code path that marks an attr stale
without taking the delegation back.

Happy to rework if you'd prefer the call-update-mtime shape instead,
or if the guard should live in a helper next to
nfs_have_directory_delegation().

Thanks,
Tom

Tom Haynes (1):
  nfs: don't skip revalidate on directory delegation when attrs flagged
    stale

 fs/nfs/inode.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

-- 
2.53.0


             reply	other threads:[~2026-04-18 19:03 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-18 19:03 Tom Haynes [this message]
2026-04-18 19:03 ` [PATCH 1/1] nfs: don't skip revalidate on directory delegation when attrs flagged stale Tom Haynes
2026-04-23 13:37   ` Anna Schumaker
2026-04-23 14:29     ` Thomas Haynes

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260418190301.3661-1-loghyr@gmail.com \
    --to=loghyr@gmail.com \
    --cc=anna@kernel.org \
    --cc=chuck.lever@oracle.com \
    --cc=jlayton@kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=trondmy@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox