nfsd: track requested dir attributes

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 <jlayton@kernel.org>
Link: https://patch.msgid.link/20260616-dir-deleg-v7-19-6cbc7eac0ade@kernel.org
Signed-off-by: Chuck Lever <cel@kernel.org>
This commit is contained in:
Jeff Layton 2026-06-16 07:59:02 -04:00 committed by Chuck Lever
parent c21812da72
commit ac36b75864
3 changed files with 18 additions and 4 deletions

View File

@ -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

View File

@ -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;

View File

@ -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)