Re: [PATCH v6 18/20] nfsd: properly track requested child attributes

"Chuck Lever" <[email protected]>
Newsgroups gmane.linux.documentation,gmane.linux.kernel,gmane.linux.nfs
Message-ID <[email protected]>

On Thu, Jun 11, 2026, at 1:50 PM, Jeff Layton wrote:
> Track the union of requested and supported child attributes in the
> delegation, and only encode the attributes in that union when sending
> add/remove/rename updates.
>
> Signed-off-by: Jeff Layton <[email protected]>
> ---
>  fs/nfsd/nfs4proc.c  |  2 ++
>  fs/nfsd/nfs4state.c | 18 ++++++++++++++++++
>  fs/nfsd/nfs4xdr.c   | 15 ++++++---------
>  fs/nfsd/state.h     |  3 +++
>  4 files changed, 29 insertions(+), 9 deletions(-)
>
> diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
> index 29f7339dc220..caec82e77081 100644
> --- a/fs/nfsd/nfs4proc.c
> +++ b/fs/nfsd/nfs4proc.c
> @@ -2577,6 +2577,8 @@ nfsd4_get_dir_delegation(struct svc_rqst *rqstp,
> 
>  	gdd->gddrnf_status = GDD4_OK;
>  	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];
>  	nfs4_put_stid(&dd->dl_stid);
>  	return nfs_ok;
>  }
> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index aa99783ce901..0e6e008c121e 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c
> @@ -9930,6 +9930,21 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst 
> *rqstp, struct dentry *dentry,
>  	return status;
>  }
> 
> +#define GDD_WORD0_CHILD_ATTRS	(FATTR4_WORD0_TYPE |		\
> +				 FATTR4_WORD0_CHANGE |		\
> +				 FATTR4_WORD0_SIZE |		\
> +				 FATTR4_WORD0_FILEID |		\
> +				 FATTR4_WORD0_FILEHANDLE)
> +
> +#define GDD_WORD1_CHILD_ATTRS	(FATTR4_WORD1_MODE |		\
> +				 FATTR4_WORD1_NUMLINKS |	\
> +				 FATTR4_WORD1_RAWDEV |		\
> +				 FATTR4_WORD1_SPACE_USED |	\
> +				 FATTR4_WORD1_TIME_ACCESS |	\
> +				 FATTR4_WORD1_TIME_METADATA |	\
> +				 FATTR4_WORD1_TIME_MODIFY |	\
> +				 FATTR4_WORD1_TIME_CREATE)
> +
>  /**
>   * nfsd_get_dir_deleg - attempt to get a directory delegation
>   * @cstate: compound state
> @@ -9998,6 +10013,9 @@ 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
> diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
> index 15ccd54ffdb6..1e3c360c06cd 100644
> --- a/fs/nfsd/nfs4xdr.c
> +++ b/fs/nfsd/nfs4xdr.c
> @@ -4271,18 +4271,15 @@ nfsd4_setup_notify_entry4(struct notify_entry4 
> *ne, struct xdr_stream *xdr,
> 
>  	args.change_attr = nfsd4_change_attribute(&args.stat);
> 
> -	attrmask[0] = FATTR4_WORD0_TYPE | FATTR4_WORD0_CHANGE |
> -		      FATTR4_WORD0_SIZE | FATTR4_WORD0_FILEID;
> -	attrmask[1] = FATTR4_WORD1_MODE | FATTR4_WORD1_NUMLINKS | 
> FATTR4_WORD1_RAWDEV |
> -		      FATTR4_WORD1_SPACE_USED | FATTR4_WORD1_TIME_ACCESS |
> -		      FATTR4_WORD1_TIME_METADATA | FATTR4_WORD1_TIME_MODIFY;
> +	attrmask[0] = dp->dl_child_attrs[0];
> +	attrmask[1] = dp->dl_child_attrs[1];
>  	attrmask[2] = 0;
> 
> -	if (setup_notify_fhandle(dentry, fi, nf, &args))
> -		attrmask[0] |= FATTR4_WORD0_FILEHANDLE;
> +	if (!setup_notify_fhandle(dentry, fi, nf, &args))
> +		attrmask[0] &= ~FATTR4_WORD0_FILEHANDLE;
> 
> -	if (args.stat.result_mask & STATX_BTIME)
> -		attrmask[1] |= FATTR4_WORD1_TIME_CREATE;
> +	if (!(args.stat.result_mask & STATX_BTIME))
> +		attrmask[1] &= ~FATTR4_WORD1_TIME_CREATE;
> 
>  	ne->ne_attrs.attrmask.count = 2;
>  	ne->ne_attrs.attr_vals.data = (u8 *)xdr->p;
> diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
> index d912e3d04dd7..0763893bfd48 100644
> --- a/fs/nfsd/state.h
> +++ b/fs/nfsd/state.h
> @@ -297,6 +297,9 @@ struct nfs4_delegation {
>  	struct timespec64	dl_atime;
>  	struct timespec64	dl_mtime;
>  	struct timespec64	dl_ctime;
> +
> +	/* For dir delegations */
> +	uint32_t		dl_child_attrs[2];
>  };
> 
>  static inline bool deleg_is_read(u32 dl_type)
>

When a client requests any supported child attribute in word 1, this can
make gddr_child_attributes[1] non-zero, so nfsd4_encode_bitmap4() emits a
two-word bitmap. nfsd4_get_dir_delegation_rsize() still budgets only the
old one-word child-attribute bitmap before executing this non-idempotent
op, so a compound near the reply/slot limit can grant a directory
delegation and then fail encoding with NFS4ERR_RESOURCE/REP_TOO_BIG,
leaving the client without the returned stateid.


-- 
Chuck Lever
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.