Commit 44524359 authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds

[PATCH] knfsd: Replace two page lists in struct svc_rqst with one

We are planning to increase RPCSVC_MAXPAGES from about 8 to about 256.  This
means we need to be a bit careful about arrays of size RPCSVC_MAXPAGES.

struct svc_rqst contains two such arrays.  However the there are never more
that RPCSVC_MAXPAGES pages in the two arrays together, so only one array is
needed.

The two arrays are for the pages holding the request, and the pages holding
the reply.  Instead of two arrays, we can simply keep an index into where the
first reply page is.

This patch also removes a number of small inline functions that probably
server to obscure what is going on rather than clarify it, and opencode the
needed functionality.

Also remove the 'rq_restailpage' variable as it is *always* 0.  i.e.  if the
response 'xdr' structure has a non-empty tail it is always in the same pages
as the head.

 check counters are initilised and incr properly
 check for consistant usage of ++ etc
 maybe extra some inlines for common approach
 general review
Signed-off-by: default avatarNeil Brown <neilb@suse.de>
Cc: Magnus Maatta <novell@kiruna.se>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 5680c446
...@@ -241,7 +241,7 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, u32 *p, ...@@ -241,7 +241,7 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, u32 *p,
rqstp->rq_res.page_len = w; rqstp->rq_res.page_len = w;
while (w > 0) { while (w > 0) {
if (!svc_take_res_page(rqstp)) if (!rqstp->rq_respages[rqstp->rq_resused++])
return 0; return 0;
w -= PAGE_SIZE; w -= PAGE_SIZE;
} }
......
...@@ -185,7 +185,7 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, u32 *p, ...@@ -185,7 +185,7 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, u32 *p,
rqstp->rq_res.page_len = w; rqstp->rq_res.page_len = w;
while (w > 0) { while (w > 0) {
if (!svc_take_res_page(rqstp)) if (!rqstp->rq_respages[rqstp->rq_resused++])
return 0; return 0;
w -= PAGE_SIZE; w -= PAGE_SIZE;
} }
......
...@@ -343,8 +343,7 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, u32 *p, ...@@ -343,8 +343,7 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, u32 *p,
/* set up the kvec */ /* set up the kvec */
v=0; v=0;
while (len > 0) { while (len > 0) {
pn = rqstp->rq_resused; pn = rqstp->rq_resused++;
svc_take_page(rqstp);
args->vec[v].iov_base = page_address(rqstp->rq_respages[pn]); args->vec[v].iov_base = page_address(rqstp->rq_respages[pn]);
args->vec[v].iov_len = len < PAGE_SIZE? len : PAGE_SIZE; args->vec[v].iov_len = len < PAGE_SIZE? len : PAGE_SIZE;
len -= args->vec[v].iov_len; len -= args->vec[v].iov_len;
...@@ -382,7 +381,7 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p, ...@@ -382,7 +381,7 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
while (len > args->vec[v].iov_len) { while (len > args->vec[v].iov_len) {
len -= args->vec[v].iov_len; len -= args->vec[v].iov_len;
v++; v++;
args->vec[v].iov_base = page_address(rqstp->rq_argpages[v]); args->vec[v].iov_base = page_address(rqstp->rq_pages[v]);
args->vec[v].iov_len = PAGE_SIZE; args->vec[v].iov_len = PAGE_SIZE;
} }
args->vec[v].iov_len = len; args->vec[v].iov_len = len;
...@@ -446,11 +445,11 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p, ...@@ -446,11 +445,11 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p,
* This page appears in the rq_res.pages list, but as pages_len is always * This page appears in the rq_res.pages list, but as pages_len is always
* 0, it won't get in the way * 0, it won't get in the way
*/ */
svc_take_page(rqstp);
len = ntohl(*p++); len = ntohl(*p++);
if (len == 0 || len > NFS3_MAXPATHLEN || len >= PAGE_SIZE) if (len == 0 || len > NFS3_MAXPATHLEN || len >= PAGE_SIZE)
return 0; return 0;
args->tname = new = page_address(rqstp->rq_respages[rqstp->rq_resused-1]); args->tname = new =
page_address(rqstp->rq_respages[rqstp->rq_resused++]);
args->tlen = len; args->tlen = len;
/* first copy and check from the first page */ /* first copy and check from the first page */
old = (char*)p; old = (char*)p;
...@@ -522,8 +521,8 @@ nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, u32 *p, ...@@ -522,8 +521,8 @@ nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, u32 *p,
{ {
if (!(p = decode_fh(p, &args->fh))) if (!(p = decode_fh(p, &args->fh)))
return 0; return 0;
svc_take_page(rqstp); args->buffer =
args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused-1]); page_address(rqstp->rq_respages[rqstp->rq_resused++]);
return xdr_argsize_check(rqstp, p); return xdr_argsize_check(rqstp, p);
} }
...@@ -554,8 +553,8 @@ nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p, ...@@ -554,8 +553,8 @@ nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p,
if (args->count > PAGE_SIZE) if (args->count > PAGE_SIZE)
args->count = PAGE_SIZE; args->count = PAGE_SIZE;
svc_take_page(rqstp); args->buffer =
args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused-1]); page_address(rqstp->rq_respages[rqstp->rq_resused++]);
return xdr_argsize_check(rqstp, p); return xdr_argsize_check(rqstp, p);
} }
...@@ -578,8 +577,7 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, u32 *p, ...@@ -578,8 +577,7 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, u32 *p,
args->count = len; args->count = len;
while (len > 0) { while (len > 0) {
pn = rqstp->rq_resused; pn = rqstp->rq_resused++;
svc_take_page(rqstp);
if (!args->buffer) if (!args->buffer)
args->buffer = page_address(rqstp->rq_respages[pn]); args->buffer = page_address(rqstp->rq_respages[pn]);
len -= PAGE_SIZE; len -= PAGE_SIZE;
...@@ -668,7 +666,6 @@ nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p, ...@@ -668,7 +666,6 @@ nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p,
rqstp->rq_res.page_len = resp->len; rqstp->rq_res.page_len = resp->len;
if (resp->len & 3) { if (resp->len & 3) {
/* need to pad the tail */ /* need to pad the tail */
rqstp->rq_restailpage = 0;
rqstp->rq_res.tail[0].iov_base = p; rqstp->rq_res.tail[0].iov_base = p;
*p = 0; *p = 0;
rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3); rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3);
...@@ -693,7 +690,6 @@ nfs3svc_encode_readres(struct svc_rqst *rqstp, u32 *p, ...@@ -693,7 +690,6 @@ nfs3svc_encode_readres(struct svc_rqst *rqstp, u32 *p,
rqstp->rq_res.page_len = resp->count; rqstp->rq_res.page_len = resp->count;
if (resp->count & 3) { if (resp->count & 3) {
/* need to pad the tail */ /* need to pad the tail */
rqstp->rq_restailpage = 0;
rqstp->rq_res.tail[0].iov_base = p; rqstp->rq_res.tail[0].iov_base = p;
*p = 0; *p = 0;
rqstp->rq_res.tail[0].iov_len = 4 - (resp->count & 3); rqstp->rq_res.tail[0].iov_len = 4 - (resp->count & 3);
...@@ -768,7 +764,6 @@ nfs3svc_encode_readdirres(struct svc_rqst *rqstp, u32 *p, ...@@ -768,7 +764,6 @@ nfs3svc_encode_readdirres(struct svc_rqst *rqstp, u32 *p,
rqstp->rq_res.page_len = (resp->count) << 2; rqstp->rq_res.page_len = (resp->count) << 2;
/* add the 'tail' to the end of the 'head' page - page 0. */ /* add the 'tail' to the end of the 'head' page - page 0. */
rqstp->rq_restailpage = 0;
rqstp->rq_res.tail[0].iov_base = p; rqstp->rq_res.tail[0].iov_base = p;
*p++ = 0; /* no more entries */ *p++ = 0; /* no more entries */
*p++ = htonl(resp->common.err == nfserr_eof); *p++ = htonl(resp->common.err == nfserr_eof);
......
...@@ -2039,7 +2039,8 @@ nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, int nfserr, struct n ...@@ -2039,7 +2039,8 @@ nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, int nfserr, struct n
} }
static int static int
nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read *read) nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr,
struct nfsd4_read *read)
{ {
u32 eof; u32 eof;
int v, pn; int v, pn;
...@@ -2061,10 +2062,11 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read ...@@ -2061,10 +2062,11 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read
len = maxcount; len = maxcount;
v = 0; v = 0;
while (len > 0) { while (len > 0) {
pn = resp->rqstp->rq_resused; pn = resp->rqstp->rq_resused++;
svc_take_page(resp->rqstp); read->rd_iov[v].iov_base =
read->rd_iov[v].iov_base = page_address(resp->rqstp->rq_respages[pn]); page_address(resp->rqstp->rq_respages[pn]);
read->rd_iov[v].iov_len = len < PAGE_SIZE ? len : PAGE_SIZE; read->rd_iov[v].iov_len =
len < PAGE_SIZE ? len : PAGE_SIZE;
v++; v++;
len -= PAGE_SIZE; len -= PAGE_SIZE;
} }
...@@ -2078,7 +2080,8 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read ...@@ -2078,7 +2080,8 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read
nfserr = nfserr_inval; nfserr = nfserr_inval;
if (nfserr) if (nfserr)
return nfserr; return nfserr;
eof = (read->rd_offset + maxcount >= read->rd_fhp->fh_dentry->d_inode->i_size); eof = (read->rd_offset + maxcount >=
read->rd_fhp->fh_dentry->d_inode->i_size);
WRITE32(eof); WRITE32(eof);
WRITE32(maxcount); WRITE32(maxcount);
...@@ -2088,7 +2091,6 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read ...@@ -2088,7 +2091,6 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read
resp->xbuf->page_len = maxcount; resp->xbuf->page_len = maxcount;
/* Use rest of head for padding and remaining ops: */ /* Use rest of head for padding and remaining ops: */
resp->rqstp->rq_restailpage = 0;
resp->xbuf->tail[0].iov_base = p; resp->xbuf->tail[0].iov_base = p;
resp->xbuf->tail[0].iov_len = 0; resp->xbuf->tail[0].iov_len = 0;
if (maxcount&3) { if (maxcount&3) {
...@@ -2113,8 +2115,7 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r ...@@ -2113,8 +2115,7 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r
if (resp->xbuf->page_len) if (resp->xbuf->page_len)
return nfserr_resource; return nfserr_resource;
svc_take_page(resp->rqstp); page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]);
page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
maxcount = PAGE_SIZE; maxcount = PAGE_SIZE;
RESERVE_SPACE(4); RESERVE_SPACE(4);
...@@ -2138,7 +2139,6 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r ...@@ -2138,7 +2139,6 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r
resp->xbuf->page_len = maxcount; resp->xbuf->page_len = maxcount;
/* Use rest of head for padding and remaining ops: */ /* Use rest of head for padding and remaining ops: */
resp->rqstp->rq_restailpage = 0;
resp->xbuf->tail[0].iov_base = p; resp->xbuf->tail[0].iov_base = p;
resp->xbuf->tail[0].iov_len = 0; resp->xbuf->tail[0].iov_len = 0;
if (maxcount&3) { if (maxcount&3) {
...@@ -2189,8 +2189,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re ...@@ -2189,8 +2189,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re
goto err_no_verf; goto err_no_verf;
} }
svc_take_page(resp->rqstp); page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]);
page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
readdir->common.err = 0; readdir->common.err = 0;
readdir->buflen = maxcount; readdir->buflen = maxcount;
readdir->buffer = page; readdir->buffer = page;
...@@ -2215,10 +2214,10 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re ...@@ -2215,10 +2214,10 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re
p = readdir->buffer; p = readdir->buffer;
*p++ = 0; /* no more entries */ *p++ = 0; /* no more entries */
*p++ = htonl(readdir->common.err == nfserr_eof); *p++ = htonl(readdir->common.err == nfserr_eof);
resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); resp->xbuf->page_len = ((char*)p) - (char*)page_address(
resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
/* Use rest of head for padding and remaining ops: */ /* Use rest of head for padding and remaining ops: */
resp->rqstp->rq_restailpage = 0;
resp->xbuf->tail[0].iov_base = tailbase; resp->xbuf->tail[0].iov_base = tailbase;
resp->xbuf->tail[0].iov_len = 0; resp->xbuf->tail[0].iov_len = 0;
resp->p = resp->xbuf->tail[0].iov_base; resp->p = resp->xbuf->tail[0].iov_base;
......
...@@ -262,8 +262,7 @@ nfssvc_decode_readargs(struct svc_rqst *rqstp, u32 *p, ...@@ -262,8 +262,7 @@ nfssvc_decode_readargs(struct svc_rqst *rqstp, u32 *p,
*/ */
v=0; v=0;
while (len > 0) { while (len > 0) {
pn=rqstp->rq_resused; pn = rqstp->rq_resused++;
svc_take_page(rqstp);
args->vec[v].iov_base = page_address(rqstp->rq_respages[pn]); args->vec[v].iov_base = page_address(rqstp->rq_respages[pn]);
args->vec[v].iov_len = len < PAGE_SIZE?len:PAGE_SIZE; args->vec[v].iov_len = len < PAGE_SIZE?len:PAGE_SIZE;
len -= args->vec[v].iov_len; len -= args->vec[v].iov_len;
...@@ -295,7 +294,7 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, u32 *p, ...@@ -295,7 +294,7 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
while (len > args->vec[v].iov_len) { while (len > args->vec[v].iov_len) {
len -= args->vec[v].iov_len; len -= args->vec[v].iov_len;
v++; v++;
args->vec[v].iov_base = page_address(rqstp->rq_argpages[v]); args->vec[v].iov_base = page_address(rqstp->rq_pages[v]);
args->vec[v].iov_len = PAGE_SIZE; args->vec[v].iov_len = PAGE_SIZE;
} }
args->vec[v].iov_len = len; args->vec[v].iov_len = len;
...@@ -333,8 +332,7 @@ nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, u32 *p, struct nfsd_readlinka ...@@ -333,8 +332,7 @@ nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, u32 *p, struct nfsd_readlinka
{ {
if (!(p = decode_fh(p, &args->fh))) if (!(p = decode_fh(p, &args->fh)))
return 0; return 0;
svc_take_page(rqstp); args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused++]);
args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused-1]);
return xdr_argsize_check(rqstp, p); return xdr_argsize_check(rqstp, p);
} }
...@@ -375,8 +373,7 @@ nfssvc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p, ...@@ -375,8 +373,7 @@ nfssvc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p,
if (args->count > PAGE_SIZE) if (args->count > PAGE_SIZE)
args->count = PAGE_SIZE; args->count = PAGE_SIZE;
svc_take_page(rqstp); args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused++]);
args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused-1]);
return xdr_argsize_check(rqstp, p); return xdr_argsize_check(rqstp, p);
} }
...@@ -416,7 +413,6 @@ nfssvc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p, ...@@ -416,7 +413,6 @@ nfssvc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p,
rqstp->rq_res.page_len = resp->len; rqstp->rq_res.page_len = resp->len;
if (resp->len & 3) { if (resp->len & 3) {
/* need to pad the tail */ /* need to pad the tail */
rqstp->rq_restailpage = 0;
rqstp->rq_res.tail[0].iov_base = p; rqstp->rq_res.tail[0].iov_base = p;
*p = 0; *p = 0;
rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3); rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3);
...@@ -436,7 +432,6 @@ nfssvc_encode_readres(struct svc_rqst *rqstp, u32 *p, ...@@ -436,7 +432,6 @@ nfssvc_encode_readres(struct svc_rqst *rqstp, u32 *p,
rqstp->rq_res.page_len = resp->count; rqstp->rq_res.page_len = resp->count;
if (resp->count & 3) { if (resp->count & 3) {
/* need to pad the tail */ /* need to pad the tail */
rqstp->rq_restailpage = 0;
rqstp->rq_res.tail[0].iov_base = p; rqstp->rq_res.tail[0].iov_base = p;
*p = 0; *p = 0;
rqstp->rq_res.tail[0].iov_len = 4 - (resp->count&3); rqstp->rq_res.tail[0].iov_len = 4 - (resp->count&3);
......
...@@ -791,22 +791,26 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset ...@@ -791,22 +791,26 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset
{ {
unsigned long count = desc->count; unsigned long count = desc->count;
struct svc_rqst *rqstp = desc->arg.data; struct svc_rqst *rqstp = desc->arg.data;
struct page **pp = rqstp->rq_respages + rqstp->rq_resused;
if (size > count) if (size > count)
size = count; size = count;
if (rqstp->rq_res.page_len == 0) { if (rqstp->rq_res.page_len == 0) {
get_page(page); get_page(page);
rqstp->rq_respages[rqstp->rq_resused++] = page; put_page(*pp);
*pp = page;
rqstp->rq_resused++;
rqstp->rq_res.page_base = offset; rqstp->rq_res.page_base = offset;
rqstp->rq_res.page_len = size; rqstp->rq_res.page_len = size;
} else if (page != rqstp->rq_respages[rqstp->rq_resused-1]) { } else if (page != pp[-1]) {
get_page(page); get_page(page);
rqstp->rq_respages[rqstp->rq_resused++] = page; put_page(*pp);
*pp = page;
rqstp->rq_resused++;
rqstp->rq_res.page_len += size; rqstp->rq_res.page_len += size;
} else { } else
rqstp->rq_res.page_len += size; rqstp->rq_res.page_len += size;
}
desc->count = count - size; desc->count = count - size;
desc->written += size; desc->written += size;
...@@ -837,7 +841,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, ...@@ -837,7 +841,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
file->f_ra = ra->p_ra; file->f_ra = ra->p_ra;
if (file->f_op->sendfile && rqstp->rq_sendfile_ok) { if (file->f_op->sendfile && rqstp->rq_sendfile_ok) {
svc_pushback_unused_pages(rqstp); rqstp->rq_resused = 1;
err = file->f_op->sendfile(file, &offset, *count, err = file->f_op->sendfile(file, &offset, *count,
nfsd_read_actor, rqstp); nfsd_read_actor, rqstp);
} else { } else {
......
...@@ -170,7 +170,6 @@ static inline void svc_putu32(struct kvec *iov, __be32 val) ...@@ -170,7 +170,6 @@ static inline void svc_putu32(struct kvec *iov, __be32 val)
/* /*
* The context of a single thread, including the request currently being * The context of a single thread, including the request currently being
* processed. * processed.
* NOTE: First two items must be prev/next.
*/ */
struct svc_rqst { struct svc_rqst {
struct list_head rq_list; /* idle list */ struct list_head rq_list; /* idle list */
...@@ -189,12 +188,9 @@ struct svc_rqst { ...@@ -189,12 +188,9 @@ struct svc_rqst {
struct xdr_buf rq_arg; struct xdr_buf rq_arg;
struct xdr_buf rq_res; struct xdr_buf rq_res;
struct page * rq_argpages[RPCSVC_MAXPAGES]; struct page * rq_pages[RPCSVC_MAXPAGES];
struct page * rq_respages[RPCSVC_MAXPAGES]; struct page * *rq_respages; /* points into rq_pages */
int rq_restailpage; int rq_resused; /* number of pages used for result */
short rq_argused; /* pages used for argument */
short rq_arghi; /* pages available in argument page list */
short rq_resused; /* pages used for result */
__be32 rq_xid; /* transmission id */ __be32 rq_xid; /* transmission id */
u32 rq_prog; /* program number */ u32 rq_prog; /* program number */
...@@ -255,63 +251,18 @@ xdr_ressize_check(struct svc_rqst *rqstp, __be32 *p) ...@@ -255,63 +251,18 @@ xdr_ressize_check(struct svc_rqst *rqstp, __be32 *p)
return vec->iov_len <= PAGE_SIZE; return vec->iov_len <= PAGE_SIZE;
} }
static inline struct page * static inline void svc_free_res_pages(struct svc_rqst *rqstp)
svc_take_res_page(struct svc_rqst *rqstp)
{ {
if (rqstp->rq_arghi <= rqstp->rq_argused) while (rqstp->rq_resused) {
return NULL; struct page **pp = (rqstp->rq_respages +
rqstp->rq_arghi--; --rqstp->rq_resused);
rqstp->rq_respages[rqstp->rq_resused] = if (*pp) {
rqstp->rq_argpages[rqstp->rq_arghi]; put_page(*pp);
return rqstp->rq_respages[rqstp->rq_resused++]; *pp = NULL;
}
static inline void svc_take_page(struct svc_rqst *rqstp)
{
if (rqstp->rq_arghi <= rqstp->rq_argused) {
WARN_ON(1);
return;
}
rqstp->rq_arghi--;
rqstp->rq_respages[rqstp->rq_resused] =
rqstp->rq_argpages[rqstp->rq_arghi];
rqstp->rq_resused++;
}
static inline void svc_pushback_allpages(struct svc_rqst *rqstp)
{
while (rqstp->rq_resused) {
if (rqstp->rq_respages[--rqstp->rq_resused] == NULL)
continue;
rqstp->rq_argpages[rqstp->rq_arghi++] =
rqstp->rq_respages[rqstp->rq_resused];
rqstp->rq_respages[rqstp->rq_resused] = NULL;
}
}
static inline void svc_pushback_unused_pages(struct svc_rqst *rqstp)
{
while (rqstp->rq_resused &&
rqstp->rq_res.pages != &rqstp->rq_respages[rqstp->rq_resused]) {
if (rqstp->rq_respages[--rqstp->rq_resused] != NULL) {
rqstp->rq_argpages[rqstp->rq_arghi++] =
rqstp->rq_respages[rqstp->rq_resused];
rqstp->rq_respages[rqstp->rq_resused] = NULL;
} }
} }
} }
static inline void svc_free_allpages(struct svc_rqst *rqstp)
{
while (rqstp->rq_resused) {
if (rqstp->rq_respages[--rqstp->rq_resused] == NULL)
continue;
put_page(rqstp->rq_respages[rqstp->rq_resused]);
rqstp->rq_respages[rqstp->rq_resused] = NULL;
}
}
struct svc_deferred_req { struct svc_deferred_req {
u32 prot; /* protocol (UDP or TCP) */ u32 prot; /* protocol (UDP or TCP) */
struct sockaddr_in addr; struct sockaddr_in addr;
......
...@@ -1191,7 +1191,6 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp) ...@@ -1191,7 +1191,6 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)
resbuf->tail[0].iov_base = resbuf->head[0].iov_base resbuf->tail[0].iov_base = resbuf->head[0].iov_base
+ resbuf->head[0].iov_len; + resbuf->head[0].iov_len;
resbuf->tail[0].iov_len = 0; resbuf->tail[0].iov_len = 0;
rqstp->rq_restailpage = 0;
resv = &resbuf->tail[0]; resv = &resbuf->tail[0];
} else { } else {
resv = &resbuf->tail[0]; resv = &resbuf->tail[0];
...@@ -1240,7 +1239,7 @@ svcauth_gss_wrap_resp_priv(struct svc_rqst *rqstp) ...@@ -1240,7 +1239,7 @@ svcauth_gss_wrap_resp_priv(struct svc_rqst *rqstp)
inpages = resbuf->pages; inpages = resbuf->pages;
/* XXX: Would be better to write some xdr helper functions for /* XXX: Would be better to write some xdr helper functions for
* nfs{2,3,4}xdr.c that place the data right, instead of copying: */ * nfs{2,3,4}xdr.c that place the data right, instead of copying: */
if (resbuf->tail[0].iov_base && rqstp->rq_restailpage == 0) { if (resbuf->tail[0].iov_base) {
BUG_ON(resbuf->tail[0].iov_base >= resbuf->head[0].iov_base BUG_ON(resbuf->tail[0].iov_base >= resbuf->head[0].iov_base
+ PAGE_SIZE); + PAGE_SIZE);
BUG_ON(resbuf->tail[0].iov_base < resbuf->head[0].iov_base); BUG_ON(resbuf->tail[0].iov_base < resbuf->head[0].iov_base);
...@@ -1258,7 +1257,6 @@ svcauth_gss_wrap_resp_priv(struct svc_rqst *rqstp) ...@@ -1258,7 +1257,6 @@ svcauth_gss_wrap_resp_priv(struct svc_rqst *rqstp)
resbuf->tail[0].iov_base = resbuf->head[0].iov_base resbuf->tail[0].iov_base = resbuf->head[0].iov_base
+ resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE; + resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE;
resbuf->tail[0].iov_len = 0; resbuf->tail[0].iov_len = 0;
rqstp->rq_restailpage = 0;
} }
if (gss_wrap(gsd->rsci->mechctx, offset, resbuf, inpages)) if (gss_wrap(gsd->rsci->mechctx, offset, resbuf, inpages))
return -ENOMEM; return -ENOMEM;
......
...@@ -417,18 +417,15 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size) ...@@ -417,18 +417,15 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size)
if (size > RPCSVC_MAXPAYLOAD) if (size > RPCSVC_MAXPAYLOAD)
size = RPCSVC_MAXPAYLOAD; size = RPCSVC_MAXPAYLOAD;
pages = 2 + (size+ PAGE_SIZE -1) / PAGE_SIZE; pages = 2 + (size+ PAGE_SIZE -1) / PAGE_SIZE;
rqstp->rq_argused = 0;
rqstp->rq_resused = 0;
arghi = 0; arghi = 0;
BUG_ON(pages > RPCSVC_MAXPAGES); BUG_ON(pages > RPCSVC_MAXPAGES);
while (pages) { while (pages) {
struct page *p = alloc_page(GFP_KERNEL); struct page *p = alloc_page(GFP_KERNEL);
if (!p) if (!p)
break; break;
rqstp->rq_argpages[arghi++] = p; rqstp->rq_pages[arghi++] = p;
pages--; pages--;
} }
rqstp->rq_arghi = arghi;
return ! pages; return ! pages;
} }
...@@ -438,14 +435,10 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size) ...@@ -438,14 +435,10 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size)
static void static void
svc_release_buffer(struct svc_rqst *rqstp) svc_release_buffer(struct svc_rqst *rqstp)
{ {
while (rqstp->rq_arghi) int i;
put_page(rqstp->rq_argpages[--rqstp->rq_arghi]); for (i=0; i<ARRAY_SIZE(rqstp->rq_pages); i++)
while (rqstp->rq_resused) { if (rqstp->rq_pages[i])
if (rqstp->rq_respages[--rqstp->rq_resused] == NULL) put_page(rqstp->rq_pages[i]);
continue;
put_page(rqstp->rq_respages[rqstp->rq_resused]);
}
rqstp->rq_argused = 0;
} }
/* /*
...@@ -707,10 +700,10 @@ svc_process(struct svc_rqst *rqstp) ...@@ -707,10 +700,10 @@ svc_process(struct svc_rqst *rqstp)
/* setup response xdr_buf. /* setup response xdr_buf.
* Initially it has just one page * Initially it has just one page
*/ */
svc_take_page(rqstp); /* must succeed */ rqstp->rq_resused = 1;
resv->iov_base = page_address(rqstp->rq_respages[0]); resv->iov_base = page_address(rqstp->rq_respages[0]);
resv->iov_len = 0; resv->iov_len = 0;
rqstp->rq_res.pages = rqstp->rq_respages+1; rqstp->rq_res.pages = rqstp->rq_respages + 1;
rqstp->rq_res.len = 0; rqstp->rq_res.len = 0;
rqstp->rq_res.page_base = 0; rqstp->rq_res.page_base = 0;
rqstp->rq_res.page_len = 0; rqstp->rq_res.page_len = 0;
......
...@@ -313,7 +313,7 @@ svc_sock_release(struct svc_rqst *rqstp) ...@@ -313,7 +313,7 @@ svc_sock_release(struct svc_rqst *rqstp)
svc_release_skb(rqstp); svc_release_skb(rqstp);
svc_free_allpages(rqstp); svc_free_res_pages(rqstp);
rqstp->rq_res.page_len = 0; rqstp->rq_res.page_len = 0;
rqstp->rq_res.page_base = 0; rqstp->rq_res.page_base = 0;
...@@ -412,7 +412,8 @@ svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr) ...@@ -412,7 +412,8 @@ svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr)
/* send head */ /* send head */
if (slen == xdr->head[0].iov_len) if (slen == xdr->head[0].iov_len)
flags = 0; flags = 0;
len = kernel_sendpage(sock, rqstp->rq_respages[0], 0, xdr->head[0].iov_len, flags); len = kernel_sendpage(sock, rqstp->rq_respages[0], 0,
xdr->head[0].iov_len, flags);
if (len != xdr->head[0].iov_len) if (len != xdr->head[0].iov_len)
goto out; goto out;
slen -= xdr->head[0].iov_len; slen -= xdr->head[0].iov_len;
...@@ -437,8 +438,9 @@ svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr) ...@@ -437,8 +438,9 @@ svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr)
} }
/* send tail */ /* send tail */
if (xdr->tail[0].iov_len) { if (xdr->tail[0].iov_len) {
result = kernel_sendpage(sock, rqstp->rq_respages[rqstp->rq_restailpage], result = kernel_sendpage(sock, rqstp->rq_respages[0],
((unsigned long)xdr->tail[0].iov_base)& (PAGE_SIZE-1), ((unsigned long)xdr->tail[0].iov_base)
& (PAGE_SIZE-1),
xdr->tail[0].iov_len, 0); xdr->tail[0].iov_len, 0);
if (result > 0) if (result > 0)
...@@ -708,9 +710,11 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) ...@@ -708,9 +710,11 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
if (len <= rqstp->rq_arg.head[0].iov_len) { if (len <= rqstp->rq_arg.head[0].iov_len) {
rqstp->rq_arg.head[0].iov_len = len; rqstp->rq_arg.head[0].iov_len = len;
rqstp->rq_arg.page_len = 0; rqstp->rq_arg.page_len = 0;
rqstp->rq_respages = rqstp->rq_pages+1;
} else { } else {
rqstp->rq_arg.page_len = len - rqstp->rq_arg.head[0].iov_len; rqstp->rq_arg.page_len = len - rqstp->rq_arg.head[0].iov_len;
rqstp->rq_argused += (rqstp->rq_arg.page_len + PAGE_SIZE - 1)/ PAGE_SIZE; rqstp->rq_respages = rqstp->rq_pages + 1 +
(rqstp->rq_arg.page_len + PAGE_SIZE - 1)/ PAGE_SIZE;
} }
if (serv->sv_stats) if (serv->sv_stats)
...@@ -1053,11 +1057,12 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp) ...@@ -1053,11 +1057,12 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp)
vlen = PAGE_SIZE; vlen = PAGE_SIZE;
pnum = 1; pnum = 1;
while (vlen < len) { while (vlen < len) {
vec[pnum].iov_base = page_address(rqstp->rq_argpages[rqstp->rq_argused++]); vec[pnum].iov_base = page_address(rqstp->rq_pages[pnum]);
vec[pnum].iov_len = PAGE_SIZE; vec[pnum].iov_len = PAGE_SIZE;
pnum++; pnum++;
vlen += PAGE_SIZE; vlen += PAGE_SIZE;
} }
rqstp->rq_respages = &rqstp->rq_pages[pnum];
/* Now receive data */ /* Now receive data */
len = svc_recvfrom(rqstp, vec, pnum, len); len = svc_recvfrom(rqstp, vec, pnum, len);
...@@ -1209,7 +1214,7 @@ svc_recv(struct svc_rqst *rqstp, long timeout) ...@@ -1209,7 +1214,7 @@ svc_recv(struct svc_rqst *rqstp, long timeout)
struct svc_sock *svsk =NULL; struct svc_sock *svsk =NULL;
struct svc_serv *serv = rqstp->rq_server; struct svc_serv *serv = rqstp->rq_server;
struct svc_pool *pool = rqstp->rq_pool; struct svc_pool *pool = rqstp->rq_pool;
int len; int len, i;
int pages; int pages;
struct xdr_buf *arg; struct xdr_buf *arg;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
...@@ -1226,27 +1231,22 @@ svc_recv(struct svc_rqst *rqstp, long timeout) ...@@ -1226,27 +1231,22 @@ svc_recv(struct svc_rqst *rqstp, long timeout)
"svc_recv: service %p, wait queue active!\n", "svc_recv: service %p, wait queue active!\n",
rqstp); rqstp);
/* Initialize the buffers */
/* first reclaim pages that were moved to response list */
svc_pushback_allpages(rqstp);
/* now allocate needed pages. If we get a failure, sleep briefly */ /* now allocate needed pages. If we get a failure, sleep briefly */
pages = 2 + (serv->sv_bufsz + PAGE_SIZE -1) / PAGE_SIZE; pages = 2 + (serv->sv_bufsz + PAGE_SIZE -1) / PAGE_SIZE;
while (rqstp->rq_arghi < pages) { for (i=0; i < pages ; i++)
struct page *p = alloc_page(GFP_KERNEL); while (rqstp->rq_pages[i] == NULL) {
if (!p) { struct page *p = alloc_page(GFP_KERNEL);
schedule_timeout_uninterruptible(msecs_to_jiffies(500)); if (!p)
continue; schedule_timeout_uninterruptible(msecs_to_jiffies(500));
rqstp->rq_pages[i] = p;
} }
rqstp->rq_argpages[rqstp->rq_arghi++] = p;
}
/* Make arg->head point to first page and arg->pages point to rest */ /* Make arg->head point to first page and arg->pages point to rest */
arg = &rqstp->rq_arg; arg = &rqstp->rq_arg;
arg->head[0].iov_base = page_address(rqstp->rq_argpages[0]); arg->head[0].iov_base = page_address(rqstp->rq_pages[0]);
arg->head[0].iov_len = PAGE_SIZE; arg->head[0].iov_len = PAGE_SIZE;
rqstp->rq_argused = 1; arg->pages = rqstp->rq_pages + 1;
arg->pages = rqstp->rq_argpages + 1;
arg->page_base = 0; arg->page_base = 0;
/* save at least one page for response */ /* save at least one page for response */
arg->page_len = (pages-2)*PAGE_SIZE; arg->page_len = (pages-2)*PAGE_SIZE;
...@@ -1704,6 +1704,7 @@ static int svc_deferred_recv(struct svc_rqst *rqstp) ...@@ -1704,6 +1704,7 @@ static int svc_deferred_recv(struct svc_rqst *rqstp)
rqstp->rq_prot = dr->prot; rqstp->rq_prot = dr->prot;
rqstp->rq_addr = dr->addr; rqstp->rq_addr = dr->addr;
rqstp->rq_daddr = dr->daddr; rqstp->rq_daddr = dr->daddr;
rqstp->rq_respages = rqstp->rq_pages;
return dr->argslen<<2; return dr->argslen<<2;
} }
......
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