fs/nfs/nfs3proc.c           |    3 -
 fs/nfs/nfs4xdr.c            |    2 
 fs/nfs/proc.c               |    2 
 fs/nfsd/export.c            |   97 ++++++++++++++++++++++++++------------------
 fs/nfsd/nfs3xdr.c           |   12 +----
 fs/nfsd/nfsfh.c             |   62 +++++++++++++++++++---------
 fs/nfsd/nfsproc.c           |   20 ++++-----
 fs/nfsd/nfsxdr.c            |    8 +--
 include/linux/nfsd/export.h |    2 
 include/linux/nfsd/nfsd.h   |   12 +++++
 include/linux/nfsd/nfsfh.h  |   26 ++---------
 11 files changed, 141 insertions(+), 105 deletions(-)

diff -puN fs/nfsd/export.c~KD32-nfs-B5 fs/nfsd/export.c
--- 25/fs/nfsd/export.c~KD32-nfs-B5	2003-09-21 22:35:10.000000000 -0700
+++ 25-akpm/fs/nfsd/export.c	2003-09-21 22:35:10.000000000 -0700
@@ -55,11 +55,16 @@ static int		exp_verify_string(char *cp, 
 #define	EXPKEY_HASHMASK		(EXPKEY_HASHMAX -1)
 static struct cache_head *expkey_table[EXPKEY_HASHMAX];
 
+static inline int key_len(int type)
+{
+	return type == 0 ? 8 : type == 1 ? 4 : 12;
+}
+
 static inline int svc_expkey_hash(struct svc_expkey *item)
 {
 	int hash = item->ek_fsidtype;
 	char * cp = (char*)item->ek_fsid;
-	int len = (item->ek_fsidtype==0)?8:4;
+	int len = key_len(item->ek_fsidtype);
 
 	hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
 	hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS);
@@ -89,7 +94,7 @@ void expkey_request(struct cache_detail 
 	qword_add(bpp, blen, ek->ek_client->name);
 	snprintf(type, 5, "%d", ek->ek_fsidtype);
 	qword_add(bpp, blen, type);
-	qword_addhex(bpp, blen, (char*)ek->ek_fsid, ek->ek_fsidtype==0?8:4);
+	qword_addhex(bpp, blen, (char*)ek->ek_fsid, key_len(ek->ek_fsidtype));
 	(*bpp)[-1] = '\n';
 }
 
@@ -130,12 +135,12 @@ int expkey_parse(struct cache_detail *cd
 	if (*ep)
 		goto out;
 	dprintk("found fsidtype %d\n", fsidtype);
-	if (fsidtype > 1)
+	if (fsidtype > 2)
 		goto out;
 	if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
 		goto out;
 	dprintk("found fsid length %d\n", len);
-	if (len != ((fsidtype==0)?8:4))
+	if (len != key_len(fsidtype))
 		goto out;
 
 	/* OK, we seem to have a valid key */
@@ -206,8 +211,10 @@ static int expkey_show(struct seq_file *
 	ek = container_of(h, struct svc_expkey, h);
 	seq_printf(m, "%s %d 0x%08x", ek->ek_client->name,
 		   ek->ek_fsidtype, ek->ek_fsid[0]);
-	if (ek->ek_fsid == 0)
-		seq_printf(m, "%08x", ek->ek_fsid[0]);
+	if (ek->ek_fsidtype != 1)
+		seq_printf(m, "%08x", ek->ek_fsid[1]);
+	if (ek->ek_fsidtype == 2)
+		seq_printf(m, "%08x", ek->ek_fsid[2]);
 	if (test_bit(CACHE_VALID, &h->flags) && 
 	    !test_bit(CACHE_NEGATIVE, &h->flags)) {
 		seq_printf(m, " ");
@@ -230,13 +237,8 @@ struct cache_detail svc_expkey_cache = {
 static inline int svc_expkey_match (struct svc_expkey *a, struct svc_expkey *b)
 {
 	if (a->ek_fsidtype != b->ek_fsidtype ||
-	    a->ek_client != b->ek_client)
-		return 0;
-	if (a->ek_fsid[0] != b->ek_fsid[0])
-		return 0;
-	if (a->ek_fsidtype == 1)
-		return 1;
-	if (a->ek_fsid[1] != b->ek_fsid[1])
+	    a->ek_client != b->ek_client ||
+	    memcmp(a->ek_fsid, b->ek_fsid, key_len(a->ek_fsidtype)) != 0)
 		return 0;
 	return 1;
 }
@@ -248,6 +250,7 @@ static inline void svc_expkey_init(struc
 	new->ek_fsidtype = item->ek_fsidtype;
 	new->ek_fsid[0] = item->ek_fsid[0];
 	new->ek_fsid[1] = item->ek_fsid[1];
+	new->ek_fsid[2] = item->ek_fsid[2];
 }
 
 static inline void svc_expkey_update(struct svc_expkey *new, struct svc_expkey *item)
@@ -502,8 +505,7 @@ exp_find_key(svc_client *clp, int fsid_t
 
 	key.ek_client = clp;
 	key.ek_fsidtype = fsid_type;
-	key.ek_fsid[0] = fsidv[0];
-	key.ek_fsid[1] = fsidv[1];
+	memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
 
 	ek = svc_expkey_lookup(&key, 0);
 	if (ek != NULL)
@@ -519,8 +521,7 @@ int exp_set_key(svc_client *clp, int fsi
 
 	key.ek_client = clp;
 	key.ek_fsidtype = fsid_type;
-	key.ek_fsid[0] = fsidv[0];
-	key.ek_fsid[1] = fsidv[1];
+	memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
 	key.ek_export = exp;
 	key.h.expiry_time = NEVER;
 	key.h.flags = 0;
@@ -539,10 +540,14 @@ int exp_set_key(svc_client *clp, int fsi
 static inline struct svc_expkey *
 exp_get_key(svc_client *clp, dev_t dev, ino_t ino)
 {
-	u32 fsidv[2];
+	u32 fsidv[3];
 	
-	mk_fsid_v0(fsidv, dev, ino);
-	return exp_find_key(clp, 0, fsidv, NULL);
+	if (old_valid_dev(dev)) {
+		mk_fsid_v0(fsidv, dev, ino);
+		return exp_find_key(clp, 0, fsidv, NULL);
+	}
+	mk_fsid_v2(fsidv, dev, ino);
+	return exp_find_key(clp, 2, fsidv, NULL);
 }
 
 /*
@@ -671,11 +676,15 @@ static int exp_fsid_hash(svc_client *clp
 static int exp_hash(struct auth_domain *clp, struct svc_export *exp)
 {
 	u32 fsid[2];
-	struct inode *inode;
+	struct inode *inode = exp->ex_dentry->d_inode;
+	dev_t dev = inode->i_sb->s_dev;
 
-	inode = exp->ex_dentry->d_inode;
-	mk_fsid_v0(fsid,  inode->i_sb->s_dev, inode->i_ino);
-	return exp_set_key(clp, 0, fsid, exp);
+	if (old_valid_dev(dev)) {
+		mk_fsid_v0(fsid, dev, inode->i_ino);
+		return exp_set_key(clp, 0, fsid, exp);
+	}
+	mk_fsid_v2(fsid, dev, inode->i_ino);
+	return exp_set_key(clp, 2, fsid, exp);
 }
 
 static void exp_unhash(struct svc_export *exp)
@@ -819,32 +828,42 @@ int
 exp_unexport(struct nfsctl_export *nxp)
 {
 	struct auth_domain *dom;
+	svc_export *exp;
+	struct nameidata nd;
 	int		err;
 
 	/* Consistency check */
-	if (!exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
+	if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
+	    !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
 		return -EINVAL;
 
 	exp_writelock();
 
 	err = -EINVAL;
 	dom = auth_domain_find(nxp->ex_client);
-
-	if (dom) {
-		struct svc_expkey *key = exp_get_key(dom, nxp->ex_dev, nxp->ex_ino);
-		if (key && !IS_ERR(key) && key->ek_export) {
-			exp_do_unexport(key->ek_export);
-			err = 0;
-			expkey_put(&key->h, &svc_expkey_cache);
-		} else
-			dprintk("nfsd: no export %x/%lx for %s\n",
-				(unsigned)nxp->ex_dev,
-				(unsigned long) nxp->ex_ino, nxp->ex_client);
-		auth_domain_put(dom);
-		cache_flush();
-	} else
+	if (!dom) {
 		dprintk("nfsd: unexport couldn't find %s\n", nxp->ex_client);
+		goto out_unlock;
+	}
+
+	err = path_lookup(nxp->ex_path, 0, &nd);
+	if (err)
+		goto out_domain;
 
+	err = -EINVAL;
+	exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL);
+	path_release(&nd);
+	if (!exp)
+		goto out_domain;
+
+	exp_do_unexport(exp);
+	exp_put(exp);
+	err = 0;
+
+out_domain:
+	auth_domain_put(dom);
+	cache_flush();
+out_unlock:
 	exp_writeunlock();
 	return err;
 }
diff -puN fs/nfsd/nfs3xdr.c~KD32-nfs-B5 fs/nfsd/nfs3xdr.c
--- 25/fs/nfsd/nfs3xdr.c~KD32-nfs-B5	2003-09-21 22:35:10.000000000 -0700
+++ 25-akpm/fs/nfsd/nfs3xdr.c	2003-09-21 22:35:10.000000000 -0700
@@ -186,12 +186,10 @@ encode_fattr3(struct svc_rqst *rqstp, u3
 	p = xdr_encode_hyper(p, ((u64)stat.blocks) << 9);
 	*p++ = htonl((u32) MAJOR(stat.rdev));
 	*p++ = htonl((u32) MINOR(stat.rdev));
-	if (rqstp->rq_reffh->fh_version == 1
-	    && rqstp->rq_reffh->fh_fsid_type == 1
-	    && (fhp->fh_export->ex_flags & NFSEXP_FSID))
+	if (is_fsid(fhp, rqstp->rq_reffh))
 		p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
 	else
-		p = xdr_encode_hyper(p, (u64) stat.dev);
+		p = xdr_encode_hyper(p, (u64) old_encode_dev(stat.dev));
 	p = xdr_encode_hyper(p, (u64) stat.ino);
 	p = encode_time3(p, &stat.atime);
 	lease_get_mtime(dentry->d_inode, &time); 
@@ -222,12 +220,10 @@ encode_saved_post_attr(struct svc_rqst *
 	p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9);
 	*p++ = fhp->fh_post_rdev[0];
 	*p++ = fhp->fh_post_rdev[1];
-	if (rqstp->rq_reffh->fh_version == 1
-	    && rqstp->rq_reffh->fh_fsid_type == 1
-	    && (fhp->fh_export->ex_flags & NFSEXP_FSID))
+	if (is_fsid(fhp, rqstp->rq_reffh))
 		p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
 	else
-		p = xdr_encode_hyper(p, (u64) inode->i_sb->s_dev);
+		p = xdr_encode_hyper(p, (u64)old_encode_dev(inode->i_sb->s_dev));
 	p = xdr_encode_hyper(p, (u64) inode->i_ino);
 	p = encode_time3(p, &fhp->fh_post_atime);
 	p = encode_time3(p, &fhp->fh_post_mtime);
diff -puN fs/nfsd/nfsfh.c~KD32-nfs-B5 fs/nfsd/nfsfh.c
--- 25/fs/nfsd/nfsfh.c~KD32-nfs-B5	2003-09-21 22:35:10.000000000 -0700
+++ 25-akpm/fs/nfsd/nfsfh.c	2003-09-21 22:35:10.000000000 -0700
@@ -125,6 +125,9 @@ fh_verify(struct svc_rqst *rqstp, struct
 			case 1:
 				len = 1;
 				break;
+			case 2:
+				len = 3;
+				break;
 			default:
 				goto out;
 			}
@@ -137,7 +140,7 @@ fh_verify(struct svc_rqst *rqstp, struct
 			if (fh->fh_size != NFS_FHSIZE)
 				goto out;
 			/* assume old filehandle format */
-			xdev = u32_to_dev_t(fh->ofh_xdev);
+			xdev = old_decode_dev(fh->ofh_xdev);
 			xino = u32_to_ino_t(fh->ofh_xino);
 			mk_fsid_v0(tfh, xdev, xino);
 			exp = exp_find(rqstp->rq_client, 0, tfh, &rqstp->rq_chandle);
@@ -329,12 +332,21 @@ fh_compose(struct svc_fh *fhp, struct sv
 		parent->d_name.name, dentry->d_name.name,
 		(inode ? inode->i_ino : 0));
 
-	if (ref_fh) {
+	/* for large devnums rules are simple */
+	if (!old_valid_dev(ex_dev)) {
+		ref_fh_version = 1;
+		if (exp->ex_flags & NFSEXP_FSID)
+			ref_fh_fsid_type = 1;
+		else
+			ref_fh_fsid_type = 2;
+	} else if (ref_fh) {
 		ref_fh_version = ref_fh->fh_handle.fh_version;
 		ref_fh_fsid_type = ref_fh->fh_handle.fh_fsid_type;
-		if (ref_fh == fhp)
-			fh_put(ref_fh);
+		if (!(exp->ex_flags & NFSEXP_FSID) || ref_fh_fsid_type == 2)
+			ref_fh_fsid_type = 0;
 	}
+	if (ref_fh == fhp)
+		fh_put(ref_fh);
 
 	if (fhp->fh_locked || fhp->fh_dentry) {
 		printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n",
@@ -353,7 +365,7 @@ fh_compose(struct svc_fh *fhp, struct sv
 		memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE);
 		fhp->fh_handle.fh_size = NFS_FHSIZE;
 		fhp->fh_handle.ofh_dcookie = 0xfeebbaca;
-		fhp->fh_handle.ofh_dev =  htonl((MAJOR(ex_dev)<<16)| MINOR(ex_dev));
+		fhp->fh_handle.ofh_dev =  old_encode_dev(ex_dev);
 		fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev;
 		fhp->fh_handle.ofh_xino = ino_t_to_u32(exp->ex_dentry->d_inode->i_ino);
 		fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry));
@@ -363,19 +375,33 @@ fh_compose(struct svc_fh *fhp, struct sv
 		fhp->fh_handle.fh_version = 1;
 		fhp->fh_handle.fh_auth_type = 0;
 		datap = fhp->fh_handle.fh_auth+0;
-		if ((exp->ex_flags & NFSEXP_FSID) &&
-		    (ref_fh_fsid_type == 1)) {
-			fhp->fh_handle.fh_fsid_type = 1;
-			/* fsid_type 1 == 4 bytes filesystem id */
-			mk_fsid_v1(datap, exp->ex_fsid);
-			datap += 1;
-			fhp->fh_handle.fh_size = 2*4;
-		} else {
-			fhp->fh_handle.fh_fsid_type = 0;
-			/* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */
-			mk_fsid_v0(datap, ex_dev, exp->ex_dentry->d_inode->i_ino);
-			datap += 2;
-			fhp->fh_handle.fh_size = 3*4;
+		fhp->fh_handle.fh_fsid_type = ref_fh_fsid_type;
+		switch (ref_fh_fsid_type) {
+			case 1:
+				/* fsid_type 1 == 4 bytes filesystem id */
+				mk_fsid_v1(datap, exp->ex_fsid);
+				datap += 1;
+				fhp->fh_handle.fh_size = 2*4;
+				break;
+			case 2:
+				/*
+				 * fsid_type 2:
+				 * 4byte major, 4byte minor, 4byte inode
+				 */
+				mk_fsid_v2(datap, ex_dev,
+					exp->ex_dentry->d_inode->i_ino);
+				datap += 3;
+				fhp->fh_handle.fh_size = 4*4;
+				break;
+			default:
+				/*
+				 * fsid_type 0:
+				 * 2byte major, 2byte minor, 4byte inode
+				 */
+				mk_fsid_v0(datap, ex_dev,
+					exp->ex_dentry->d_inode->i_ino);
+				datap += 2;
+				fhp->fh_handle.fh_size = 3*4;
 		}
 		if (inode) {
 			int size = fhp->fh_maxsize/4 - 3;
diff -puN fs/nfsd/nfsproc.c~KD32-nfs-B5 fs/nfsd/nfsproc.c
--- 25/fs/nfsd/nfsproc.c~KD32-nfs-B5	2003-09-21 22:35:10.000000000 -0700
+++ 25-akpm/fs/nfsd/nfsproc.c	2003-09-21 22:35:10.000000000 -0700
@@ -184,7 +184,7 @@ nfsd_proc_create(struct svc_rqst *rqstp,
 	struct inode	*inode;
 	struct dentry	*dchild;
 	int		nfserr, type, mode;
-	dev_t		rdev = 0;
+	dev_t		rdev = 0, wanted = old_decode_dev(attr->ia_size);
 
 	dprintk("nfsd: CREATE   %s %.*s\n",
 		SVCFH_fmt(dirfhp), argp->len, argp->name);
@@ -230,7 +230,7 @@ nfsd_proc_create(struct svc_rqst *rqstp,
 	inode = newfhp->fh_dentry->d_inode;
 
 	/* Unfudge the mode bits */
-	if (attr->ia_valid & ATTR_MODE) { 
+	if (attr->ia_valid & ATTR_MODE) {
 		type = attr->ia_mode & S_IFMT;
 		mode = attr->ia_mode & ~S_IFMT;
 		if (!type) {
@@ -242,7 +242,7 @@ nfsd_proc_create(struct svc_rqst *rqstp,
 				case S_IFCHR:
 				case S_IFBLK:
 					/* reserve rdev for later checking */
-					attr->ia_size = inode->i_rdev;
+					rdev = inode->i_rdev;
 					attr->ia_valid |= ATTR_SIZE;
 
 					/* FALLTHROUGH */
@@ -277,22 +277,21 @@ nfsd_proc_create(struct svc_rqst *rqstp,
 	 */
 	if (type != S_IFREG) {
 		int	is_borc = 0;
-		u32	size = attr->ia_size;
-
-		/* may need to change when we widen dev_t */
-		rdev = old_decode_dev(size);
 		if (type != S_IFBLK && type != S_IFCHR) {
 			rdev = 0;
 		} else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) {
 			/* If you think you've seen the worst, grok this. */
 			type = S_IFIFO;
-		} else if (size != rdev) {
+		} else if (!rdev && attr->ia_size != old_encode_dev(wanted)) {
 			/* dev got truncated because of 16bit Linux dev_t */
+			/* may need to change when we widen dev_t */
 			nfserr = nfserr_inval;
 			goto out_unlock;
 		} else {
 			/* Okay, char or block special */
 			is_borc = 1;
+			if (!rdev)
+				rdev = wanted;
 		}
 
 		/* we've used the SIZE information, so discard it */
@@ -300,11 +299,10 @@ nfsd_proc_create(struct svc_rqst *rqstp,
 
 		/* Make sure the type and device matches */
 		nfserr = nfserr_exist;
-		if (inode && (type != (inode->i_mode & S_IFMT) || 
-		    (is_borc && inode->i_rdev != rdev)))
+		if (inode && type != (inode->i_mode & S_IFMT))
 			goto out_unlock;
 	}
-	
+
 	nfserr = 0;
 	if (!inode) {
 		/* File doesn't exist. Create it and set attrs */
diff -puN fs/nfsd/nfsxdr.c~KD32-nfs-B5 fs/nfsd/nfsxdr.c
--- 25/fs/nfsd/nfsxdr.c~KD32-nfs-B5	2003-09-21 22:35:10.000000000 -0700
+++ 25-akpm/fs/nfsd/nfsxdr.c	2003-09-21 22:35:10.000000000 -0700
@@ -159,16 +159,14 @@ encode_fattr(struct svc_rqst *rqstp, u32
 	}
 	*p++ = htonl((u32) stat.blksize);
 	if (S_ISCHR(type) || S_ISBLK(type))
-		*p++ = htonl((u32) stat.rdev);
+		*p++ = htonl((u32) old_encode_dev(stat.rdev));
 	else
 		*p++ = htonl(0xffffffff);
 	*p++ = htonl((u32) stat.blocks);
-	if (rqstp->rq_reffh->fh_version == 1 
-	    && rqstp->rq_reffh->fh_fsid_type == 1
-	    && (fhp->fh_export->ex_flags & NFSEXP_FSID))
+	if (is_fsid(fhp, rqstp->rq_reffh))
 		*p++ = htonl((u32) fhp->fh_export->ex_fsid);
 	else
-		*p++ = htonl((u32) stat.dev);
+		*p++ = htonl((u32) old_encode_dev(stat.dev));
 	*p++ = htonl((u32) stat.ino);
 	*p++ = htonl((u32) stat.atime.tv_sec);
 	*p++ = htonl(stat.atime.tv_nsec ? stat.atime.tv_nsec / 1000 : 0);
diff -puN fs/nfs/nfs3proc.c~KD32-nfs-B5 fs/nfs/nfs3proc.c
--- 25/fs/nfs/nfs3proc.c~KD32-nfs-B5	2003-09-21 22:35:10.000000000 -0700
+++ 25-akpm/fs/nfs/nfs3proc.c	2003-09-21 22:35:10.000000000 -0700
@@ -651,7 +651,8 @@ nfs3_proc_mknod(struct inode *dir, struc
 	default:	return -EINVAL;
 	}
 
-	dprintk("NFS call  mknod %s %x\n", name->name, (unsigned)rdev);
+	dprintk("NFS call  mknod %s %u:%u\n", name->name,
+			MAJOR(rdev), MINOR(rdev));
 	dir_attr.valid = 0;
 	fattr->valid = 0;
 	status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0);
diff -puN fs/nfs/nfs4xdr.c~KD32-nfs-B5 fs/nfs/nfs4xdr.c
--- 25/fs/nfs/nfs4xdr.c~KD32-nfs-B5	2003-09-21 22:35:10.000000000 -0700
+++ 25-akpm/fs/nfs/nfs4xdr.c	2003-09-21 22:35:10.000000000 -0700
@@ -1503,7 +1503,7 @@ decode_getattr(struct xdr_stream *xdr, s
 		READ32(major);
 		READ32(minor);
 		nfp->rdev = MKDEV(major, minor);
-		dprintk("read_attrs: rdev=0x%x\n", nfp->rdev);
+		dprintk("read_attrs: rdev=%u:%u\n", major, minor);
         }
         if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) {
                 READ_BUF(8);
diff -puN fs/nfs/proc.c~KD32-nfs-B5 fs/nfs/proc.c
--- 25/fs/nfs/proc.c~KD32-nfs-B5	2003-09-21 22:35:10.000000000 -0700
+++ 25-akpm/fs/nfs/proc.c	2003-09-21 22:35:10.000000000 -0700
@@ -277,7 +277,7 @@ nfs_proc_mknod(struct inode *dir, struct
 		sattr->ia_valid &= ~ATTR_SIZE;
 	} else if (S_ISCHR(mode) || S_ISBLK(mode)) {
 		sattr->ia_valid |= ATTR_SIZE;
-		sattr->ia_size   = rdev;	/* get out your barf bag */
+		sattr->ia_size = old_encode_dev(rdev);/* get out your barf bag */
 	}
 
 	fattr->valid = 0;
diff -puN include/linux/nfsd/export.h~KD32-nfs-B5 include/linux/nfsd/export.h
--- 25/include/linux/nfsd/export.h~KD32-nfs-B5	2003-09-21 22:35:10.000000000 -0700
+++ 25-akpm/include/linux/nfsd/export.h	2003-09-21 22:35:10.000000000 -0700
@@ -65,7 +65,7 @@ struct svc_expkey {
 
 	struct auth_domain *	ek_client;
 	int			ek_fsidtype;
-	u32			ek_fsid[2];
+	u32			ek_fsid[3];
 
 	struct svc_export *	ek_export;
 };
diff -puN include/linux/nfsd/nfsd.h~KD32-nfs-B5 include/linux/nfsd/nfsd.h
--- 25/include/linux/nfsd/nfsd.h~KD32-nfs-B5	2003-09-21 22:35:10.000000000 -0700
+++ 25-akpm/include/linux/nfsd/nfsd.h	2003-09-21 22:35:10.000000000 -0700
@@ -15,6 +15,7 @@
 #include <linux/unistd.h>
 #include <linux/dirent.h>
 #include <linux/fs.h>
+#include <linux/mount.h>
 
 #include <linux/nfsd/debug.h>
 #include <linux/nfsd/nfsfh.h>
@@ -207,6 +208,17 @@ void		nfsd_lockd_shutdown(void);
  */
 extern struct timeval	nfssvc_boot;
 
+static inline int is_fsid(struct svc_fh *fh, struct knfsd_fh *reffh)
+{
+	if (fh->fh_export->ex_flags & NFSEXP_FSID) {
+		struct vfsmount *mnt = fh->fh_export->ex_mnt;
+		if (!old_valid_dev(mnt->mnt_sb->s_dev) ||
+		    (reffh->fh_version == 1 && reffh->fh_fsid_type == 1))
+			return 1;
+	}
+	return 0;
+}
+
 
 #ifdef CONFIG_NFSD_V4
 
diff -puN include/linux/nfsd/nfsfh.h~KD32-nfs-B5 include/linux/nfsd/nfsfh.h
--- 25/include/linux/nfsd/nfsfh.h~KD32-nfs-B5	2003-09-21 22:35:10.000000000 -0700
+++ 25-akpm/include/linux/nfsd/nfsfh.h	2003-09-21 22:35:10.000000000 -0700
@@ -117,26 +117,6 @@ struct knfsd_fh {
 
 #ifdef __KERNEL__
 
-/*
- * Conversion macros for the filehandle fields.
- *
- * Keep the device numbers in "backwards compatible
- * format", ie the low 16 bits contain the low 8 bits
- * of the 20-bit minor and the 12-bit major number.
- *
- * The high 16 bits contain the rest (4 bits major
- * and 12 bits minor),
- */
-
-static inline dev_t u32_to_dev_t(__u32 udev)
-{
-	unsigned int minor, major;
-
-	minor = (udev & 0xff) | ((udev >> 8) & 0xfff00);
-	major = ((udev >> 8) & 0xff) | ((udev >> 20) & 0xf00);
-	return MKDEV(major, minor);
-}
-
 static inline __u32 ino_t_to_u32(ino_t ino)
 {
 	return (__u32) ino;
@@ -196,6 +176,12 @@ static inline void mk_fsid_v1(u32 *fsidv
 	fsidv[0] = fsid;
 }
 
+static inline void mk_fsid_v2(u32 *fsidv, dev_t dev, ino_t ino)
+{
+	fsidv[0] = htonl(MAJOR(dev));
+	fsidv[1] = htonl(MINOR(dev));
+	fsidv[2] = ino_t_to_u32(ino);
+}
 
 /*
  * Shorthand for dprintk()'s

_