[PATCH] knfsd: nfsd4: fix corruption of returned data when using 64k pages
In v4 we grab an extra page just for the padding of returned data. The formula that the rpc server uses to allocate pages for the response doesn't take into account this extra page. Instead of adjusting those formulae, we adopt the same solution as v2 and v3, and put the "tail" data in the same page as the "head" data. Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
f0e2993e9e
commit
6ed6decccf
1 changed files with 18 additions and 26 deletions
|
@ -2084,27 +2084,20 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read
|
|||
WRITE32(eof);
|
||||
WRITE32(maxcount);
|
||||
ADJUST_ARGS();
|
||||
resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
|
||||
|
||||
resp->xbuf->head[0].iov_len = (char*)p
|
||||
- (char*)resp->xbuf->head[0].iov_base;
|
||||
resp->xbuf->page_len = maxcount;
|
||||
|
||||
/* read zero bytes -> don't set up tail */
|
||||
if(!maxcount)
|
||||
return 0;
|
||||
|
||||
/* set up page for remaining responses */
|
||||
svc_take_page(resp->rqstp);
|
||||
resp->xbuf->tail[0].iov_base =
|
||||
page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
|
||||
resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
|
||||
/* 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_len = 0;
|
||||
resp->p = resp->xbuf->tail[0].iov_base;
|
||||
resp->end = resp->p + PAGE_SIZE/4;
|
||||
|
||||
if (maxcount&3) {
|
||||
*(resp->p)++ = 0;
|
||||
RESERVE_SPACE(4);
|
||||
WRITE32(0);
|
||||
resp->xbuf->tail[0].iov_base += maxcount&3;
|
||||
resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
|
||||
ADJUST_ARGS();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -2141,21 +2134,20 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r
|
|||
|
||||
WRITE32(maxcount);
|
||||
ADJUST_ARGS();
|
||||
resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
|
||||
|
||||
svc_take_page(resp->rqstp);
|
||||
resp->xbuf->tail[0].iov_base =
|
||||
page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
|
||||
resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
|
||||
resp->xbuf->tail[0].iov_len = 0;
|
||||
resp->p = resp->xbuf->tail[0].iov_base;
|
||||
resp->end = resp->p + PAGE_SIZE/4;
|
||||
|
||||
resp->xbuf->head[0].iov_len = (char*)p
|
||||
- (char*)resp->xbuf->head[0].iov_base;
|
||||
resp->xbuf->page_len = maxcount;
|
||||
|
||||
/* 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_len = 0;
|
||||
if (maxcount&3) {
|
||||
*(resp->p)++ = 0;
|
||||
RESERVE_SPACE(4);
|
||||
WRITE32(0);
|
||||
resp->xbuf->tail[0].iov_base += maxcount&3;
|
||||
resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
|
||||
ADJUST_ARGS();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue