OSDN Git Service

NFSD: Refactor the generic write vector fill helper
authorChuck Lever <chuck.lever@oracle.com>
Fri, 27 Jul 2018 15:19:05 +0000 (11:19 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Thu, 9 Aug 2018 20:11:21 +0000 (16:11 -0400)
fill_in_write_vector() is nearly the same logic as
svc_fill_write_vector(), but there are a few differences so that
the former can handle multiple WRITE payloads in a single COMPOUND.

svc_fill_write_vector() can be adjusted so that it can be used in
the NFSv4 WRITE code path too. Instead of assuming the pages are
coming from rq_args.pages, have the caller pass in the page list.

The immediate benefit is a reduction of code duplication. It also
prevents the NFSv4 WRITE decoder from passing an empty vector
element when the transport has provided the payload in the xdr_buf's
page array.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/nfs3proc.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfsproc.c
include/linux/sunrpc/svc.h
net/sunrpc/svc.c

index 6259a4b..8d1c2d1 100644 (file)
@@ -202,7 +202,8 @@ nfsd3_proc_write(struct svc_rqst *rqstp)
 
        fh_copy(&resp->fh, &argp->fh);
        resp->committed = argp->stable;
-       nvecs = svc_fill_write_vector(rqstp, &argp->first, cnt);
+       nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
+                                     &argp->first, cnt);
        if (!nvecs)
                RETURN_STATUS(nfserr_io);
        nfserr = nfsd_write(rqstp, &resp->fh, argp->offset,
index 3652f9b..b7bc6e1 100644 (file)
@@ -986,24 +986,6 @@ out:
        return status;
 }
 
-static int fill_in_write_vector(struct kvec *vec, struct nfsd4_write *write)
-{
-        int i = 1;
-        int buflen = write->wr_buflen;
-
-        vec[0].iov_base = write->wr_head.iov_base;
-        vec[0].iov_len = min_t(int, buflen, write->wr_head.iov_len);
-        buflen -= vec[0].iov_len;
-
-        while (buflen) {
-                vec[i].iov_base = page_address(write->wr_pagelist[i - 1]);
-                vec[i].iov_len = min_t(int, PAGE_SIZE, buflen);
-                buflen -= vec[i].iov_len;
-                i++;
-        }
-        return i;
-}
-
 static __be32
 nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
            union nfsd4_op_u *u)
@@ -1031,7 +1013,10 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        write->wr_how_written = write->wr_stable_how;
        gen_boot_verifier(&write->wr_verifier, SVC_NET(rqstp));
 
-       nvecs = fill_in_write_vector(rqstp->rq_vec, write);
+       nvecs = svc_fill_write_vector(rqstp, write->wr_pagelist,
+                                     &write->wr_head, write->wr_buflen);
+       if (!nvecs)
+               return nfserr_io;
        WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec));
 
        status = nfsd_vfs_write(rqstp, &cstate->current_fh, filp,
index f107f9f..a6faee5 100644 (file)
@@ -218,7 +218,8 @@ nfsd_proc_write(struct svc_rqst *rqstp)
                SVCFH_fmt(&argp->fh),
                argp->len, argp->offset);
 
-       nvecs = svc_fill_write_vector(rqstp, &argp->first, cnt);
+       nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
+                                     &argp->first, cnt);
        if (!nvecs)
                return nfserr_io;
        nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
index 574368e..43f88bd 100644 (file)
@@ -496,6 +496,7 @@ void                   svc_reserve(struct svc_rqst *rqstp, int space);
 struct svc_pool *  svc_pool_for_cpu(struct svc_serv *serv, int cpu);
 char *            svc_print_addr(struct svc_rqst *, char *, size_t);
 unsigned int      svc_fill_write_vector(struct svc_rqst *rqstp,
+                                        struct page **pages,
                                         struct kvec *first, size_t total);
 char             *svc_fill_symlink_pathname(struct svc_rqst *rqstp,
                                             struct kvec *first, size_t total);
index 30a4226..2194ed5 100644 (file)
@@ -1537,16 +1537,16 @@ EXPORT_SYMBOL_GPL(svc_max_payload);
 /**
  * svc_fill_write_vector - Construct data argument for VFS write call
  * @rqstp: svc_rqst to operate on
+ * @pages: list of pages containing data payload
  * @first: buffer containing first section of write payload
  * @total: total number of bytes of write payload
  *
- * Returns the number of elements populated in the data argument array.
+ * Fills in rqstp::rq_vec, and returns the number of elements.
  */
-unsigned int svc_fill_write_vector(struct svc_rqst *rqstp, struct kvec *first,
-                                  size_t total)
+unsigned int svc_fill_write_vector(struct svc_rqst *rqstp, struct page **pages,
+                                  struct kvec *first, size_t total)
 {
        struct kvec *vec = rqstp->rq_vec;
-       struct page **pages;
        unsigned int i;
 
        /* Some types of transport can present the write payload
@@ -1560,14 +1560,11 @@ unsigned int svc_fill_write_vector(struct svc_rqst *rqstp, struct kvec *first,
                ++i;
        }
 
-       WARN_ON_ONCE(rqstp->rq_arg.page_base != 0);
-       pages = rqstp->rq_arg.pages;
        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;
                ++i;
-
                ++pages;
        }