Commit 3fd9557a authored by Chuck Lever's avatar Chuck Lever Committed by J. Bruce Fields

NFSD: Refactor the generic write vector fill helper

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: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 07d0ff3b
...@@ -202,7 +202,8 @@ nfsd3_proc_write(struct svc_rqst *rqstp) ...@@ -202,7 +202,8 @@ nfsd3_proc_write(struct svc_rqst *rqstp)
fh_copy(&resp->fh, &argp->fh); fh_copy(&resp->fh, &argp->fh);
resp->committed = argp->stable; 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) if (!nvecs)
RETURN_STATUS(nfserr_io); RETURN_STATUS(nfserr_io);
nfserr = nfsd_write(rqstp, &resp->fh, argp->offset, nfserr = nfsd_write(rqstp, &resp->fh, argp->offset,
......
...@@ -986,24 +986,6 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -986,24 +986,6 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
return status; 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 static __be32
nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
union nfsd4_op_u *u) union nfsd4_op_u *u)
...@@ -1031,7 +1013,10 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -1031,7 +1013,10 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
write->wr_how_written = write->wr_stable_how; write->wr_how_written = write->wr_stable_how;
gen_boot_verifier(&write->wr_verifier, SVC_NET(rqstp)); 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)); WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec));
status = nfsd_vfs_write(rqstp, &cstate->current_fh, filp, status = nfsd_vfs_write(rqstp, &cstate->current_fh, filp,
......
...@@ -218,7 +218,8 @@ nfsd_proc_write(struct svc_rqst *rqstp) ...@@ -218,7 +218,8 @@ nfsd_proc_write(struct svc_rqst *rqstp)
SVCFH_fmt(&argp->fh), SVCFH_fmt(&argp->fh),
argp->len, argp->offset); 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) if (!nvecs)
return nfserr_io; return nfserr_io;
nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh), nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
......
...@@ -496,6 +496,7 @@ void svc_reserve(struct svc_rqst *rqstp, int space); ...@@ -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); struct svc_pool * svc_pool_for_cpu(struct svc_serv *serv, int cpu);
char * svc_print_addr(struct svc_rqst *, char *, size_t); char * svc_print_addr(struct svc_rqst *, char *, size_t);
unsigned int svc_fill_write_vector(struct svc_rqst *rqstp, unsigned int svc_fill_write_vector(struct svc_rqst *rqstp,
struct page **pages,
struct kvec *first, size_t total); struct kvec *first, size_t total);
char *svc_fill_symlink_pathname(struct svc_rqst *rqstp, char *svc_fill_symlink_pathname(struct svc_rqst *rqstp,
struct kvec *first, size_t total); struct kvec *first, size_t total);
......
...@@ -1537,16 +1537,16 @@ EXPORT_SYMBOL_GPL(svc_max_payload); ...@@ -1537,16 +1537,16 @@ EXPORT_SYMBOL_GPL(svc_max_payload);
/** /**
* svc_fill_write_vector - Construct data argument for VFS write call * svc_fill_write_vector - Construct data argument for VFS write call
* @rqstp: svc_rqst to operate on * @rqstp: svc_rqst to operate on
* @pages: list of pages containing data payload
* @first: buffer containing first section of write payload * @first: buffer containing first section of write payload
* @total: total number of bytes 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, unsigned int svc_fill_write_vector(struct svc_rqst *rqstp, struct page **pages,
size_t total) struct kvec *first, size_t total)
{ {
struct kvec *vec = rqstp->rq_vec; struct kvec *vec = rqstp->rq_vec;
struct page **pages;
unsigned int i; unsigned int i;
/* Some types of transport can present the write payload /* 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, ...@@ -1560,14 +1560,11 @@ unsigned int svc_fill_write_vector(struct svc_rqst *rqstp, struct kvec *first,
++i; ++i;
} }
WARN_ON_ONCE(rqstp->rq_arg.page_base != 0);
pages = rqstp->rq_arg.pages;
while (total) { while (total) {
vec[i].iov_base = page_address(*pages); vec[i].iov_base = page_address(*pages);
vec[i].iov_len = min_t(size_t, total, PAGE_SIZE); vec[i].iov_len = min_t(size_t, total, PAGE_SIZE);
total -= vec[i].iov_len; total -= vec[i].iov_len;
++i; ++i;
++pages; ++pages;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment