mirror of
https://github.com/torvalds/linux.git
synced 2026-09-14 16:10:02 +02:00
nfs4.2: request UNCACHEABLE_FILE_DATA only for regular files
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. In particular, drop it from nfs4_update_changeattr_locked()'s force-revalidation aggregation: that helper only ever runs on directory inodes (its callers update a directory's change information after OPEN-create, REMOVE, RENAME and LINK), so it was setting the file-only bit on directories. - Gate the request by object type at the 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. - Type-gate nfs4_bitmask_set(), which translates NFS_INO_INVALID_UNCACHEABLE_FILE_DATA into a request for attr 87 in the getattr attached to WRITE, CLOSE and DELEGRETURN. WRITE and CLOSE only ever pass regular files, but DELEGRETURN passes whatever object held the delegation -- with directory delegation support that includes directories -- so request attr 87 there only for S_ISREG inodes. 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 and LAYOUTCOMMIT use server->cache_consistency_bitmask (no word2 attributes); 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 Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
This commit is contained in:
parent
86ff184279
commit
6f36ce3098
|
|
@ -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);
|
||||
|
|
@ -2471,7 +2472,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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
@ -1243,7 +1252,7 @@ nfs4_update_changeattr_locked(struct inode *inode,
|
|||
NFS_INO_INVALID_SIZE | NFS_INO_INVALID_OTHER |
|
||||
NFS_INO_INVALID_BLOCKS | NFS_INO_INVALID_NLINK |
|
||||
NFS_INO_INVALID_MODE | NFS_INO_INVALID_BTIME |
|
||||
NFS_INO_INVALID_XATTR | NFS_INO_INVALID_UNCACHEABLE_FILE_DATA;
|
||||
NFS_INO_INVALID_XATTR;
|
||||
nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
|
||||
}
|
||||
nfsi->attrtimeo_timestamp = jiffies;
|
||||
|
|
@ -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;
|
||||
|
|
@ -5816,7 +5847,12 @@ void nfs4_bitmask_set(__u32 bitmask[], const __u32 src[],
|
|||
bitmask[1] |= FATTR4_WORD1_SPACE_USED;
|
||||
if (cache_validity & NFS_INO_INVALID_BTIME)
|
||||
bitmask[1] |= FATTR4_WORD1_TIME_CREATE;
|
||||
if (cache_validity & NFS_INO_INVALID_UNCACHEABLE_FILE_DATA)
|
||||
/*
|
||||
* uncacheable_file_data (attr 87) applies only to regular files; a
|
||||
* directory can reach here via DELEGRETURN of a directory delegation.
|
||||
*/
|
||||
if ((cache_validity & NFS_INO_INVALID_UNCACHEABLE_FILE_DATA) &&
|
||||
S_ISREG(inode->i_mode))
|
||||
bitmask[2] |= FATTR4_WORD2_UNCACHEABLE_FILE_DATA;
|
||||
|
||||
if (cache_validity & NFS_INO_INVALID_SIZE)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user