[PATCH v4 13/21] nfsd: add helper to marshal a fattr4 from completed args

From: Jeff Layton

Date: Fri May 22 2026 - 08:38:25 EST


Break the loop that encodes the actual attr_vals field into a separate
function.

Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
---
fs/nfsd/nfs4xdr.c | 44 +++++++++++++++++++++++++-------------------
1 file changed, 25 insertions(+), 19 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 31df04675713..703caa2ee7dc 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -3882,6 +3882,22 @@ static const nfsd4_enc_attr nfsd4_enc_fattr4_encode_ops[] = {
#endif
};

+static __be32
+nfsd4_encode_attr_vals(struct xdr_stream *xdr, u32 *attrmask, struct nfsd4_fattr_args *args)
+{
+ DECLARE_BITMAP(attr_bitmap, ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops));
+ unsigned long bit;
+ __be32 status;
+
+ bitmap_from_arr32(attr_bitmap, attrmask, ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops));
+ for_each_set_bit(bit, attr_bitmap, ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops)) {
+ status = nfsd4_enc_fattr4_encode_ops[bit](xdr, args);
+ if (status != nfs_ok)
+ return status;
+ }
+ return nfs_ok;
+}
+
/*
* Note: @fhp can be NULL; in this case, we might have to compose the filehandle
* ourselves. @case_cache is NULL for callers that encode a single dentry
@@ -3895,7 +3911,6 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
int ignore_crossmnt,
struct nfsd_case_attrs_cache *case_cache)
{
- DECLARE_BITMAP(attr_bitmap, ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops));
struct nfs4_delegation *dp = NULL;
struct nfsd4_fattr_args args;
struct svc_fh *tempfh = NULL;
@@ -3910,7 +3925,6 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
.mnt = exp->ex_path.mnt,
.dentry = dentry,
};
- unsigned long bit;

WARN_ON_ONCE(bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1);
WARN_ON_ONCE(!nfsd_attrs_supported(minorversion, bmval));
@@ -4124,27 +4138,22 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
#endif /* CONFIG_NFSD_V4_POSIX_ACLS */

/* attrmask */
- status = nfsd4_encode_bitmap4(xdr, attrmask[0], attrmask[1],
- attrmask[2]);
+ status = nfsd4_encode_bitmap4(xdr, attrmask[0], attrmask[1], attrmask[2]);
if (status)
goto out;

/* attr_vals */
attrlen_offset = xdr->buf->len;
- if (unlikely(!xdr_reserve_space(xdr, XDR_UNIT)))
- goto out_resource;
- bitmap_from_arr32(attr_bitmap, attrmask,
- ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops));
- for_each_set_bit(bit, attr_bitmap,
- ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops)) {
- status = nfsd4_enc_fattr4_encode_ops[bit](xdr, &args);
- if (status != nfs_ok)
- goto out;
+ if (unlikely(!xdr_reserve_space(xdr, XDR_UNIT))) {
+ status = nfserr_resource;
+ goto out;
}
- attrlen = cpu_to_be32(xdr->buf->len - attrlen_offset - XDR_UNIT);
- write_bytes_to_xdr_buf(xdr->buf, attrlen_offset, &attrlen, XDR_UNIT);
- status = nfs_ok;

+ status = nfsd4_encode_attr_vals(xdr, attrmask, &args);
+ if (status == nfs_ok) {
+ attrlen = cpu_to_be32(xdr->buf->len - attrlen_offset - XDR_UNIT);
+ write_bytes_to_xdr_buf(xdr->buf, attrlen_offset, &attrlen, XDR_UNIT);
+ }
out:
#ifdef CONFIG_NFSD_V4_POSIX_ACLS
if (args.dpacl)
@@ -4167,9 +4176,6 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
out_nfserr:
status = nfserrno(err);
goto out;
-out_resource:
- status = nfserr_resource;
- goto out;
}

static bool

--
2.54.0