Skip to content

Commit d7de37d

Browse files
committed
NFSD: Relocate the xdr_reserve_space_vec() call site
In order to detect when a direct READ is possible, we need the send buffer's .page_len to be zero when there is nothing in the buffer's .pages array yet. However, when xdr_reserve_space_vec() extends the size of the xdr_stream to accommodate a READ payload, it adds to the send buffer's .page_len. It should be safe to reserve the stream space /after/ the VFS read operation completes. This is, for example, how an NFSv3 READ works: the VFS read goes into the rq_bvec, and is then added to the send xdr_stream later by svcxdr_encode_opaque_pages(). Now that xdr_reserve_space_vec() uses the number of bytes actually read, the xdr_truncate_encode() call is no longer necessary. Reviewed-by: NeilBrown <neil@brown.name> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent 803bc84 commit d7de37d

1 file changed

Lines changed: 16 additions & 4 deletions

File tree

fs/nfsd/nfs4xdr.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4480,18 +4480,30 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,
44804480
__be32 zero = xdr_zero;
44814481
__be32 nfserr;
44824482

4483-
if (xdr_reserve_space_vec(xdr, maxcount) < 0)
4484-
return nfserr_resource;
4485-
44864483
nfserr = nfsd_iter_read(resp->rqstp, read->rd_fhp, read->rd_nf,
44874484
read->rd_offset, &maxcount, base,
44884485
&read->rd_eof);
44894486
read->rd_length = maxcount;
44904487
if (nfserr)
44914488
return nfserr;
4489+
4490+
/*
4491+
* svcxdr_encode_opaque_pages() is not used here because
4492+
* we don't want to encode subsequent results in this
4493+
* COMPOUND into the xdr->buf's tail, but rather those
4494+
* results should follow the NFS READ payload in the
4495+
* buf's pages.
4496+
*/
4497+
if (xdr_reserve_space_vec(xdr, maxcount) < 0)
4498+
return nfserr_resource;
4499+
4500+
/*
4501+
* Mark the buffer location of the NFS READ payload so that
4502+
* direct placement-capable transports send only the
4503+
* payload bytes out-of-band.
4504+
*/
44924505
if (svc_encode_result_payload(resp->rqstp, starting_len, maxcount))
44934506
return nfserr_io;
4494-
xdr_truncate_encode(xdr, starting_len + xdr_align_size(maxcount));
44954507

44964508
write_bytes_to_xdr_buf(xdr->buf, starting_len + maxcount, &zero,
44974509
xdr_pad_size(maxcount));

0 commit comments

Comments
 (0)