From: NeilBrown <neilb@cse.unsw.edu.au>

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

 25-akpm/fs/nfsd/nfs3proc.c |   12 ++++++++++--
 25-akpm/fs/nfsd/nfs3xdr.c  |   10 ++++++++--
 2 files changed, 18 insertions(+), 4 deletions(-)

diff -puN fs/nfsd/nfs3proc.c~knfsd-fix-two-xdr-encode-bugs-for-readdirplus-reply fs/nfsd/nfs3proc.c
--- 25/fs/nfsd/nfs3proc.c~knfsd-fix-two-xdr-encode-bugs-for-readdirplus-reply	2004-08-20 00:01:00.689572400 -0700
+++ 25-akpm/fs/nfsd/nfs3proc.c	2004-08-20 00:01:00.694571640 -0700
@@ -492,8 +492,16 @@ nfsd3_proc_readdirplus(struct svc_rqst *
 		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 -puN fs/nfsd/nfs3xdr.c~knfsd-fix-two-xdr-encode-bugs-for-readdirplus-reply fs/nfsd/nfs3xdr.c
--- 25/fs/nfsd/nfs3xdr.c~knfsd-fix-two-xdr-encode-bugs-for-readdirplus-reply	2004-08-20 00:01:00.691572096 -0700
+++ 25-akpm/fs/nfsd/nfs3xdr.c	2004-08-20 00:01:00.695571488 -0700
@@ -762,10 +762,16 @@ nfs3svc_encode_readdirres(struct svc_rqs
 		/* 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);
_