NFSD: Update the NFSv2 READLINK result encoder to use struct xdr_stream
authorChuck Lever <chuck.lever@oracle.com>
Fri, 23 Oct 2020 19:41:09 +0000 (15:41 -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 2ae6409..f550804 100644 (file)
@@ -151,13 +151,14 @@ nfsd_proc_readlink(struct svc_rqst *rqstp)
 {
        struct nfsd_fhandle *argp = rqstp->rq_argp;
        struct nfsd_readlinkres *resp = rqstp->rq_resp;
-       char *buffer = page_address(*(rqstp->rq_next_page++));
 
        dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh));
 
        /* Read the symlink. */
        resp->len = NFS_MAXPATHLEN;
-       resp->status = nfsd_readlink(rqstp, &argp->fh, buffer, &resp->len);
+       resp->page = *(rqstp->rq_next_page++);
+       resp->status = nfsd_readlink(rqstp, &argp->fh,
+                                    page_address(resp->page), &resp->len);
 
        fh_put(&argp->fh);
        return rpc_success;
index 989144b..74d9d11 100644 (file)
@@ -527,24 +527,22 @@ nfssvc_encode_diropres(struct svc_rqst *rqstp, __be32 *p)
 int
 nfssvc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p)
 {
+       struct xdr_stream *xdr = &rqstp->rq_res_stream;
        struct nfsd_readlinkres *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++ = htonl(resp->len);
-       xdr_ressize_check(rqstp, p);
-       rqstp->rq_res.page_len = resp->len;
-       if (resp->len & 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->len&3);
-       }
-       if (svc_encode_result_payload(rqstp, head->iov_len, resp->len))
+       if (!svcxdr_encode_stat(xdr, resp->status))
                return 0;
+       switch (resp->status) {
+       case nfs_ok:
+               if (xdr_stream_encode_u32(xdr, resp->len) < 0)
+                       return 0;
+               xdr_write_pages(xdr, &resp->page, 0, resp->len);
+               if (svc_encode_result_payload(rqstp, head->iov_len, resp->len) < 0)
+                       return 0;
+               break;
+       }
+
        return 1;
 }
 
index a9b4ee6..b868565 100644 (file)
@@ -94,6 +94,7 @@ struct nfsd_diropres  {
 struct nfsd_readlinkres {
        __be32                  status;
        int                     len;
+       struct page             *page;
 };
 
 struct nfsd_readres {