nfsd: split off the write decode code into a separate function
authorFrank van der Linden <fllinden@amazon.com>
Tue, 23 Jun 2020 22:39:21 +0000 (22:39 +0000)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 13 Jul 2020 21:27:03 +0000 (17:27 -0400)
nfs4_decode_write has code to parse incoming XDR write data in to
a kvec head, and a list of pages.

Put this code in to a separate function, so that it can be used
later by the xattr code, for setxattr. No functional change.

Signed-off-by: Frank van der Linden <fllinden@amazon.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/nfs4xdr.c

index 996ac01ee97738bde2c8e8782a16ff2e9eb6a9b3..48806b493ebaa28bfce1ed5de3682de4735994d5 100644 (file)
@@ -257,6 +257,44 @@ svcxdr_dupstr(struct nfsd4_compoundargs *argp, void *buf, u32 len)
        return p;
 }
 
+static __be32
+svcxdr_construct_vector(struct nfsd4_compoundargs *argp, struct kvec *head,
+                       struct page ***pagelist, u32 buflen)
+{
+       int avail;
+       int len;
+       int pages;
+
+       /* Sorry .. no magic macros for this.. *
+        * READ_BUF(write->wr_buflen);
+        * SAVEMEM(write->wr_buf, write->wr_buflen);
+        */
+       avail = (char *)argp->end - (char *)argp->p;
+       if (avail + argp->pagelen < buflen) {
+               dprintk("NFSD: xdr error (%s:%d)\n",
+                              __FILE__, __LINE__);
+               return nfserr_bad_xdr;
+       }
+       head->iov_base = argp->p;
+       head->iov_len = avail;
+       *pagelist = argp->pagelist;
+
+       len = XDR_QUADLEN(buflen) << 2;
+       if (len >= avail) {
+               len -= avail;
+
+               pages = len >> PAGE_SHIFT;
+               argp->pagelist += pages;
+               argp->pagelen -= pages * PAGE_SIZE;
+               len -= pages * PAGE_SIZE;
+
+               next_decode_page(argp);
+       }
+       argp->p += XDR_QUADLEN(len);
+
+       return 0;
+}
+
 /**
  * savemem - duplicate a chunk of memory for later processing
  * @argp: NFSv4 compound argument structure to be freed with
@@ -1265,8 +1303,6 @@ nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify
 static __be32
 nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
 {
-       int avail;
-       int len;
        DECODE_HEAD;
 
        status = nfsd4_decode_stateid(argp, &write->wr_stateid);
@@ -1279,34 +1315,10 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
                goto xdr_error;
        write->wr_buflen = be32_to_cpup(p++);
 
-       /* Sorry .. no magic macros for this.. *
-        * READ_BUF(write->wr_buflen);
-        * SAVEMEM(write->wr_buf, write->wr_buflen);
-        */
-       avail = (char*)argp->end - (char*)argp->p;
-       if (avail + argp->pagelen < write->wr_buflen) {
-               dprintk("NFSD: xdr error (%s:%d)\n",
-                               __FILE__, __LINE__);
-               goto xdr_error;
-       }
-       write->wr_head.iov_base = p;
-       write->wr_head.iov_len = avail;
-       write->wr_pagelist = argp->pagelist;
-
-       len = XDR_QUADLEN(write->wr_buflen) << 2;
-       if (len >= avail) {
-               int pages;
-
-               len -= avail;
-
-               pages = len >> PAGE_SHIFT;
-               argp->pagelist += pages;
-               argp->pagelen -= pages * PAGE_SIZE;
-               len -= pages * PAGE_SIZE;
-
-               next_decode_page(argp);
-       }
-       argp->p += XDR_QUADLEN(len);
+       status = svcxdr_construct_vector(argp, &write->wr_head,
+                                        &write->wr_pagelist, write->wr_buflen);
+       if (status)
+               return status;
 
        DECODE_TAIL;
 }