[PATCH v4 5/6] nfs4.2: request UNCACHEABLE_DIRENT_METADATA only for directories
Mike Snitzer <[email protected]> Mon, 27 Jul 2026 17:09:42 -0400
| Newsgroups | org.kernel.vger.linux-nfs |
|---|---|
| Message-ID | <0949ae8eb880fe0fbe702fc1c3e5fbd70ec356da.1785140181.git.snitzer@kernel.org> |
The UNCACHEABLE_DIRENT_METADATA attribute (attr 88) applies only to directory objects (NF4DIR); per draft-ietf-nfsv4-uncacheable-directories a server must reject a query of it on any other object type with NFS4ERR_INVAL. Request it by object type at the single choke point nfs4_bitmap_copy_adjust(): add FATTR4_WORD2_UNCACHEABLE_DIRENT_METADATA for a directory target (gated on server->attr_bitmask, i.e. only when the server supports it) and strip it for any non-directory or unknown target (callers with an unknown object type, e.g. LOOKUP/LOOKUPP/CREATE, pass a NULL inode and are already routed through this helper). Crucially, attr 88 is NOT carried in the shared request bitmaps (nfs4_fattr_bitmap, nfs4_pnfs_open_bitmap). Those are used verbatim as the OPEN "open_bitmap" -- the GETATTR embedded in OPEN, which is masked only by the server's supported set and is not type-gated -- so a directory-only attribute placed there would be requested on every regular-file OPEN and draw NFS4ERR_INVAL. Adding it in copy_adjust instead keeps it off OPEN while still requesting it on directory GETATTRs. This differs from the companion NF4REG-only UNCACHEABLE_FILE_DATA attribute, which does ride the shared bitmaps: it is legal on the OPEN of a regular file (where it is wanted, to drive O_DIRECT), so copy_adjust merely strips it for non-regular targets. Net: a regular file requests file_data and never dirent_metadata, a directory requests dirent_metadata and never file_data, and an unknown/other object requests neither. The type gate runs before the helper's read/write (file) delegation handling and is the only adjustment the directory attribute needs: a directory cannot hold a file delegation, so the delegation-based suppression below it never applies. Link: https://datatracker.ietf.org/doc/draft-ietf-nfsv4-uncacheable-directories/ Signed-off-by: Mike Snitzer <[email protected]> Assisted-by: Claude:claude-opus-4-8 --- fs/nfs/nfs4proc.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 35156c54dac3..e4b4012d1f49 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -310,13 +310,26 @@ static void nfs4_bitmap_copy_adjust(__u32 *dst, const __u32 *src, 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). + * (NF4REG) and the uncacheable_dirent_metadata attribute only to + * directories (NF4DIR); a server must reject a query of either on any + * other object type with NFS4ERR_INVAL. Never request either unless + * the target is known to be of the matching type (callers with an + * unknown object type, e.g. LOOKUP, pass a NULL inode). + * + * uncacheable_file_data rides the shared request bitmaps (it is legal + * on the OPEN of a regular file, where it is wanted); strip it here for + * any non-regular target. uncacheable_dirent_metadata must NOT ride + * those bitmaps -- they are used verbatim by OPEN on regular files, + * where a directory-only attribute would draw NFS4ERR_INVAL -- so it is + * added here for directories only, gated on server support. */ if (!inode || !S_ISREG(inode->i_mode)) dst[2] &= ~FATTR4_WORD2_UNCACHEABLE_FILE_DATA; + if (inode && S_ISDIR(inode->i_mode)) + dst[2] |= NFS_SERVER(inode)->attr_bitmask[2] & + FATTR4_WORD2_UNCACHEABLE_DIRENT_METADATA; + else + dst[2] &= ~FATTR4_WORD2_UNCACHEABLE_DIRENT_METADATA; if (!inode || !nfs_have_read_or_write_delegation(inode)) return; -- 2.47.3