diff options
author | NeilBrown <neilb@suse.de> | 2006-10-04 05:15:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-04 10:55:15 -0400 |
commit | 4452435948424e5322c2a2fefbdc2cf3732cc45d (patch) | |
tree | d2082c68d33298e85298852cafde7999ccca3364 /fs | |
parent | 5680c44632053a6c9464bca43083f01776d318da (diff) |
[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: Neil Brown <neilb@suse.de>
Cc: Magnus Maatta <novell@kiruna.se>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfsd/nfs2acl.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs3acl.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs3xdr.c | 23 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 27 | ||||
-rw-r--r-- | fs/nfsd/nfsxdr.c | 13 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 16 |
6 files changed, 38 insertions, 45 deletions
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c index fe56b38364cc..71108da2e54e 100644 --- a/fs/nfsd/nfs2acl.c +++ b/fs/nfsd/nfs2acl.c | |||
@@ -241,7 +241,7 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, u32 *p, | |||
241 | 241 | ||
242 | rqstp->rq_res.page_len = w; | 242 | rqstp->rq_res.page_len = w; |
243 | while (w > 0) { | 243 | while (w > 0) { |
244 | if (!svc_take_res_page(rqstp)) | 244 | if (!rqstp->rq_respages[rqstp->rq_resused++]) |
245 | return 0; | 245 | return 0; |
246 | w -= PAGE_SIZE; | 246 | w -= PAGE_SIZE; |
247 | } | 247 | } |
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c index 16e10c170aed..f813b054f4a1 100644 --- a/fs/nfsd/nfs3acl.c +++ b/fs/nfsd/nfs3acl.c | |||
@@ -185,7 +185,7 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, u32 *p, | |||
185 | 185 | ||
186 | rqstp->rq_res.page_len = w; | 186 | rqstp->rq_res.page_len = w; |
187 | while (w > 0) { | 187 | while (w > 0) { |
188 | if (!svc_take_res_page(rqstp)) | 188 | if (!rqstp->rq_respages[rqstp->rq_resused++]) |
189 | return 0; | 189 | return 0; |
190 | w -= PAGE_SIZE; | 190 | w -= PAGE_SIZE; |
191 | } | 191 | } |
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 243d94b9653a..20ba728a4642 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c | |||
@@ -343,8 +343,7 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, u32 *p, | |||
343 | /* set up the kvec */ | 343 | /* set up the kvec */ |
344 | v=0; | 344 | v=0; |
345 | while (len > 0) { | 345 | while (len > 0) { |
346 | pn = rqstp->rq_resused; | 346 | pn = rqstp->rq_resused++; |
347 | svc_take_page(rqstp); | ||
348 | args->vec[v].iov_base = page_address(rqstp->rq_respages[pn]); | 347 | args->vec[v].iov_base = page_address(rqstp->rq_respages[pn]); |
349 | args->vec[v].iov_len = len < PAGE_SIZE? len : PAGE_SIZE; | 348 | args->vec[v].iov_len = len < PAGE_SIZE? len : PAGE_SIZE; |
350 | len -= args->vec[v].iov_len; | 349 | len -= args->vec[v].iov_len; |
@@ -382,7 +381,7 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p, | |||
382 | while (len > args->vec[v].iov_len) { | 381 | while (len > args->vec[v].iov_len) { |
383 | len -= args->vec[v].iov_len; | 382 | len -= args->vec[v].iov_len; |
384 | v++; | 383 | v++; |
385 | args->vec[v].iov_base = page_address(rqstp->rq_argpages[v]); | 384 | args->vec[v].iov_base = page_address(rqstp->rq_pages[v]); |
386 | args->vec[v].iov_len = PAGE_SIZE; | 385 | args->vec[v].iov_len = PAGE_SIZE; |
387 | } | 386 | } |
388 | args->vec[v].iov_len = len; | 387 | args->vec[v].iov_len = len; |
@@ -446,11 +445,11 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p, | |||
446 | * This page appears in the rq_res.pages list, but as pages_len is always | 445 | * This page appears in the rq_res.pages list, but as pages_len is always |
447 | * 0, it won't get in the way | 446 | * 0, it won't get in the way |
448 | */ | 447 | */ |
449 | svc_take_page(rqstp); | ||
450 | len = ntohl(*p++); | 448 | len = ntohl(*p++); |
451 | if (len == 0 || len > NFS3_MAXPATHLEN || len >= PAGE_SIZE) | 449 | if (len == 0 || len > NFS3_MAXPATHLEN || len >= PAGE_SIZE) |
452 | return 0; | 450 | return 0; |
453 | args->tname = new = page_address(rqstp->rq_respages[rqstp->rq_resused-1]); | 451 | args->tname = new = |
452 | page_address(rqstp->rq_respages[rqstp->rq_resused++]); | ||
454 | args->tlen = len; | 453 | args->tlen = len; |
455 | /* first copy and check from the first page */ | 454 | /* first copy and check from the first page */ |
456 | old = (char*)p; | 455 | old = (char*)p; |
@@ -522,8 +521,8 @@ nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, u32 *p, | |||
522 | { | 521 | { |
523 | if (!(p = decode_fh(p, &args->fh))) | 522 | if (!(p = decode_fh(p, &args->fh))) |
524 | return 0; | 523 | return 0; |
525 | svc_take_page(rqstp); | 524 | args->buffer = |
526 | args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused-1]); | 525 | page_address(rqstp->rq_respages[rqstp->rq_resused++]); |
527 | 526 | ||
528 | return xdr_argsize_check(rqstp, p); | 527 | return xdr_argsize_check(rqstp, p); |
529 | } | 528 | } |
@@ -554,8 +553,8 @@ nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p, | |||
554 | if (args->count > PAGE_SIZE) | 553 | if (args->count > PAGE_SIZE) |
555 | args->count = PAGE_SIZE; | 554 | args->count = PAGE_SIZE; |
556 | 555 | ||
557 | svc_take_page(rqstp); | 556 | args->buffer = |
558 | args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused-1]); | 557 | page_address(rqstp->rq_respages[rqstp->rq_resused++]); |
559 | 558 | ||
560 | return xdr_argsize_check(rqstp, p); | 559 | return xdr_argsize_check(rqstp, p); |
561 | } | 560 | } |
@@ -578,8 +577,7 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, u32 *p, | |||
578 | args->count = len; | 577 | args->count = len; |
579 | 578 | ||
580 | while (len > 0) { | 579 | while (len > 0) { |
581 | pn = rqstp->rq_resused; | 580 | pn = rqstp->rq_resused++; |
582 | svc_take_page(rqstp); | ||
583 | if (!args->buffer) | 581 | if (!args->buffer) |
584 | args->buffer = page_address(rqstp->rq_respages[pn]); | 582 | args->buffer = page_address(rqstp->rq_respages[pn]); |
585 | len -= PAGE_SIZE; | 583 | len -= PAGE_SIZE; |
@@ -668,7 +666,6 @@ nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p, | |||
668 | rqstp->rq_res.page_len = resp->len; | 666 | rqstp->rq_res.page_len = resp->len; |
669 | if (resp->len & 3) { | 667 | if (resp->len & 3) { |
670 | /* need to pad the tail */ | 668 | /* need to pad the tail */ |
671 | rqstp->rq_restailpage = 0; | ||
672 | rqstp->rq_res.tail[0].iov_base = p; | 669 | rqstp->rq_res.tail[0].iov_base = p; |
673 | *p = 0; | 670 | *p = 0; |
674 | rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3); | 671 | 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 | rqstp->rq_res.page_len = resp->count; | 690 | rqstp->rq_res.page_len = resp->count; |
694 | if (resp->count & 3) { | 691 | if (resp->count & 3) { |
695 | /* need to pad the tail */ | 692 | /* need to pad the tail */ |
696 | rqstp->rq_restailpage = 0; | ||
697 | rqstp->rq_res.tail[0].iov_base = p; | 693 | rqstp->rq_res.tail[0].iov_base = p; |
698 | *p = 0; | 694 | *p = 0; |
699 | rqstp->rq_res.tail[0].iov_len = 4 - (resp->count & 3); | 695 | 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 | rqstp->rq_res.page_len = (resp->count) << 2; | 764 | rqstp->rq_res.page_len = (resp->count) << 2; |
769 | 765 | ||
770 | /* add the 'tail' to the end of the 'head' page - page 0. */ | 766 | /* add the 'tail' to the end of the 'head' page - page 0. */ |
771 | rqstp->rq_restailpage = 0; | ||
772 | rqstp->rq_res.tail[0].iov_base = p; | 767 | rqstp->rq_res.tail[0].iov_base = p; |
773 | *p++ = 0; /* no more entries */ | 768 | *p++ = 0; /* no more entries */ |
774 | *p++ = htonl(resp->common.err == nfserr_eof); | 769 | *p++ = htonl(resp->common.err == nfserr_eof); |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 5be00436b5b8..9f30c53ac0ed 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -2039,7 +2039,8 @@ nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, int nfserr, struct n | |||
2039 | } | 2039 | } |
2040 | 2040 | ||
2041 | static int | 2041 | static int |
2042 | nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read *read) | 2042 | nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, |
2043 | struct nfsd4_read *read) | ||
2043 | { | 2044 | { |
2044 | u32 eof; | 2045 | u32 eof; |
2045 | int v, pn; | 2046 | int v, pn; |
@@ -2061,10 +2062,11 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read | |||
2061 | len = maxcount; | 2062 | len = maxcount; |
2062 | v = 0; | 2063 | v = 0; |
2063 | while (len > 0) { | 2064 | while (len > 0) { |
2064 | pn = resp->rqstp->rq_resused; | 2065 | pn = resp->rqstp->rq_resused++; |
2065 | svc_take_page(resp->rqstp); | 2066 | read->rd_iov[v].iov_base = |
2066 | read->rd_iov[v].iov_base = page_address(resp->rqstp->rq_respages[pn]); | 2067 | page_address(resp->rqstp->rq_respages[pn]); |
2067 | read->rd_iov[v].iov_len = len < PAGE_SIZE ? len : PAGE_SIZE; | 2068 | read->rd_iov[v].iov_len = |
2069 | len < PAGE_SIZE ? len : PAGE_SIZE; | ||
2068 | v++; | 2070 | v++; |
2069 | len -= PAGE_SIZE; | 2071 | len -= PAGE_SIZE; |
2070 | } | 2072 | } |
@@ -2078,7 +2080,8 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read | |||
2078 | nfserr = nfserr_inval; | 2080 | nfserr = nfserr_inval; |
2079 | if (nfserr) | 2081 | if (nfserr) |
2080 | return nfserr; | 2082 | return nfserr; |
2081 | eof = (read->rd_offset + maxcount >= read->rd_fhp->fh_dentry->d_inode->i_size); | 2083 | eof = (read->rd_offset + maxcount >= |
2084 | read->rd_fhp->fh_dentry->d_inode->i_size); | ||
2082 | 2085 | ||
2083 | WRITE32(eof); | 2086 | WRITE32(eof); |
2084 | WRITE32(maxcount); | 2087 | WRITE32(maxcount); |
@@ -2088,7 +2091,6 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read | |||
2088 | resp->xbuf->page_len = maxcount; | 2091 | resp->xbuf->page_len = maxcount; |
2089 | 2092 | ||
2090 | /* Use rest of head for padding and remaining ops: */ | 2093 | /* Use rest of head for padding and remaining ops: */ |
2091 | resp->rqstp->rq_restailpage = 0; | ||
2092 | resp->xbuf->tail[0].iov_base = p; | 2094 | resp->xbuf->tail[0].iov_base = p; |
2093 | resp->xbuf->tail[0].iov_len = 0; | 2095 | resp->xbuf->tail[0].iov_len = 0; |
2094 | if (maxcount&3) { | 2096 | if (maxcount&3) { |
@@ -2113,8 +2115,7 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r | |||
2113 | if (resp->xbuf->page_len) | 2115 | if (resp->xbuf->page_len) |
2114 | return nfserr_resource; | 2116 | return nfserr_resource; |
2115 | 2117 | ||
2116 | svc_take_page(resp->rqstp); | 2118 | page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]); |
2117 | page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); | ||
2118 | 2119 | ||
2119 | maxcount = PAGE_SIZE; | 2120 | maxcount = PAGE_SIZE; |
2120 | RESERVE_SPACE(4); | 2121 | RESERVE_SPACE(4); |
@@ -2138,7 +2139,6 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r | |||
2138 | resp->xbuf->page_len = maxcount; | 2139 | resp->xbuf->page_len = maxcount; |
2139 | 2140 | ||
2140 | /* Use rest of head for padding and remaining ops: */ | 2141 | /* Use rest of head for padding and remaining ops: */ |
2141 | resp->rqstp->rq_restailpage = 0; | ||
2142 | resp->xbuf->tail[0].iov_base = p; | 2142 | resp->xbuf->tail[0].iov_base = p; |
2143 | resp->xbuf->tail[0].iov_len = 0; | 2143 | resp->xbuf->tail[0].iov_len = 0; |
2144 | if (maxcount&3) { | 2144 | if (maxcount&3) { |
@@ -2189,8 +2189,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re | |||
2189 | goto err_no_verf; | 2189 | goto err_no_verf; |
2190 | } | 2190 | } |
2191 | 2191 | ||
2192 | svc_take_page(resp->rqstp); | 2192 | page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]); |
2193 | page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); | ||
2194 | readdir->common.err = 0; | 2193 | readdir->common.err = 0; |
2195 | readdir->buflen = maxcount; | 2194 | readdir->buflen = maxcount; |
2196 | readdir->buffer = page; | 2195 | readdir->buffer = page; |
@@ -2215,10 +2214,10 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re | |||
2215 | p = readdir->buffer; | 2214 | p = readdir->buffer; |
2216 | *p++ = 0; /* no more entries */ | 2215 | *p++ = 0; /* no more entries */ |
2217 | *p++ = htonl(readdir->common.err == nfserr_eof); | 2216 | *p++ = htonl(readdir->common.err == nfserr_eof); |
2218 | resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); | 2217 | resp->xbuf->page_len = ((char*)p) - (char*)page_address( |
2218 | resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); | ||
2219 | 2219 | ||
2220 | /* Use rest of head for padding and remaining ops: */ | 2220 | /* Use rest of head for padding and remaining ops: */ |
2221 | resp->rqstp->rq_restailpage = 0; | ||
2222 | resp->xbuf->tail[0].iov_base = tailbase; | 2221 | resp->xbuf->tail[0].iov_base = tailbase; |
2223 | resp->xbuf->tail[0].iov_len = 0; | 2222 | resp->xbuf->tail[0].iov_len = 0; |
2224 | resp->p = resp->xbuf->tail[0].iov_base; | 2223 | resp->p = resp->xbuf->tail[0].iov_base; |
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index 3f14a17eaa6e..ad2fba3c54f8 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c | |||
@@ -262,8 +262,7 @@ nfssvc_decode_readargs(struct svc_rqst *rqstp, u32 *p, | |||
262 | */ | 262 | */ |
263 | v=0; | 263 | v=0; |
264 | while (len > 0) { | 264 | while (len > 0) { |
265 | pn=rqstp->rq_resused; | 265 | pn = rqstp->rq_resused++; |
266 | svc_take_page(rqstp); | ||
267 | args->vec[v].iov_base = page_address(rqstp->rq_respages[pn]); | 266 | args->vec[v].iov_base = page_address(rqstp->rq_respages[pn]); |
268 | args->vec[v].iov_len = len < PAGE_SIZE?len:PAGE_SIZE; | 267 | args->vec[v].iov_len = len < PAGE_SIZE?len:PAGE_SIZE; |
269 | len -= args->vec[v].iov_len; | 268 | len -= args->vec[v].iov_len; |
@@ -295,7 +294,7 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, u32 *p, | |||
295 | while (len > args->vec[v].iov_len) { | 294 | while (len > args->vec[v].iov_len) { |
296 | len -= args->vec[v].iov_len; | 295 | len -= args->vec[v].iov_len; |
297 | v++; | 296 | v++; |
298 | args->vec[v].iov_base = page_address(rqstp->rq_argpages[v]); | 297 | args->vec[v].iov_base = page_address(rqstp->rq_pages[v]); |
299 | args->vec[v].iov_len = PAGE_SIZE; | 298 | args->vec[v].iov_len = PAGE_SIZE; |
300 | } | 299 | } |
301 | args->vec[v].iov_len = len; | 300 | args->vec[v].iov_len = len; |
@@ -333,8 +332,7 @@ nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, u32 *p, struct nfsd_readlinka | |||
333 | { | 332 | { |
334 | if (!(p = decode_fh(p, &args->fh))) | 333 | if (!(p = decode_fh(p, &args->fh))) |
335 | return 0; | 334 | return 0; |
336 | svc_take_page(rqstp); | 335 | args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused++]); |
337 | args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused-1]); | ||
338 | 336 | ||
339 | return xdr_argsize_check(rqstp, p); | 337 | return xdr_argsize_check(rqstp, p); |
340 | } | 338 | } |
@@ -375,8 +373,7 @@ nfssvc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p, | |||
375 | if (args->count > PAGE_SIZE) | 373 | if (args->count > PAGE_SIZE) |
376 | args->count = PAGE_SIZE; | 374 | args->count = PAGE_SIZE; |
377 | 375 | ||
378 | svc_take_page(rqstp); | 376 | args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused++]); |
379 | args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused-1]); | ||
380 | 377 | ||
381 | return xdr_argsize_check(rqstp, p); | 378 | return xdr_argsize_check(rqstp, p); |
382 | } | 379 | } |
@@ -416,7 +413,6 @@ nfssvc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p, | |||
416 | rqstp->rq_res.page_len = resp->len; | 413 | rqstp->rq_res.page_len = resp->len; |
417 | if (resp->len & 3) { | 414 | if (resp->len & 3) { |
418 | /* need to pad the tail */ | 415 | /* need to pad the tail */ |
419 | rqstp->rq_restailpage = 0; | ||
420 | rqstp->rq_res.tail[0].iov_base = p; | 416 | rqstp->rq_res.tail[0].iov_base = p; |
421 | *p = 0; | 417 | *p = 0; |
422 | rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3); | 418 | 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 | rqstp->rq_res.page_len = resp->count; | 432 | rqstp->rq_res.page_len = resp->count; |
437 | if (resp->count & 3) { | 433 | if (resp->count & 3) { |
438 | /* need to pad the tail */ | 434 | /* need to pad the tail */ |
439 | rqstp->rq_restailpage = 0; | ||
440 | rqstp->rq_res.tail[0].iov_base = p; | 435 | rqstp->rq_res.tail[0].iov_base = p; |
441 | *p = 0; | 436 | *p = 0; |
442 | rqstp->rq_res.tail[0].iov_len = 4 - (resp->count&3); | 437 | rqstp->rq_res.tail[0].iov_len = 4 - (resp->count&3); |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 443ebc52e382..bfd36e587ec5 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -791,22 +791,26 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset | |||
791 | { | 791 | { |
792 | unsigned long count = desc->count; | 792 | unsigned long count = desc->count; |
793 | struct svc_rqst *rqstp = desc->arg.data; | 793 | struct svc_rqst *rqstp = desc->arg.data; |
794 | struct page **pp = rqstp->rq_respages + rqstp->rq_resused; | ||
794 | 795 | ||
795 | if (size > count) | 796 | if (size > count) |
796 | size = count; | 797 | size = count; |
797 | 798 | ||
798 | if (rqstp->rq_res.page_len == 0) { | 799 | if (rqstp->rq_res.page_len == 0) { |
799 | get_page(page); | 800 | get_page(page); |
800 | rqstp->rq_respages[rqstp->rq_resused++] = page; | 801 | put_page(*pp); |
802 | *pp = page; | ||
803 | rqstp->rq_resused++; | ||
801 | rqstp->rq_res.page_base = offset; | 804 | rqstp->rq_res.page_base = offset; |
802 | rqstp->rq_res.page_len = size; | 805 | rqstp->rq_res.page_len = size; |
803 | } else if (page != rqstp->rq_respages[rqstp->rq_resused-1]) { | 806 | } else if (page != pp[-1]) { |
804 | get_page(page); | 807 | get_page(page); |
805 | rqstp->rq_respages[rqstp->rq_resused++] = page; | 808 | put_page(*pp); |
809 | *pp = page; | ||
810 | rqstp->rq_resused++; | ||
806 | rqstp->rq_res.page_len += size; | 811 | rqstp->rq_res.page_len += size; |
807 | } else { | 812 | } else |
808 | rqstp->rq_res.page_len += size; | 813 | rqstp->rq_res.page_len += size; |
809 | } | ||
810 | 814 | ||
811 | desc->count = count - size; | 815 | desc->count = count - size; |
812 | desc->written += size; | 816 | desc->written += size; |
@@ -837,7 +841,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
837 | file->f_ra = ra->p_ra; | 841 | file->f_ra = ra->p_ra; |
838 | 842 | ||
839 | if (file->f_op->sendfile && rqstp->rq_sendfile_ok) { | 843 | if (file->f_op->sendfile && rqstp->rq_sendfile_ok) { |
840 | svc_pushback_unused_pages(rqstp); | 844 | rqstp->rq_resused = 1; |
841 | err = file->f_op->sendfile(file, &offset, *count, | 845 | err = file->f_op->sendfile(file, &offset, *count, |
842 | nfsd_read_actor, rqstp); | 846 | nfsd_read_actor, rqstp); |
843 | } else { | 847 | } else { |