Skip to content

Commit 703d752

Browse files
committed
NFSD: Hoist rq_vec preparation into nfsd_read() [step two]
Now that the preparation of an rq_vec has been removed from the generic read path, nfsd_splice_read() no longer needs to reset rq_next_page. nfsd4_encode_read() calls nfsd_splice_read() directly. As far as I can ascertain, resetting rq_next_page for NFSv4 splice reads is unnecessary because rq_next_page is already set correctly. Moreover, resetting it might even be incorrect if previous operations in the COMPOUND have already consumed at least a page of the send buffer. I would expect that the result would be encoding the READ payload over previously-encoded results. Signed-off-by: Chuck Lever <[email protected]>
1 parent 507df40 commit 703d752

File tree

4 files changed

+30
-22
lines changed

4 files changed

+30
-22
lines changed

fs/nfsd/nfs4xdr.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4103,13 +4103,13 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,
41034103
__be32 zero = xdr_zero;
41044104
__be32 nfserr;
41054105

4106-
read->rd_vlen = xdr_reserve_space_vec(xdr, resp->rqstp->rq_vec, maxcount);
4107-
if (read->rd_vlen < 0)
4106+
if (xdr_reserve_space_vec(xdr, maxcount) < 0)
41084107
return nfserr_resource;
41094108

4110-
nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset,
4111-
resp->rqstp->rq_vec, read->rd_vlen, &maxcount,
4112-
&read->rd_eof);
4109+
nfserr = nfsd_iter_read(resp->rqstp, read->rd_fhp, file,
4110+
read->rd_offset, &maxcount,
4111+
xdr->buf->page_len & ~PAGE_MASK,
4112+
&read->rd_eof);
41134113
read->rd_length = maxcount;
41144114
if (nfserr)
41154115
return nfserr;

fs/nfsd/vfs.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,18 @@ static __be32 nfsd_finish_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
10031003
}
10041004
}
10051005

1006+
/**
1007+
* nfsd_splice_read - Perform a VFS read using a splice pipe
1008+
* @rqstp: RPC transaction context
1009+
* @fhp: file handle of file to be read
1010+
* @file: opened struct file of file to be read
1011+
* @offset: starting byte offset
1012+
* @count: IN: requested number of bytes; OUT: number of bytes read
1013+
* @eof: OUT: set non-zero if operation reached the end of the file
1014+
*
1015+
* Returns nfs_ok on success, otherwise an nfserr stat value is
1016+
* returned.
1017+
*/
10061018
__be32 nfsd_splice_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
10071019
struct file *file, loff_t offset, unsigned long *count,
10081020
u32 *eof)
@@ -1016,7 +1028,6 @@ __be32 nfsd_splice_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
10161028
ssize_t host_err;
10171029

10181030
trace_nfsd_read_splice(rqstp, fhp, offset, *count);
1019-
rqstp->rq_next_page = rqstp->rq_respages + 1;
10201031
host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor);
10211032
return nfsd_finish_read(rqstp, fhp, file, offset, count, eof, host_err);
10221033
}

include/linux/sunrpc/xdr.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,7 @@ extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf,
242242
extern void xdr_init_encode_pages(struct xdr_stream *xdr, struct xdr_buf *buf,
243243
struct page **pages, struct rpc_rqst *rqst);
244244
extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes);
245-
extern int xdr_reserve_space_vec(struct xdr_stream *xdr, struct kvec *vec,
246-
size_t nbytes);
245+
extern int xdr_reserve_space_vec(struct xdr_stream *xdr, size_t nbytes);
247246
extern void __xdr_commit_encode(struct xdr_stream *xdr);
248247
extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len);
249248
extern void xdr_truncate_decode(struct xdr_stream *xdr, size_t len);

net/sunrpc/xdr.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,22 +1070,22 @@ __be32 * xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes)
10701070
}
10711071
EXPORT_SYMBOL_GPL(xdr_reserve_space);
10721072

1073-
10741073
/**
10751074
* xdr_reserve_space_vec - Reserves a large amount of buffer space for sending
10761075
* @xdr: pointer to xdr_stream
1077-
* @vec: pointer to a kvec array
10781076
* @nbytes: number of bytes to reserve
10791077
*
1080-
* Reserves enough buffer space to encode 'nbytes' of data and stores the
1081-
* pointers in 'vec'. The size argument passed to xdr_reserve_space() is
1082-
* determined based on the number of bytes remaining in the current page to
1083-
* avoid invalidating iov_base pointers when xdr_commit_encode() is called.
1078+
* The size argument passed to xdr_reserve_space() is determined based
1079+
* on the number of bytes remaining in the current page to avoid
1080+
* invalidating iov_base pointers when xdr_commit_encode() is called.
1081+
*
1082+
* Return values:
1083+
* %0: success
1084+
* %-EMSGSIZE: not enough space is available in @xdr
10841085
*/
1085-
int xdr_reserve_space_vec(struct xdr_stream *xdr, struct kvec *vec, size_t nbytes)
1086+
int xdr_reserve_space_vec(struct xdr_stream *xdr, size_t nbytes)
10861087
{
1087-
int thislen;
1088-
int v = 0;
1088+
size_t thislen;
10891089
__be32 *p;
10901090

10911091
/*
@@ -1097,21 +1097,19 @@ int xdr_reserve_space_vec(struct xdr_stream *xdr, struct kvec *vec, size_t nbyte
10971097
xdr->end = xdr->p;
10981098
}
10991099

1100+
/* XXX: Let's find a way to make this more efficient */
11001101
while (nbytes) {
11011102
thislen = xdr->buf->page_len % PAGE_SIZE;
11021103
thislen = min_t(size_t, nbytes, PAGE_SIZE - thislen);
11031104

11041105
p = xdr_reserve_space(xdr, thislen);
11051106
if (!p)
1106-
return -EIO;
1107+
return -EMSGSIZE;
11071108

1108-
vec[v].iov_base = p;
1109-
vec[v].iov_len = thislen;
1110-
v++;
11111109
nbytes -= thislen;
11121110
}
11131111

1114-
return v;
1112+
return 0;
11151113
}
11161114
EXPORT_SYMBOL_GPL(xdr_reserve_space_vec);
11171115

0 commit comments

Comments
 (0)