Using a bvec array vs a kvec one slightly simplifies the logic, and allow to remove the rq_vecs array. Signed-off-by: Christoph Hellwig <hch@xxxxxx> --- fs/nfsd/vfs.c | 27 ++++++++++++++++----------- include/linux/sunrpc/svc.h | 1 - 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 0cc9639fba79..1804aed0739b 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1078,26 +1078,31 @@ __be32 nfsd_iter_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, loff_t offset, unsigned long *count, unsigned int base, u32 *eof) { - unsigned long v, total; + unsigned long total = *count; struct iov_iter iter; loff_t ppos = offset; - struct page *page; + unsigned int v = 0; ssize_t host_err; - v = 0; - total = *count; + /* + * Note: if this request is served through the socket transport, rq_bvec + * will be rebuilt again in the transport, including the XDR header and + * trailer. It would be nice to fully build it in one place, but that + * needs more work. + */ while (total) { - page = *(rqstp->rq_next_page++); - rqstp->rq_vec[v].iov_base = page_address(page) + base; - rqstp->rq_vec[v].iov_len = min_t(size_t, total, PAGE_SIZE - base); - total -= rqstp->rq_vec[v].iov_len; - ++v; + unsigned int len = min(total, PAGE_SIZE - base); + struct page *page = *(rqstp->rq_next_page++); + + bvec_set_page(&rqstp->rq_bvec[v++], page, len, base); + if (WARN_ON_ONCE(v > ARRAY_SIZE(rqstp->rq_bvec))) + return -EIO; + total -= len; base = 0; } - WARN_ON_ONCE(v > ARRAY_SIZE(rqstp->rq_vec)); trace_nfsd_read_vector(rqstp, fhp, offset, *count); - iov_iter_kvec(&iter, ITER_DEST, rqstp->rq_vec, v, *count); + iov_iter_bvec(&iter, ITER_DEST, rqstp->rq_bvec, v, *count); host_err = vfs_iter_read(file, &iter, &ppos, 0); return nfsd_finish_read(rqstp, fhp, file, offset, count, eof, host_err); } diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index c25456738315..a040583a29da 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -194,7 +194,6 @@ struct svc_rqst { struct page * *rq_page_end; /* one past the last page */ struct folio_batch rq_fbatch; - struct kvec rq_vec[RPCSVC_MAXPAGES]; /* generally useful.. */ struct bio_vec rq_bvec[RPCSVC_MAXPAGES]; __be32 rq_xid; /* transmission id */ -- 2.47.2