Commit 332d1a03 authored by Trond Myklebust's avatar Trond Myklebust

NFS: nfs4_bitmask_adjust() must not change the server global bitmasks

As currently set, the calls to nfs4_bitmask_adjust() will end up
overwriting the contents of the nfs_server cache_consistency_bitmask
field.
The intention here should be to modify a private copy of that mask in
the close/delegreturn/write arguments.

Fixes: 76bd5c01 ("NFSv4: make cache consistency bitmask dynamic")
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent beab450d
...@@ -108,9 +108,10 @@ static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *, ...@@ -108,9 +108,10 @@ static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *,
static int nfs41_free_stateid(struct nfs_server *, const nfs4_stateid *, static int nfs41_free_stateid(struct nfs_server *, const nfs4_stateid *,
const struct cred *, bool); const struct cred *, bool);
#endif #endif
static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode, static void nfs4_bitmask_set(__u32 bitmask[NFS4_BITMASK_SZ],
struct nfs_server *server, const __u32 *src, struct inode *inode,
struct nfs4_label *label); struct nfs_server *server,
struct nfs4_label *label);
#ifdef CONFIG_NFS_V4_SECURITY_LABEL #ifdef CONFIG_NFS_V4_SECURITY_LABEL
static inline struct nfs4_label * static inline struct nfs4_label *
...@@ -3591,6 +3592,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) ...@@ -3591,6 +3592,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
struct nfs4_closedata *calldata = data; struct nfs4_closedata *calldata = data;
struct nfs4_state *state = calldata->state; struct nfs4_state *state = calldata->state;
struct inode *inode = calldata->inode; struct inode *inode = calldata->inode;
struct nfs_server *server = NFS_SERVER(inode);
struct pnfs_layout_hdr *lo; struct pnfs_layout_hdr *lo;
bool is_rdonly, is_wronly, is_rdwr; bool is_rdonly, is_wronly, is_rdwr;
int call_close = 0; int call_close = 0;
...@@ -3647,8 +3649,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) ...@@ -3647,8 +3649,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
if (calldata->arg.fmode == 0 || calldata->arg.fmode == FMODE_READ) { if (calldata->arg.fmode == 0 || calldata->arg.fmode == FMODE_READ) {
/* Close-to-open cache consistency revalidation */ /* Close-to-open cache consistency revalidation */
if (!nfs4_have_delegation(inode, FMODE_READ)) { if (!nfs4_have_delegation(inode, FMODE_READ)) {
calldata->arg.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask; nfs4_bitmask_set(calldata->arg.bitmask_store,
nfs4_bitmask_adjust(calldata->arg.bitmask, inode, NFS_SERVER(inode), NULL); server->cache_consistency_bitmask,
inode, server, NULL);
calldata->arg.bitmask = calldata->arg.bitmask_store;
} else } else
calldata->arg.bitmask = NULL; calldata->arg.bitmask = NULL;
} }
...@@ -5416,19 +5420,17 @@ bool nfs4_write_need_cache_consistency_data(struct nfs_pgio_header *hdr) ...@@ -5416,19 +5420,17 @@ bool nfs4_write_need_cache_consistency_data(struct nfs_pgio_header *hdr)
return nfs4_have_delegation(hdr->inode, FMODE_READ) == 0; return nfs4_have_delegation(hdr->inode, FMODE_READ) == 0;
} }
static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode, static void nfs4_bitmask_set(__u32 bitmask[NFS4_BITMASK_SZ], const __u32 *src,
struct nfs_server *server, struct inode *inode, struct nfs_server *server,
struct nfs4_label *label) struct nfs4_label *label)
{ {
unsigned long cache_validity = READ_ONCE(NFS_I(inode)->cache_validity); unsigned long cache_validity = READ_ONCE(NFS_I(inode)->cache_validity);
unsigned int i;
if ((cache_validity & NFS_INO_INVALID_DATA) || memcpy(bitmask, src, sizeof(*bitmask) * NFS4_BITMASK_SZ);
(cache_validity & NFS_INO_REVAL_PAGECACHE) ||
(cache_validity & NFS_INO_REVAL_FORCED) ||
(cache_validity & NFS_INO_INVALID_OTHER))
nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, label), inode);
if (cache_validity & (NFS_INO_INVALID_CHANGE | NFS_INO_REVAL_PAGECACHE))
bitmask[0] |= FATTR4_WORD0_CHANGE;
if (cache_validity & NFS_INO_INVALID_ATIME) if (cache_validity & NFS_INO_INVALID_ATIME)
bitmask[1] |= FATTR4_WORD1_TIME_ACCESS; bitmask[1] |= FATTR4_WORD1_TIME_ACCESS;
if (cache_validity & NFS_INO_INVALID_OTHER) if (cache_validity & NFS_INO_INVALID_OTHER)
...@@ -5437,16 +5439,22 @@ static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode, ...@@ -5437,16 +5439,22 @@ static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode,
FATTR4_WORD1_NUMLINKS; FATTR4_WORD1_NUMLINKS;
if (label && label->len && cache_validity & NFS_INO_INVALID_LABEL) if (label && label->len && cache_validity & NFS_INO_INVALID_LABEL)
bitmask[2] |= FATTR4_WORD2_SECURITY_LABEL; bitmask[2] |= FATTR4_WORD2_SECURITY_LABEL;
if (cache_validity & NFS_INO_INVALID_CHANGE)
bitmask[0] |= FATTR4_WORD0_CHANGE;
if (cache_validity & NFS_INO_INVALID_CTIME) if (cache_validity & NFS_INO_INVALID_CTIME)
bitmask[1] |= FATTR4_WORD1_TIME_METADATA; bitmask[1] |= FATTR4_WORD1_TIME_METADATA;
if (cache_validity & NFS_INO_INVALID_MTIME) if (cache_validity & NFS_INO_INVALID_MTIME)
bitmask[1] |= FATTR4_WORD1_TIME_MODIFY; bitmask[1] |= FATTR4_WORD1_TIME_MODIFY;
if (cache_validity & NFS_INO_INVALID_SIZE)
bitmask[0] |= FATTR4_WORD0_SIZE;
if (cache_validity & NFS_INO_INVALID_BLOCKS) if (cache_validity & NFS_INO_INVALID_BLOCKS)
bitmask[1] |= FATTR4_WORD1_SPACE_USED; bitmask[1] |= FATTR4_WORD1_SPACE_USED;
if (nfs4_have_delegation(inode, FMODE_READ) &&
!(cache_validity & NFS_INO_REVAL_FORCED))
bitmask[0] &= ~FATTR4_WORD0_SIZE;
else if (cache_validity &
(NFS_INO_INVALID_SIZE | NFS_INO_REVAL_PAGECACHE))
bitmask[0] |= FATTR4_WORD0_SIZE;
for (i = 0; i < NFS4_BITMASK_SZ; i++)
bitmask[i] &= server->attr_bitmask[i];
} }
static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr, static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
...@@ -5459,8 +5467,10 @@ static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr, ...@@ -5459,8 +5467,10 @@ static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
hdr->args.bitmask = NULL; hdr->args.bitmask = NULL;
hdr->res.fattr = NULL; hdr->res.fattr = NULL;
} else { } else {
hdr->args.bitmask = server->cache_consistency_bitmask; nfs4_bitmask_set(hdr->args.bitmask_store,
nfs4_bitmask_adjust(hdr->args.bitmask, hdr->inode, server, NULL); server->cache_consistency_bitmask,
hdr->inode, server, NULL);
hdr->args.bitmask = hdr->args.bitmask_store;
} }
if (!hdr->pgio_done_cb) if (!hdr->pgio_done_cb)
...@@ -6502,8 +6512,10 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred, ...@@ -6502,8 +6512,10 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
data->args.fhandle = &data->fh; data->args.fhandle = &data->fh;
data->args.stateid = &data->stateid; data->args.stateid = &data->stateid;
data->args.bitmask = server->cache_consistency_bitmask; nfs4_bitmask_set(data->args.bitmask_store,
nfs4_bitmask_adjust(data->args.bitmask, inode, server, NULL); server->cache_consistency_bitmask, inode, server,
NULL);
data->args.bitmask = data->args.bitmask_store;
nfs_copy_fh(&data->fh, NFS_FH(inode)); nfs_copy_fh(&data->fh, NFS_FH(inode));
nfs4_stateid_copy(&data->stateid, stateid); nfs4_stateid_copy(&data->stateid, stateid);
data->res.fattr = &data->fattr; data->res.fattr = &data->fattr;
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#define NFS_DEF_FILE_IO_SIZE (4096U) #define NFS_DEF_FILE_IO_SIZE (4096U)
#define NFS_MIN_FILE_IO_SIZE (1024U) #define NFS_MIN_FILE_IO_SIZE (1024U)
#define NFS_BITMASK_SZ 3
struct nfs4_string { struct nfs4_string {
unsigned int len; unsigned int len;
char *data; char *data;
...@@ -525,7 +527,8 @@ struct nfs_closeargs { ...@@ -525,7 +527,8 @@ struct nfs_closeargs {
struct nfs_seqid * seqid; struct nfs_seqid * seqid;
fmode_t fmode; fmode_t fmode;
u32 share_access; u32 share_access;
u32 * bitmask; const u32 * bitmask;
u32 bitmask_store[NFS_BITMASK_SZ];
struct nfs4_layoutreturn_args *lr_args; struct nfs4_layoutreturn_args *lr_args;
}; };
...@@ -608,7 +611,8 @@ struct nfs4_delegreturnargs { ...@@ -608,7 +611,8 @@ struct nfs4_delegreturnargs {
struct nfs4_sequence_args seq_args; struct nfs4_sequence_args seq_args;
const struct nfs_fh *fhandle; const struct nfs_fh *fhandle;
const nfs4_stateid *stateid; const nfs4_stateid *stateid;
u32 * bitmask; const u32 *bitmask;
u32 bitmask_store[NFS_BITMASK_SZ];
struct nfs4_layoutreturn_args *lr_args; struct nfs4_layoutreturn_args *lr_args;
}; };
...@@ -648,7 +652,8 @@ struct nfs_pgio_args { ...@@ -648,7 +652,8 @@ struct nfs_pgio_args {
union { union {
unsigned int replen; /* used by read */ unsigned int replen; /* used by read */
struct { struct {
u32 * bitmask; /* used by write */ const u32 * bitmask; /* used by write */
u32 bitmask_store[NFS_BITMASK_SZ]; /* used by write */
enum nfs3_stable_how stable; /* used by write */ enum nfs3_stable_how stable; /* used by write */
}; };
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment