[PATCH] knfsd: add some new fsid types

Add support for using a filesystem UUID to identify and export point in the
filehandle.

For NFSv2, this UUID is xor-ed down to 4 or 8 bytes so that it doesn't take up
too much room.  For NFSv3+, we use the full 16 bytes, and possibly also a
64bit inode number for exports beneath the root of a filesystem.

When generating an fsid to return in 'stat' information, use the UUID (hashed
down to size) if it is available and a small 'fsid' was not specifically
provided.

Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 6555c50..0c24b9e 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -153,6 +153,7 @@
 	struct dentry	*dentry = fhp->fh_dentry;
 	int type;
 	struct timespec time;
+	u32 f;
 
 	type = (stat->mode & S_IFMT);
 
@@ -173,10 +174,22 @@
 	else
 		*p++ = htonl(0xffffffff);
 	*p++ = htonl((u32) stat->blocks);
-	if (is_fsid(fhp, rqstp->rq_reffh))
-		*p++ = htonl((u32) fhp->fh_export->ex_fsid);
-	else
+	switch (fsid_source(fhp)) {
+	default:
+	case FSIDSOURCE_DEV:
 		*p++ = htonl(new_encode_dev(stat->dev));
+		break;
+	case FSIDSOURCE_FSID:
+		*p++ = htonl((u32) fhp->fh_export->ex_fsid);
+		break;
+	case FSIDSOURCE_UUID:
+		f = ((u32*)fhp->fh_export->ex_uuid)[0];
+		f ^= ((u32*)fhp->fh_export->ex_uuid)[1];
+		f ^= ((u32*)fhp->fh_export->ex_uuid)[2];
+		f ^= ((u32*)fhp->fh_export->ex_uuid)[3];
+		*p++ = htonl(f);
+		break;
+	}
 	*p++ = htonl((u32) stat->ino);
 	*p++ = htonl((u32) stat->atime.tv_sec);
 	*p++ = htonl(stat->atime.tv_nsec ? stat->atime.tv_nsec / 1000 : 0);