NFSD: Update the NFSv2 READ result encoder to use struct xdr_stream
authorChuck Lever <chuck.lever@oracle.com>
Fri, 23 Oct 2020 20:40:11 +0000 (16:40 -0400)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 22 Mar 2021 14:18:58 +0000 (10:18 -0400)
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/nfsproc.c
fs/nfsd/nfsxdr.c
fs/nfsd/xdr.h

index f550804..2088bb0 100644 (file)
@@ -185,6 +185,7 @@ nfsd_proc_read(struct svc_rqst *rqstp)
 
        v = 0;
        len = argp->count;
+       resp->pages = rqstp->rq_next_page;
        while (len > 0) {
                struct page *page = *(rqstp->rq_next_page++);
 
index 74d9d11..d6d7d07 100644 (file)
@@ -549,27 +549,25 @@ nfssvc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p)
 int
 nfssvc_encode_readres(struct svc_rqst *rqstp, __be32 *p)
 {
+       struct xdr_stream *xdr = &rqstp->rq_res_stream;
        struct nfsd_readres *resp = rqstp->rq_resp;
        struct kvec *head = rqstp->rq_res.head;
 
-       *p++ = resp->status;
-       if (resp->status != nfs_ok)
-               return xdr_ressize_check(rqstp, p);
-
-       p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
-       *p++ = htonl(resp->count);
-       xdr_ressize_check(rqstp, p);
-
-       /* now update rqstp->rq_res to reflect data as well */
-       rqstp->rq_res.page_len = resp->count;
-       if (resp->count & 3) {
-               /* need to pad the tail */
-               rqstp->rq_res.tail[0].iov_base = p;
-               *p = 0;
-               rqstp->rq_res.tail[0].iov_len = 4 - (resp->count&3);
-       }
-       if (svc_encode_result_payload(rqstp, head->iov_len, resp->count))
+       if (!svcxdr_encode_stat(xdr, resp->status))
                return 0;
+       switch (resp->status) {
+       case nfs_ok:
+               if (!svcxdr_encode_fattr(rqstp, xdr, &resp->fh, &resp->stat))
+                       return 0;
+               if (xdr_stream_encode_u32(xdr, resp->count) < 0)
+                       return 0;
+               xdr_write_pages(xdr, resp->pages, rqstp->rq_res.page_base,
+                               resp->count);
+               if (svc_encode_result_payload(rqstp, head->iov_len, resp->count) < 0)
+                       return 0;
+               break;
+       }
+
        return 1;
 }
 
index b868565..277b74c 100644 (file)
@@ -102,6 +102,7 @@ struct nfsd_readres {
        struct svc_fh           fh;
        unsigned long           count;
        struct kstat            stat;
+       struct page             **pages;
 };
 
 struct nfsd_readdirres {