dir.c     |   21 +++++++++++++++++++++
 nfs2xdr.c |    4 ++--
 nfs3xdr.c |   14 ++++++++++++--
 3 files changed, 35 insertions(+), 4 deletions(-)

diff -u --recursive --new-file --show-c-function linux-2.4.26-01-fix_unlink/fs/nfs/dir.c linux-2.4.26-02-seekdir/fs/nfs/dir.c
--- linux-2.4.26-01-fix_unlink/fs/nfs/dir.c	2004-04-16 09:35:23.000000000 -0700
+++ linux-2.4.26-02-seekdir/fs/nfs/dir.c	2004-04-16 09:35:24.000000000 -0700
@@ -34,6 +34,7 @@
 #define NFS_PARANOIA 1
 /* #define NFS_DEBUG_VERBOSE 1 */
 
+static loff_t nfs_dir_llseek(struct file *, loff_t, int);
 static int nfs_readdir(struct file *, void *, filldir_t);
 static struct dentry *nfs_lookup(struct inode *, struct dentry *);
 static int nfs_create(struct inode *, struct dentry *, int);
@@ -48,6 +49,7 @@ static int nfs_rename(struct inode *, st
 static int nfs_fsync_dir(struct file *, struct dentry *, int);
 
 struct file_operations nfs_dir_operations = {
+	llseek:		nfs_dir_llseek,
 	read:		generic_read_dir,
 	readdir:	nfs_readdir,
 	open:		nfs_open,
@@ -70,6 +72,25 @@ struct inode_operations nfs_dir_inode_op
 	setattr:	nfs_notify_change,
 };
 
+static loff_t nfs_dir_llseek(struct file *file, loff_t offset, int origin)
+{
+	switch (origin) {
+		case 1:
+			if (offset == 0) {
+				offset = file->f_pos;
+				break;
+			}
+		case 2:
+			return -EINVAL;
+	}
+	if (offset != file->f_pos) {
+		file->f_pos = offset;
+		file->f_reada = 0;
+		file->f_version = ++event;
+	}
+	return (offset <= 0) ? 0 : offset;
+}
+
 typedef u32 * (*decode_dirent_t)(u32 *, struct nfs_entry *, int);
 typedef struct {
 	struct file	*file;
diff -u --recursive --new-file --show-c-function linux-2.4.26-01-fix_unlink/fs/nfs/nfs2xdr.c linux-2.4.26-02-seekdir/fs/nfs/nfs2xdr.c
--- linux-2.4.26-01-fix_unlink/fs/nfs/nfs2xdr.c	2004-04-14 11:28:20.000000000 -0700
+++ linux-2.4.26-02-seekdir/fs/nfs/nfs2xdr.c	2004-04-16 09:35:24.000000000 -0700
@@ -369,7 +369,7 @@ nfs_xdr_readdirargs(struct rpc_rqst *req
 		count = count >> 2;
 
 	p = xdr_encode_fhandle(p, args->fh);
-	*p++ = htonl(args->cookie);
+	*p++ = htonl(args->cookie & 0xFFFFFFFF);
 	*p++ = htonl(count); /* see above */
 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 
@@ -466,7 +466,7 @@ nfs_decode_dirent(u32 *p, struct nfs_ent
 	entry->name	  = (const char *) p;
 	p		 += XDR_QUADLEN(entry->len);
 	entry->prev_cookie	  = entry->cookie;
-	entry->cookie	  = ntohl(*p++);
+	entry->cookie	  = (s64)((off_t)ntohl(*p++));
 	entry->eof	  = !p[0] && p[1];
 
 	return p;
diff -u --recursive --new-file --show-c-function linux-2.4.26-01-fix_unlink/fs/nfs/nfs3xdr.c linux-2.4.26-02-seekdir/fs/nfs/nfs3xdr.c
--- linux-2.4.26-01-fix_unlink/fs/nfs/nfs3xdr.c	2004-04-14 11:28:57.000000000 -0700
+++ linux-2.4.26-02-seekdir/fs/nfs/nfs3xdr.c	2004-04-16 09:35:24.000000000 -0700
@@ -465,6 +465,13 @@ nfs3_xdr_linkargs(struct rpc_rqst *req, 
 	return 0;
 }
 
+/* Hack to sign-extending 32-bit cookies */
+static inline
+u64 nfs_transform_cookie64(u64 cookie)
+{
+	return (cookie & 0x80000000) ? (cookie ^ 0xFFFFFFFF00000000) : cookie;
+}
+
 /*
  * Encode arguments to readdir call
  */
@@ -476,7 +483,7 @@ nfs3_xdr_readdirargs(struct rpc_rqst *re
 	u32 count = args->count;
 
 	p = xdr_encode_fhandle(p, args->fh);
-	p = xdr_encode_hyper(p, args->cookie);
+	p = xdr_encode_hyper(p, nfs_transform_cookie64(args->cookie));
 	*p++ = args->verf[0];
 	*p++ = args->verf[1];
 	if (args->plus) {
@@ -599,6 +606,8 @@ err_unmap:
 u32 *
 nfs3_decode_dirent(u32 *p, struct nfs_entry *entry, int plus)
 {
+	u64 cookie;
+
 	if (!*p++) {
 		if (!*p)
 			return ERR_PTR(-EAGAIN);
@@ -611,7 +620,8 @@ nfs3_decode_dirent(u32 *p, struct nfs_en
 	entry->name = (const char *) p;
 	p += XDR_QUADLEN(entry->len);
 	entry->prev_cookie = entry->cookie;
-	p = xdr_decode_hyper(p, &entry->cookie);
+	p = xdr_decode_hyper(p, &cookie);
+	entry->cookie = nfs_transform_cookie64(cookie);
 
 	if (plus) {
 		struct nfs_fattr fattr;