Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

NFSD: Insulate nfsd4_encode_fattr4() from page boundaries in the encode buffer

Commit ab04de60ae1c ("NFSD: Optimize nfsd4_encode_fattr()") replaced
the use of write_bytes_to_xdr_buf() because it's expensive and the
data items to be encoded are already properly aligned.

However, there's no guarantee that the pointer returned from
xdr_reserve_space() will still point to the correct reserved space
in the encode buffer after one or more intervening calls to
xdr_reserve_space(). It just happens to work with the current
implementation of xdr_reserve_space().

This commit effectively reverts the optimization.

Reviewed-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

+5 -5
+5 -5
fs/nfsd/nfs4xdr.c
··· 3507 3507 struct nfsd4_fattr_args args; 3508 3508 struct svc_fh *tempfh = NULL; 3509 3509 int starting_len = xdr->buf->len; 3510 - __be32 *attrlen_p, status; 3511 - int attrlen_offset; 3510 + unsigned int attrlen_offset; 3511 + __be32 attrlen, status; 3512 3512 u32 attrmask[3]; 3513 3513 int err; 3514 3514 struct nfsd4_compoundres *resp = rqstp->rq_resp; ··· 3629 3629 3630 3630 /* attr_vals */ 3631 3631 attrlen_offset = xdr->buf->len; 3632 - attrlen_p = xdr_reserve_space(xdr, XDR_UNIT); 3633 - if (!attrlen_p) 3632 + if (unlikely(!xdr_reserve_space(xdr, XDR_UNIT))) 3634 3633 goto out_resource; 3635 3634 bitmap_from_arr32(attr_bitmap, attrmask, 3636 3635 ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops)); ··· 3639 3640 if (status != nfs_ok) 3640 3641 goto out; 3641 3642 } 3642 - *attrlen_p = cpu_to_be32(xdr->buf->len - attrlen_offset - XDR_UNIT); 3643 + attrlen = cpu_to_be32(xdr->buf->len - attrlen_offset - XDR_UNIT); 3644 + write_bytes_to_xdr_buf(xdr->buf, attrlen_offset, &attrlen, XDR_UNIT); 3643 3645 status = nfs_ok; 3644 3646 3645 3647 out: