Index: linux-2.6.5/fs/nfsd/nfs3proc.c =================================================================== --- linux-2.6.5.orig/fs/nfsd/nfs3proc.c 2004-05-27 12:22:43.000000000 +0200 +++ linux-2.6.5/fs/nfsd/nfs3proc.c 2004-05-27 12:34:40.000000000 +0200 @@ -437,7 +437,6 @@ resp->buflen = count; resp->common.err = nfs_ok; resp->buffer = argp->buffer; - resp->offset = NULL; resp->rqstp = rqstp; nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t*) &argp->cookie, &resp->common, nfs3svc_encode_entry); Index: linux-2.6.5/fs/nfsd/nfs3xdr.c =================================================================== --- linux-2.6.5.orig/fs/nfsd/nfs3xdr.c 2004-05-27 12:22:43.000000000 +0200 +++ linux-2.6.5/fs/nfsd/nfs3xdr.c 2004-05-27 12:39:09.000000000 +0200 @@ -887,8 +887,18 @@ int elen; /* estimated entry length in words */ int num_entry_words = 0; /* actual number of words */ - if (cd->offset) - xdr_encode_hyper(cd->offset, (u64) offset); + if (cd->offset) { + u64 offset64 = offset; + + if (unlikely(cd->offset1)) { + /* we ended up with offset on a page boundary */ + *cd->offset = htonl(offset64 >> 32); + *cd->offset1 = htonl(offset64 & 0xffffffff); + cd->offset1 = NULL; + } else { + xdr_encode_hyper(cd->offset, (u64) offset); + } + } /* dprintk("encode_entry(%.*s @%ld%s)\n", @@ -969,17 +979,32 @@ /* update offset */ cd->offset = cd->buffer + (cd->offset - tmp); } else { + unsigned int offset_r = (cd->offset - tmp) << 2; + + /* update pointer to offset location. + * This is a 64bit quantity, so we need to + * deal with 3 cases: + * - entirely in first page + * - entirely in second page + * - 4 bytes in each page + */ + if (offset_r + 8 <= len1) { + cd->offset = p + (cd->offset - tmp); + } else if (offset_r >= len1) { + cd->offset -= len1 >> 2; + } else { + /* sitting on the fence */ + BUG_ON(offset_r != len1 - 4); + cd->offset = p + (cd->offset - tmp); + cd->offset1 = tmp; + } + len2 = (num_entry_words << 2) - len1; /* move from temp page to current and next pages */ memmove(p, tmp, len1); memmove(tmp, (caddr_t)tmp+len1, len2); - /* update offset */ - if (((cd->offset - tmp) << 2) <= len1) - cd->offset = p + (cd->offset - tmp); - else - cd->offset -= len1 >> 2; p = tmp + (len2 >> 2); } } Index: linux-2.6.5/include/linux/nfsd/xdr3.h =================================================================== --- linux-2.6.5.orig/include/linux/nfsd/xdr3.h 2004-05-27 12:22:43.000000000 +0200 +++ linux-2.6.5/include/linux/nfsd/xdr3.h 2004-05-27 12:28:20.000000000 +0200 @@ -183,6 +183,7 @@ u32 * buffer; int buflen; u32 * offset; + u32 * offset1; struct svc_rqst * rqstp; };