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 2/6] nfs4.2: request UNCACHEABLE_FILE_DATA only for regular files
Date: Wed, 1 Jul 2026 16:43:33 -0400 [thread overview]
Message-ID: <20260701204337.54314-3-snitzer@kernel.org> (raw)
In-Reply-To: <20260701204337.54314-1-snitzer@kernel.org>
The UNCACHEABLE_FILE_DATA attribute applies only to regular files
(NF4REG); per draft-ietf-nfsv4-uncacheable-files a server MUST reject a
query of it on any other object type with NFS4ERR_INVAL. The previous
commit decodes and tracks the attribute but does not gate it: the bit
rides in the per-server attribute bitmask (server->attr_bitmask) and in
the generic getattr request bitmap (nfs4_fattr_bitmap), so it would be
requested for non-regular objects too -- e.g. a plain directory GETATTR,
a LOOKUP that resolves to a directory, or a CREATE (which only ever makes
non-regular objects). A strict server would fail those compounds.
Gate the client accordingly:
- Only set NFS_INO_INVALID_UNCACHEABLE_FILE_DATA on regular-file inodes,
so the attribute is never (re)requested for directories or other
non-regular objects via the delegation GETATTR or nfs4_bitmask_set()
refresh paths.
- Gate the request by object type at the single choke point
nfs4_bitmap_copy_adjust(), which clears
FATTR4_WORD2_UNCACHEABLE_FILE_DATA unless the target inode is a
regular file (a NULL inode -- unknown object type -- clears it too).
This already covers GETATTR, SETATTR and LINK; route LOOKUP, LOOKUPP
and CREATE through it as well.
The bit is kept in server->attr_bitmask (it is server-supported, and OPEN
still requests it via its regular-file-only open_bitmap), so no bespoke
per-data-file bitmask plumbing is needed. The remaining getattr-bearing
compounds are already safe: ACCESS, DELEGRETURN, WRITE, CLOSE and
LAYOUTCOMMIT use server->cache_consistency_bitmask (no word2 attributes)
or operate on regular files; READDIR does not encode the bit; and
LOOKUP_ROOT, FSINFO, STATFS and PATHCONF use fixed bitmaps without it.
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Assisted-by: Claude:claude-opus-4-8
---
fs/nfs/inode.c | 6 ++++--
fs/nfs/nfs4proc.c | 37 ++++++++++++++++++++++++++++++++++---
2 files changed, 38 insertions(+), 5 deletions(-)
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 68a1d97d9560..bb6e58123341 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -565,7 +565,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
if (fattr->valid & NFS_ATTR_FATTR_UNCACHEABLE_FILE_DATA)
nfsi->uncacheable_file_data =
fattr->aux_flags & NFS_AUX_UNCACHEABLE_FILE_DATA;
- else if (fattr_supported & NFS_ATTR_FATTR_UNCACHEABLE_FILE_DATA)
+ else if (S_ISREG(inode->i_mode) &&
+ (fattr_supported & NFS_ATTR_FATTR_UNCACHEABLE_FILE_DATA))
nfs_set_cache_invalid(inode, NFS_INO_INVALID_UNCACHEABLE_FILE_DATA);
nfs_setsecurity(inode, fattr);
@@ -2473,7 +2474,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (fattr->valid & NFS_ATTR_FATTR_UNCACHEABLE_FILE_DATA)
nfsi->uncacheable_file_data =
fattr->aux_flags & NFS_AUX_UNCACHEABLE_FILE_DATA;
- else if (fattr_supported & NFS_ATTR_FATTR_UNCACHEABLE_FILE_DATA)
+ else if (S_ISREG(inode->i_mode) &&
+ (fattr_supported & NFS_ATTR_FATTR_UNCACHEABLE_FILE_DATA))
nfsi->cache_validity |=
save_cache_validity & NFS_INO_INVALID_UNCACHEABLE_FILE_DATA;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ad03b8518c14..a0d088cd47ac 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -308,6 +308,15 @@ static void nfs4_bitmap_copy_adjust(__u32 *dst, const __u32 *src,
unsigned long cache_validity;
memcpy(dst, src, NFS4_BITMASK_SZ*sizeof(*dst));
+ /*
+ * The uncacheable_file_data attribute applies only to regular files
+ * (NF4REG); a server must reject a query of it on any other object
+ * type with NFS4ERR_INVAL. Never request it unless the target is
+ * known to be a regular file (callers with an unknown object type,
+ * e.g. LOOKUP, pass a NULL inode).
+ */
+ if (!inode || !S_ISREG(inode->i_mode))
+ dst[2] &= ~FATTR4_WORD2_UNCACHEABLE_FILE_DATA;
if (!inode || !nfs_have_read_or_write_delegation(inode))
return;
@@ -4598,6 +4607,7 @@ static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir,
.rpc_resp = &res,
};
unsigned short task_flags = 0;
+ __u32 bitmask[NFS4_BITMASK_SZ];
if (nfs_server_capable(dir, NFS_CAP_MOVEABLE))
task_flags = RPC_TASK_MOVEABLE;
@@ -4606,7 +4616,13 @@ static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir,
if (nfs_lookup_is_soft_revalidate(dentry))
task_flags |= RPC_TASK_TIMEOUT;
- args.bitmask = nfs4_bitmask(server, fattr->label);
+ /*
+ * The looked-up object's type is unknown here, so gate out the
+ * regular-file-only uncacheable_file_data attribute (NULL inode).
+ */
+ nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, fattr->label),
+ NULL, 0);
+ args.bitmask = bitmask;
nfs_fattr_init(fattr);
@@ -4720,13 +4736,20 @@ static int _nfs4_proc_lookupp(struct inode *inode,
.rpc_resp = &res,
};
unsigned short task_flags = 0;
+ __u32 bitmask[NFS4_BITMASK_SZ];
if (server->flags & NFS_MOUNT_SOFTREVAL)
task_flags |= RPC_TASK_TIMEOUT;
if (server->caps & NFS_CAP_MOVEABLE)
task_flags |= RPC_TASK_MOVEABLE;
- args.bitmask = nfs4_bitmask(server, fattr->label);
+ /*
+ * The looked-up object's type is unknown here, so gate out the
+ * regular-file-only uncacheable_file_data attribute (NULL inode).
+ */
+ nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, fattr->label),
+ NULL, 0);
+ args.bitmask = bitmask;
nfs_fattr_init(fattr);
nfs4_init_sequence(server->nfs_client, &args.seq_args, &res.seq_res, 0, 0);
@@ -5141,6 +5164,7 @@ struct nfs4_createdata {
struct nfs4_create_res res;
struct nfs_fh fh;
struct nfs_fattr fattr;
+ u32 bitmask[NFS4_BITMASK_SZ];
};
static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
@@ -5164,7 +5188,14 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
data->arg.name = name;
data->arg.attrs = sattr;
data->arg.ftype = ftype;
- data->arg.bitmask = nfs4_bitmask(server, data->fattr.label);
+ /*
+ * CREATE only makes non-regular objects, so gate out the
+ * regular-file-only uncacheable_file_data attribute (NULL inode).
+ */
+ nfs4_bitmap_copy_adjust(data->bitmask,
+ nfs4_bitmask(server, data->fattr.label),
+ NULL, 0);
+ data->arg.bitmask = data->bitmask;
data->arg.umask = current_umask();
data->res.server = server;
data->res.fh = &data->fh;
--
2.47.3
next 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 ` Mike Snitzer [this message]
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 ` [PATCH v3 6/6] nfs4.2: honor UNCACHEABLE_DIRENT_METADATA by refetching readdir Mike Snitzer
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-3-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox