diff options
author | NeilBrown <neilb@suse.de> | 2006-04-11 01:55:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-04-11 09:18:52 -0400 |
commit | bb6e8a9f4005237401a45f1ea43db060ea5f9725 (patch) | |
tree | b1e0b144964691eb3b5ea241a4e686adcba2824c /fs/nfsd/nfs4xdr.c | |
parent | 6ed6decccf544970664757464cfb67e081775e6a (diff) |
[PATCH] knfsd: nfsd4: fix corruption on readdir encoding with 64k pages
Fix corruption on readdir encoding with 64k pages.
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>
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 13 |
1 files changed, 6 insertions, 7 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index f2710cfc0bc5..de3998f15f10 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -2157,7 +2157,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re | |||
2157 | { | 2157 | { |
2158 | int maxcount; | 2158 | int maxcount; |
2159 | loff_t offset; | 2159 | loff_t offset; |
2160 | u32 *page, *savep; | 2160 | u32 *page, *savep, *tailbase; |
2161 | ENCODE_HEAD; | 2161 | ENCODE_HEAD; |
2162 | 2162 | ||
2163 | if (nfserr) | 2163 | if (nfserr) |
@@ -2173,6 +2173,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re | |||
2173 | WRITE32(0); | 2173 | WRITE32(0); |
2174 | ADJUST_ARGS(); | 2174 | ADJUST_ARGS(); |
2175 | resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; | 2175 | resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; |
2176 | tailbase = p; | ||
2176 | 2177 | ||
2177 | maxcount = PAGE_SIZE; | 2178 | maxcount = PAGE_SIZE; |
2178 | if (maxcount > readdir->rd_maxcount) | 2179 | if (maxcount > readdir->rd_maxcount) |
@@ -2217,14 +2218,12 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re | |||
2217 | *p++ = htonl(readdir->common.err == nfserr_eof); | 2218 | *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]); | 2219 | resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); |
2219 | 2220 | ||
2220 | /* allocate a page for the tail */ | 2221 | /* Use rest of head for padding and remaining ops: */ |
2221 | svc_take_page(resp->rqstp); | 2222 | resp->rqstp->rq_restailpage = 0; |
2222 | resp->xbuf->tail[0].iov_base = | 2223 | resp->xbuf->tail[0].iov_base = tailbase; |
2223 | page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); | ||
2224 | resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1; | ||
2225 | resp->xbuf->tail[0].iov_len = 0; | 2224 | resp->xbuf->tail[0].iov_len = 0; |
2226 | resp->p = resp->xbuf->tail[0].iov_base; | 2225 | resp->p = resp->xbuf->tail[0].iov_base; |
2227 | resp->end = resp->p + PAGE_SIZE/4; | 2226 | resp->end = resp->p + (PAGE_SIZE - resp->xbuf->head[0].iov_len)/4; |
2228 | 2227 | ||
2229 | return 0; | 2228 | return 0; |
2230 | err_no_verf: | 2229 | err_no_verf: |