Commit 76bd5c01 authored by Olga Kornievskaia's avatar Olga Kornievskaia Committed by Anna Schumaker

NFSv4: make cache consistency bitmask dynamic

Client uses static bitmask for GETATTR on CLOSE/WRITE/DELEGRETURN
and ignores the fact that it might have some attributes marked
invalid in its cache. Compared to v3 where all attributes are
retrieved in postop attributes, v4's cache is frequently out of
sync and leads to standalone GETATTRs being sent to the server.

Instead, in addition to the minimum cache consistency attributes
also check cache_validity and adjust the GETATTR request accordingly.
Signed-off-by: default avatarOlga Kornievskaia <kolga@netapp.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 9f266451
...@@ -107,6 +107,9 @@ static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *, ...@@ -107,6 +107,9 @@ 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,
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 *
...@@ -3632,9 +3635,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) ...@@ -3632,9 +3635,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; calldata->arg.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask;
else nfs4_bitmask_adjust(calldata->arg.bitmask, inode, NFS_SERVER(inode), NULL);
} else
calldata->arg.bitmask = NULL; calldata->arg.bitmask = NULL;
} }
...@@ -5360,6 +5364,38 @@ bool nfs4_write_need_cache_consistency_data(struct nfs_pgio_header *hdr) ...@@ -5360,6 +5364,38 @@ 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,
struct nfs_server *server,
struct nfs4_label *label)
{
unsigned long cache_validity = READ_ONCE(NFS_I(inode)->cache_validity);
if ((cache_validity & NFS_INO_INVALID_DATA) ||
(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_ATIME)
bitmask[1] |= FATTR4_WORD1_TIME_ACCESS;
if (cache_validity & NFS_INO_INVALID_ACCESS)
bitmask[0] |= FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER |
FATTR4_WORD1_OWNER_GROUP;
if (cache_validity & NFS_INO_INVALID_ACL)
bitmask[0] |= FATTR4_WORD0_ACL;
if (cache_validity & NFS_INO_INVALID_LABEL)
bitmask[2] |= FATTR4_WORD2_SECURITY_LABEL;
if (cache_validity & NFS_INO_INVALID_CTIME)
bitmask[0] |= FATTR4_WORD0_CHANGE;
if (cache_validity & NFS_INO_INVALID_MTIME)
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)
bitmask[1] |= FATTR4_WORD1_SPACE_USED;
}
static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr, static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
struct rpc_message *msg, struct rpc_message *msg,
struct rpc_clnt **clnt) struct rpc_clnt **clnt)
...@@ -5369,8 +5405,10 @@ static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr, ...@@ -5369,8 +5405,10 @@ static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
if (!nfs4_write_need_cache_consistency_data(hdr)) { if (!nfs4_write_need_cache_consistency_data(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; hdr->args.bitmask = server->cache_consistency_bitmask;
nfs4_bitmask_adjust(hdr->args.bitmask, hdr->inode, server, NULL);
}
if (!hdr->pgio_done_cb) if (!hdr->pgio_done_cb)
hdr->pgio_done_cb = nfs4_write_done_cb; hdr->pgio_done_cb = nfs4_write_done_cb;
...@@ -6406,6 +6444,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred, ...@@ -6406,6 +6444,7 @@ 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; data->args.bitmask = server->cache_consistency_bitmask;
nfs4_bitmask_adjust(data->args.bitmask, inode, server, NULL);
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;
......
...@@ -525,7 +525,7 @@ struct nfs_closeargs { ...@@ -525,7 +525,7 @@ struct nfs_closeargs {
struct nfs_seqid * seqid; struct nfs_seqid * seqid;
fmode_t fmode; fmode_t fmode;
u32 share_access; u32 share_access;
const u32 * bitmask; u32 * bitmask;
struct nfs4_layoutreturn_args *lr_args; struct nfs4_layoutreturn_args *lr_args;
}; };
...@@ -608,7 +608,7 @@ struct nfs4_delegreturnargs { ...@@ -608,7 +608,7 @@ 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;
const u32 * bitmask; u32 * bitmask;
struct nfs4_layoutreturn_args *lr_args; struct nfs4_layoutreturn_args *lr_args;
}; };
...@@ -648,7 +648,7 @@ struct nfs_pgio_args { ...@@ -648,7 +648,7 @@ struct nfs_pgio_args {
union { union {
unsigned int replen; /* used by read */ unsigned int replen; /* used by read */
struct { struct {
const u32 * bitmask; /* used by write */ u32 * bitmask; /* 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