From: Chuck Lever <chuck.lever@xxxxxxxxxx> If we can get rid of all uses of rq_vec, then it can be removed. Replace one use of rqstp::rq_vec with rqstp::rq_bvec. The feeling of layering violation grows stronger now that we've included <linux/sunrpc/xdr.h> in fs/nfsd/vfs.c. Suggested-by: Christoph Hellwig <hch@xxxxxxxxxxxxx> Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> --- fs/nfsd/vfs.c | 5 +++-- net/sunrpc/svc.c | 23 +++++++++++++---------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index e92036251ee7..15195fedc44e 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -31,6 +31,7 @@ #include <linux/exportfs.h> #include <linux/writeback.h> #include <linux/security.h> +#include <linux/sunrpc/xdr.h> #include "xdr3.h" @@ -1204,8 +1205,8 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, if (stable && !fhp->fh_use_wgather) flags |= RWF_SYNC; - nvecs = svc_fill_write_vector(rqstp, payload); - iov_iter_kvec(&iter, ITER_SOURCE, rqstp->rq_vec, nvecs, *cnt); + nvecs = xdr_buf_to_bvec(rqstp->rq_bvec, rqstp->rq_maxpages, payload); + iov_iter_bvec(&iter, ITER_SOURCE, rqstp->rq_bvec, nvecs, *cnt); since = READ_ONCE(file->f_wb_err); if (verf) nfsd_copy_write_verifier(verf, nn); diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 930a10cac90b..d113f44798a1 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -1727,35 +1727,38 @@ EXPORT_SYMBOL_GPL(svc_encode_result_payload); /** * svc_fill_write_vector - Construct data argument for VFS write call - * @rqstp: svc_rqst to operate on + * @rqstp: RPC execution context * @payload: xdr_buf containing only the write data payload * - * Fills in rqstp::rq_vec, and returns the number of elements. + * Fills in @rqstp->rq_bvec, and returns the number of elements it + * populated in that array. */ unsigned int svc_fill_write_vector(struct svc_rqst *rqstp, struct xdr_buf *payload) { struct page **pages = payload->pages; + struct bio_vec *vec = rqstp->rq_bvec; struct kvec *first = payload->head; - struct kvec *vec = rqstp->rq_vec; size_t total = payload->len; - unsigned int i; + unsigned int base, len, i; /* Some types of transport can present the write payload * entirely in rq_arg.pages. In this case, @first is empty. */ i = 0; if (first->iov_len) { - vec[i].iov_base = first->iov_base; - vec[i].iov_len = min_t(size_t, total, first->iov_len); - total -= vec[i].iov_len; + len = min_t(size_t, total, first->iov_len); + bvec_set_virt(&vec[i], first->iov_base, len); + total -= len; ++i; } + base = payload->page_base; while (total) { - vec[i].iov_base = page_address(*pages); - vec[i].iov_len = min_t(size_t, total, PAGE_SIZE); - total -= vec[i].iov_len; + len = min_t(size_t, total, PAGE_SIZE); + bvec_set_page(&vec[i], *pages, len, base); + total -= len; + base = 0; ++i; ++pages; } -- 2.49.0