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 | |
| 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>
| -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: |
