aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-04-11 01:55:32 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-11 09:18:52 -0400
commit6ed6decccf544970664757464cfb67e081775e6a (patch)
tree9aa6b62856426e5aba7f34b3bbc9b24c87a54b87
parentf0e2993e9e73e8f38b05a89c98b9db94fec2199d (diff)
[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>
-rw-r--r--fs/nfsd/nfs4xdr.c42
1 files changed, 17 insertions, 25 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 845f25251d81..f2710cfc0bc5 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2084,27 +2084,20 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read
2084 WRITE32(eof); 2084 WRITE32(eof);
2085 WRITE32(maxcount); 2085 WRITE32(maxcount);
2086 ADJUST_ARGS(); 2086 ADJUST_ARGS();
2087 resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; 2087 resp->xbuf->head[0].iov_len = (char*)p
2088 2088 - (char*)resp->xbuf->head[0].iov_base;
2089 resp->xbuf->page_len = maxcount; 2089 resp->xbuf->page_len = maxcount;
2090 2090
2091 /* read zero bytes -> don't set up tail */ 2091 /* Use rest of head for padding and remaining ops: */
2092 if(!maxcount) 2092 resp->rqstp->rq_restailpage = 0;
2093 return 0; 2093 resp->xbuf->tail[0].iov_base = p;
2094
2095 /* set up page for remaining responses */
2096 svc_take_page(resp->rqstp);
2097 resp->xbuf->tail[0].iov_base =
2098 page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2099 resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
2100 resp->xbuf->tail[0].iov_len = 0; 2094 resp->xbuf->tail[0].iov_len = 0;
2101 resp->p = resp->xbuf->tail[0].iov_base;
2102 resp->end = resp->p + PAGE_SIZE/4;
2103
2104 if (maxcount&3) { 2095 if (maxcount&3) {
2105 *(resp->p)++ = 0; 2096 RESERVE_SPACE(4);
2097 WRITE32(0);
2106 resp->xbuf->tail[0].iov_base += maxcount&3; 2098 resp->xbuf->tail[0].iov_base += maxcount&3;
2107 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); 2099 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
2100 ADJUST_ARGS();
2108 } 2101 }
2109 return 0; 2102 return 0;
2110} 2103}
@@ -2141,21 +2134,20 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r
2141 2134
2142 WRITE32(maxcount); 2135 WRITE32(maxcount);
2143 ADJUST_ARGS(); 2136 ADJUST_ARGS();
2144 resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; 2137 resp->xbuf->head[0].iov_len = (char*)p
2138 - (char*)resp->xbuf->head[0].iov_base;
2139 resp->xbuf->page_len = maxcount;
2145 2140
2146 svc_take_page(resp->rqstp); 2141 /* Use rest of head for padding and remaining ops: */
2147 resp->xbuf->tail[0].iov_base = 2142 resp->rqstp->rq_restailpage = 0;
2148 page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); 2143 resp->xbuf->tail[0].iov_base = p;
2149 resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
2150 resp->xbuf->tail[0].iov_len = 0; 2144 resp->xbuf->tail[0].iov_len = 0;
2151 resp->p = resp->xbuf->tail[0].iov_base;
2152 resp->end = resp->p + PAGE_SIZE/4;
2153
2154 resp->xbuf->page_len = maxcount;
2155 if (maxcount&3) { 2145 if (maxcount&3) {
2156 *(resp->p)++ = 0; 2146 RESERVE_SPACE(4);
2147 WRITE32(0);
2157 resp->xbuf->tail[0].iov_base += maxcount&3; 2148 resp->xbuf->tail[0].iov_base += maxcount&3;
2158 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); 2149 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
2150 ADJUST_ARGS();
2159 } 2151 }
2160 return 0; 2152 return 0;
2161} 2153}