From: Mike Snitzer <snitzer@hammerspace.com>
To: Trond Myklebust <trondmy@kernel.org>, Anna Schumaker <anna@kernel.org>
Cc: Tom Haynes <loghyr@hammerspace.com>, Chuck Lever <cel@kernel.org>,
linux-nfs@vger.kernel.org
Subject: [PATCH v3 6/6] nfs4.2: honor UNCACHEABLE_DIRENT_METADATA by refetching readdir
Date: Wed, 1 Jul 2026 16:43:37 -0400 [thread overview]
Message-ID: <20260701204337.54314-7-snitzer@kernel.org> (raw)
In-Reply-To: <20260701204337.54314-1-snitzer@kernel.org>
Honor the per-directory UNCACHEABLE_DIRENT_METADATA attribute: when a
directory is marked uncacheable, nfs_readdir() bypasses the readdir page
cache and refetches directory-entry metadata from the server on every
readdir, satisfying the always-refetch semantics the attribute requires
(draft-ietf-nfsv4-uncacheable-directories Section 5.1).
Rather than searching the cached readdir folios, nfs_readdir() forces the
-EBADCOOKIE path so the request is served by uncached_readdir(); the
dir_cookie == 0 (start-of-directory) case is included so the very first
readdir of an uncacheable directory also goes to the server. A
tracepoint records when an uncacheable directory bypasses the cache.
The metadata the attribute governs is the per-entry size and timestamps,
which are carried only by READDIRPLUS (a plain READDIR refreshes names
but leaves the entries' attributes to the inode attribute caches). So
also force READDIRPLUS for an uncacheable directory (when the server is
capable): nfs_use_readdirplus() otherwise enables it only at the start of
the directory or once cache usage crosses a threshold, and the cache-
bypassing path above never accrues that usage -- which would leave
continuation READDIRs of a large directory refreshing names but serving
stale per-entry attributes. Forcing READDIRPLUS makes each READDIR
refresh the entries' attribute caches (via nfs_prime_dcache() ->
nfs_refresh_inode()), so a subsequent stat() observes current values.
The attribute does not change NFSv4.2 change-attribute semantics: the
client continues to use the directory change attribute for validation;
this only suppresses serving READDIR responses from the local cache.
See: https://datatracker.ietf.org/doc/draft-ietf-nfsv4-uncacheable-directories/
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Assisted-by: Claude:claude-opus-4-8
---
fs/nfs/dir.c | 18 ++++++++++++++++--
fs/nfs/nfstrace.h | 1 +
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 6b07abf272b1..2162e93992c2 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -667,6 +667,14 @@ static bool nfs_use_readdirplus(struct inode *dir, struct dir_context *ctx,
return false;
if (NFS_SERVER(dir)->flags & NFS_MOUNT_FORCE_RDIRPLUS)
return true;
+ /*
+ * An uncacheable directory must refetch directory-entry metadata
+ * (including per-entry size and timestamps) from the server on each
+ * READDIR; force READDIRPLUS so those attributes are refreshed on
+ * every call rather than left stale in the inode attribute caches.
+ */
+ if (NFS_I(dir)->uncacheable_dirent_metadata)
+ return true;
if (ctx->pos == 0 ||
cache_hits + cache_misses > NFS_READDIR_CACHE_USAGE_THRESHOLD)
return true;
@@ -1274,12 +1282,18 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
desc->clear_cache = force_clear;
do {
- res = readdir_search_pagecache(desc);
+ if (nfsi->uncacheable_dirent_metadata) {
+ res = -EBADCOOKIE;
+ trace_nfs_readdir_uncacheable_directory(inode);
+ } else {
+ res = readdir_search_pagecache(desc);
+ }
if (res == -EBADCOOKIE) {
res = 0;
/* This means either end of directory */
- if (desc->dir_cookie && !desc->eof) {
+ if ((desc->dir_cookie || nfsi->uncacheable_dirent_metadata) &&
+ !desc->eof) {
/* Or that the server has 'lost' a cookie */
res = uncached_readdir(desc);
if (res == 0)
diff --git a/fs/nfs/nfstrace.h b/fs/nfs/nfstrace.h
index b15c1732c869..a9930d59c610 100644
--- a/fs/nfs/nfstrace.h
+++ b/fs/nfs/nfstrace.h
@@ -181,6 +181,7 @@ DEFINE_NFS_INODE_EVENT_DONE(nfs_fsync_exit);
DEFINE_NFS_INODE_EVENT(nfs_access_enter);
DEFINE_NFS_INODE_EVENT_DONE(nfs_set_cache_invalid);
DEFINE_NFS_INODE_EVENT(nfs_readdir_force_readdirplus);
+DEFINE_NFS_INODE_EVENT(nfs_readdir_uncacheable_directory);
DEFINE_NFS_INODE_EVENT_DONE(nfs_readdir_cache_fill_done);
DEFINE_NFS_INODE_EVENT_DONE(nfs_readdir_uncached_done);
--
2.47.3
prev parent reply other threads:[~2026-07-01 20:43 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-01 20:43 [PATCH v3 0/6] nfs: NFSv4.2 client support for UNCACHEABLE_FILE_DATA and UNCACHEABLE_DIRENT_METADATA Mike Snitzer
2026-07-01 20:43 ` [PATCH v3 1/6] nfs4.2: add UNCACHEABLE_FILE_DATA attribute support Mike Snitzer
2026-07-01 20:43 ` [PATCH v3 2/6] nfs4.2: request UNCACHEABLE_FILE_DATA only for regular files Mike Snitzer
2026-07-01 20:43 ` [PATCH v3 3/6] nfs4.2: open UNCACHEABLE_FILE_DATA files with O_DIRECT Mike Snitzer
2026-07-01 20:43 ` [PATCH v3 4/6] nfs4.2: add UNCACHEABLE_DIRENT_METADATA attribute support Mike Snitzer
2026-07-01 20:43 ` [PATCH v3 5/6] nfs4.2: request UNCACHEABLE_DIRENT_METADATA only for directories Mike Snitzer
2026-07-01 20:43 ` Mike Snitzer [this message]
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=20260701204337.54314-7-snitzer@kernel.org \
--to=snitzer@hammerspace.com \
--cc=anna@kernel.org \
--cc=cel@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=loghyr@hammerspace.com \
--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 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.