diff options
author | Neil Brown <neilb@cse.unsw.edu.au> | 2004-08-22 23:02:30 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-08-22 23:02:30 -0700 |
commit | eb229d253e6cf376756101ea3fdfd4a17edc5450 (patch) | |
tree | 0b43a21df0c47a01166f2819487ebd7e77b2bce0 /fs | |
parent | 57b6949e9ca8964dcb4ba712fe3876eb21fe84ae (diff) | |
download | history-eb229d253e6cf376756101ea3fdfd4a17edc5450.tar.gz |
[PATCH] kNFSd: fix two xdr-encode bugs for readdirplus reply
More fall-out from the change to allow multi-page replies to readdir
requests.
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
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/nfs3proc.c | 12 | ||||
-rw-r--r-- | fs/nfsd/nfs3xdr.c | 10 |
2 files changed, 18 insertions, 4 deletions
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index 941ceaec1a1d5d..effcd19130908c 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c @@ -492,8 +492,16 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp, count += PAGE_SIZE; } resp->count = count >> 2; - if (resp->offset) - xdr_encode_hyper(resp->offset, offset); + if (resp->offset) { + if (unlikely(resp->offset1)) { + /* we ended up with offset on a page boundary */ + *resp->offset = htonl(offset >> 32); + *resp->offset1 = htonl(offset & 0xffffffff); + resp->offset1 = NULL; + } else { + xdr_encode_hyper(resp->offset, offset); + } + } RETURN_STATUS(nfserr); } diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index e7f907dfa2b953..f3fbef66ec0f9b 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -762,10 +762,16 @@ nfs3svc_encode_readdirres(struct svc_rqst *rqstp, u32 *p, /* stupid readdir cookie */ memcpy(p, resp->verf, 8); p += 2; xdr_ressize_check(rqstp, p); - p = resp->buffer; + if (rqstp->rq_res.head[0].iov_len + (2<<2) > PAGE_SIZE) + return 1; /*No room for trailer */ + rqstp->rq_res.page_len = (resp->count) << 2; + + /* add the 'tail' to the end of the 'head' page - page 0. */ + rqstp->rq_restailpage = 0; + rqstp->rq_res.tail[0].iov_base = p; *p++ = 0; /* no more entries */ *p++ = htonl(resp->common.err == nfserr_eof); - rqstp->rq_res.page_len = (resp->count + 2) << 2; + rqstp->rq_res.tail[0].iov_len = 2<<2; return 1; } else return xdr_ressize_check(rqstp, p); |