[PATCH v7 19/20] nfsd: track requested dir attributes
Jeff Layton <[email protected]>
| Newsgroups | gmane.linux.documentation,gmane.linux.kernel,gmane.linux.nfs |
|---|---|
| Message-ID | <[email protected]> |
Track the union of requested and supported dir attributes in the delegation. In a later patch this will be used to ensure that we only encode the attributes in that union when sending add/remove/rename updates. Since the requested dir attributes can now include word1 attributes, gddr_dir_attributes[1] may be non-zero and nfsd4_encode_bitmap4() can emit a two-word bitmap. Bump the dir-attribute bitmap budget in nfsd4_get_dir_delegation_rsize() from one word to two accordingly, so the reply-size check before this non-idempotent op accounts for the larger encoding. Signed-off-by: Jeff Layton <[email protected]> --- fs/nfsd/nfs4proc.c | 4 +++- fs/nfsd/nfs4state.c | 17 ++++++++++++++--- fs/nfsd/state.h | 1 + 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 576346578ee0..48fc7b0df4dc 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -2610,6 +2610,8 @@ nfsd4_get_dir_delegation(struct svc_rqst *rqstp, memcpy(&gdd->gddr_stateid, &dd->dl_stid.sc_stateid, sizeof(gdd->gddr_stateid)); gdd->gddr_child_attributes[0] = dd->dl_child_attrs[0]; gdd->gddr_child_attributes[1] = dd->dl_child_attrs[1]; + gdd->gddr_dir_attributes[0] = dd->dl_dir_attrs[0]; + gdd->gddr_dir_attributes[1] = dd->dl_dir_attrs[1]; nfs4_put_stid(&dd->dl_stid); return nfs_ok; } @@ -3577,7 +3579,7 @@ static u32 nfsd4_get_dir_delegation_rsize(const struct svc_rqst *rqstp, op_encode_stateid_maxsz + 2 /* gddr_notification */ + 3 /* gddr_child_attributes */ + - 2 /* gddr_dir_attributes */) * sizeof(__be32); + 3 /* gddr_dir_attributes */) * sizeof(__be32); } #ifdef CONFIG_NFSD_PNFS diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index c4dc0428f0a6..a948dc8a46cc 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -9974,6 +9974,15 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct dentry *dentry, FATTR4_WORD1_TIME_MODIFY | \ FATTR4_WORD1_TIME_CREATE) +#define GDD_WORD0_DIR_ATTRS (FATTR4_WORD0_CHANGE | \ + FATTR4_WORD0_SIZE) + +#define GDD_WORD1_DIR_ATTRS (FATTR4_WORD1_NUMLINKS | \ + FATTR4_WORD1_SPACE_USED | \ + FATTR4_WORD1_TIME_ACCESS | \ + FATTR4_WORD1_TIME_METADATA | \ + FATTR4_WORD1_TIME_MODIFY) + /** * nfsd_get_dir_deleg - attempt to get a directory delegation * @cstate: compound state @@ -10042,14 +10051,16 @@ nfsd_get_dir_deleg(struct nfsd4_compound_state *cstate, dp->dl_stid.sc_export = exp_get(cstate->current_fh.fh_export); - dp->dl_child_attrs[0] = gdd->gdda_child_attributes[0] & GDD_WORD0_CHILD_ATTRS; - dp->dl_child_attrs[1] = gdd->gdda_child_attributes[1] & GDD_WORD1_CHILD_ATTRS; - /* * NB: gddr_notification[0] represents the notifications that * will be granted to the client */ dp->dl_notify_mask = gdd->gddr_notification[0]; + dp->dl_child_attrs[0] = gdd->gdda_child_attributes[0] & GDD_WORD0_CHILD_ATTRS; + dp->dl_child_attrs[1] = gdd->gdda_child_attributes[1] & GDD_WORD1_CHILD_ATTRS; + dp->dl_dir_attrs[0] = gdd->gdda_dir_attributes[0] & GDD_WORD0_DIR_ATTRS; + dp->dl_dir_attrs[1] = gdd->gdda_dir_attributes[1] & GDD_WORD1_DIR_ATTRS; + fl = nfs4_alloc_init_lease(dp, dp->dl_notify_mask); if (!fl) goto out_put_stid; diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 2bc54546deb3..bc0181ef1cb6 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -301,6 +301,7 @@ struct nfs4_delegation { /* For dir delegations */ u32 dl_notify_mask; u32 dl_child_attrs[2]; + u32 dl_dir_attrs[2]; }; static inline bool deleg_is_read(u32 dl_type) -- 2.54.0