6344186 NFSv3 needs to support .zfs (like NFSv4 already does)
authorthurlow
Mon, 13 Mar 2006 17:10:47 -0800
changeset 1610 3436e82414c8
parent 1609 849e31419354
child 1611 2ffa29275ba7
6344186 NFSv3 needs to support .zfs (like NFSv4 already does)
usr/src/cmd/fs.d/nfs/mountd/mountd.c
usr/src/cmd/fs.d/nfs/mountd/mountd.h
usr/src/cmd/fs.d/nfs/nfslog/fhtab.h
usr/src/cmd/fs.d/nfs/nfslog/nfslog_elf.c
usr/src/lib/libc/port/sys/nfssys.c
usr/src/uts/common/fs/nfs/nfs3_srv.c
usr/src/uts/common/fs/nfs/nfs3_xdr.c
usr/src/uts/common/fs/nfs/nfs4_srv_ns.c
usr/src/uts/common/fs/nfs/nfs4_xdr.c
usr/src/uts/common/fs/nfs/nfs_acl_srv.c
usr/src/uts/common/fs/nfs/nfs_acl_xdr.c
usr/src/uts/common/fs/nfs/nfs_export.c
usr/src/uts/common/fs/nfs/nfs_log.c
usr/src/uts/common/fs/nfs/nfs_log_xdr.c
usr/src/uts/common/fs/nfs/nfs_server.c
usr/src/uts/common/fs/nfs/nfs_srv.c
usr/src/uts/common/nfs/nfs.h
usr/src/uts/common/nfs/nfs4.h
usr/src/uts/common/nfs/nfs_acl.h
usr/src/uts/common/nfs/nfs_dispatch.h
usr/src/uts/common/nfs/nfssys.h
--- a/usr/src/cmd/fs.d/nfs/mountd/mountd.c	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/cmd/fs.d/nfs/mountd/mountd.c	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -740,10 +739,11 @@
 mount(struct svc_req *rqstp)
 {
 	SVCXPRT *transp;
-	int version;
+	int version, vers;
 	struct fhstatus fhs;
 	struct mountres3 mountres3;
-	char fh3[FHSIZE3];
+	char fh[FHSIZE3];
+	int len = FHSIZE3;
 	char *path, rpath[MAXPATHLEN];
 	struct share *sh = NULL;
 	struct nd_hostservlist *clnames = NULL;
@@ -751,7 +751,6 @@
 	int error = 0, lofs_tried = 0;
 	int flavor_list[MAX_FLAVORS];
 	int flavor_count;
-	char *fhp;
 	struct netbuf *nb;
 
 	transp = rqstp->rq_xprt;
@@ -832,25 +831,14 @@
 	/*
 	 * Now get the filehandle.
 	 *
-	 * We assume here that the filehandle returned from
-	 * nfs_getfh() is only 32 bytes which is the size of struct svcfh.
-	 * NFS V2 clients get only the 32 byte filehandle.
-	 * NFS V3 clients get a 64 byte filehandle consisting
-	 * of a 32 byte filehandle followed by 32 bytes of nulls.
+	 * NFS V2 clients get a 32 byte filehandle.
+	 * NFS V3 clients get a 32 or 64 byte filehandle, depending on
+	 * the embedded FIDs.
 	 */
-	if (version == MOUNTVERS3) {
-		mountres3.mountres3_u.mountinfo.fhandle.fhandle3_len =
-								NFS3_CURFHSIZE;
-		mountres3.mountres3_u.mountinfo.fhandle.fhandle3_val = fh3;
-		fhp = fh3;
-		(void) memset(fhp + NFS3_CURFHSIZE, 0,
-						NFS3_FHSIZE-NFS3_CURFHSIZE);
-	} else {
-		fhp = (char *)&fhs.fhstatus_u.fhs_fhandle;
-	}
+	vers = (version == MOUNTVERS3) ? NFS_V3 : NFS_VERSION;
 
 	/* LINTED pointer alignment */
-	while (nfs_getfh(rpath, (fhandle_t *)fhp) < 0) {
+	while (nfs_getfh(rpath, vers, &len, fh) < 0) {
 		if (errno == EINVAL &&
 			(sh = find_lofsentry(rpath, &lofs_tried)) != NULL) {
 			errno = 0;
@@ -862,6 +850,13 @@
 		break;
 	}
 
+	if (version == MOUNTVERS3) {
+		mountres3.mountres3_u.mountinfo.fhandle.fhandle3_len = len;
+		mountres3.mountres3_u.mountinfo.fhandle.fhandle3_val = fh;
+	} else {
+		bcopy(fh, &fhs.fhstatus_u.fhs_fhandle, NFS_FHSIZE);
+	}
+
 reply:
 	switch (version) {
 	case MOUNTVERS:
--- a/usr/src/cmd/fs.d/nfs/mountd/mountd.h	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/cmd/fs.d/nfs/mountd/mountd.h	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -50,7 +49,7 @@
 extern int svc_create_local_service(void (*) (), ulong_t, ulong_t,
 					char *, char *);
 extern char *inet_ntoa_r(struct in_addr, char *);
-extern int nfs_getfh(char *, fhandle_t *);
+extern int nfs_getfh(char *, int, int *, char *);
 
 extern void nfsauth_prog(struct svc_req *, SVCXPRT *);
 
--- a/usr/src/cmd/fs.d/nfs/nfslog/fhtab.h	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/cmd/fs.d/nfs/nfslog/fhtab.h	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
  * CDDL HEADER END
  */
 /*
- * Copyright (c) 1999 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
  */
 
 #ifndef _FHTAB_H
@@ -166,7 +165,7 @@
  */
 #define	NFSLOG_GET_FHANDLE3(fh3)					\
 	(((fh3)->fh3_length == sizeof (fhandle_t)) ?			\
-		&(fh3)->fh3_u.nfs_fh3_i.fh3_i : &public_fh)
+		(fhandle_t *)&(fh3)->fh3_u.data : &public_fh)
 
 #ifdef __cplusplus
 }
--- a/usr/src/cmd/fs.d/nfs/nfslog/nfslog_elf.c	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/cmd/fs.d/nfs/nfslog/nfslog_elf.c	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -592,8 +591,8 @@
 {
 	if (!nfsl_print_fh)
 		return;
-	if (fh3->fh3_length == sizeof (fh3->fh3_u.nfs_fh3_i.fh3_i)) {
-		nfslog_fhandle_print(elfrec, &fh3->fh3_u.nfs_fh3_i.fh3_i);
+	if (fh3->fh3_length == sizeof (fhandle_t)) {
+		nfslog_fhandle_print(elfrec, (fhandle_t *)&fh3->fh3_u.data);
 	} else {
 		nfslog_opaque_print_buf(fh3->fh3_u.data, fh3->fh3_length,
 			elfrec->buf, &elfrec->bufoffset,
--- a/usr/src/lib/libc/port/sys/nfssys.c	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/lib/libc/port/sys/nfssys.c	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -59,11 +58,13 @@
 }
 
 int
-nfs_getfh(char *path, fhandle_t *fhp)
+nfs_getfh(char *path, int vers, int *lenp, char *fhp)
 {
 	struct nfs_getfh_args nga;
 
 	nga.fname = path;
+	nga.vers = vers;
+	nga.lenp = lenp;
 	nga.fhp = fhp;
 	return (_nfssys(NFS_GETFH, &nga));
 }
--- a/usr/src/uts/common/fs/nfs/nfs3_srv.c	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs3_srv.c	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -115,11 +114,11 @@
 		resp->status = puterrno3(error);
 }
 
-fhandle_t *
+void *
 rfs3_getattr_getfh(GETATTR3args *args)
 {
 
-	return ((fhandle_t *)&args->object.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->object);
 }
 
 void
@@ -305,11 +304,11 @@
 	vattr_to_wcc_data(bvap, avap, &resp->resfail.obj_wcc);
 }
 
-fhandle_t *
+void *
 rfs3_setattr_getfh(SETATTR3args *args)
 {
 
-	return ((fhandle_t *)&args->object.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->object);
 }
 
 /* ARGSUSED */
@@ -338,7 +337,7 @@
 		dvp = rootdir;
 		VN_HOLD(dvp);
 	} else {
-		dvp = nfs3_fhtovp(args->what.dirp, exi);
+		dvp = nfs3_fhtovp(&args->what.dir, exi);
 		if (dvp == NULL) {
 			error = ESTALE;
 			goto out;
@@ -365,9 +364,9 @@
 		goto out1;
 	}
 
-	fhp = args->what.dirp;
+	fhp = &args->what.dir;
 	if (strcmp(args->what.name, "..") == 0 &&
-	    EQFID(&exi->exi_fid, (fid_t *)&fhp->fh3_len)) {
+	    EQFID(&exi->exi_fid, FH3TOFIDP(fhp))) {
 		resp->status = NFS3ERR_NOENT;
 		goto out1;
 	}
@@ -376,7 +375,7 @@
 	 * If the public filehandle is used then allow
 	 * a multi-component lookup
 	 */
-	if (PUBLIC_FH3(args->what.dirp)) {
+	if (PUBLIC_FH3(&args->what.dir)) {
 		publicfh_flag = TRUE;
 		error = rfs_publicfh_mclookup(args->what.name, dvp, cr, &vp,
 					&exi, &sec);
@@ -465,11 +464,11 @@
 
 }
 
-fhandle_t *
+void *
 rfs3_lookup_getfh(LOOKUP3args *args)
 {
 
-	return ((fhandle_t *)&args->what.dirp->fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->what.dir);
 }
 
 /* ARGSUSED */
@@ -595,11 +594,11 @@
 	vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
 }
 
-fhandle_t *
+void *
 rfs3_access_getfh(ACCESS3args *args)
 {
 
-	return ((fhandle_t *)&args->object.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->object);
 }
 
 /* ARGSUSED */
@@ -706,11 +705,11 @@
 	vattr_to_post_op_attr(vap, &resp->resfail.symlink_attributes);
 }
 
-fhandle_t *
+void *
 rfs3_readlink_getfh(READLINK3args *args)
 {
 
-	return ((fhandle_t *)&args->symlink.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->symlink);
 }
 
 void
@@ -955,11 +954,11 @@
 	}
 }
 
-fhandle_t *
+void *
 rfs3_read_getfh(READ3args *args)
 {
 
-	return ((fhandle_t *)&args->file.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->file);
 }
 
 #define	MAX_IOVECS	12
@@ -1189,11 +1188,11 @@
 	vattr_to_wcc_data(bvap, avap, &resp->resfail.file_wcc);
 }
 
-fhandle_t *
+void *
 rfs3_write_getfh(WRITE3args *args)
 {
 
-	return ((fhandle_t *)&args->file.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->file);
 }
 
 void
@@ -1219,7 +1218,7 @@
 	dbvap = NULL;
 	davap = NULL;
 
-	dvp = nfs3_fhtovp(args->where.dirp, exi);
+	dvp = nfs3_fhtovp(&args->where.dir, exi);
 	if (dvp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -1535,11 +1534,11 @@
 	vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
 }
 
-fhandle_t *
+void *
 rfs3_create_getfh(CREATE3args *args)
 {
 
-	return ((fhandle_t *)&args->where.dir.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->where.dir);
 }
 
 void
@@ -1559,7 +1558,7 @@
 	dbvap = NULL;
 	davap = NULL;
 
-	dvp = nfs3_fhtovp(args->where.dirp, exi);
+	dvp = nfs3_fhtovp(&args->where.dir, exi);
 	if (dvp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -1676,11 +1675,11 @@
 	vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
 }
 
-fhandle_t *
+void *
 rfs3_mkdir_getfh(MKDIR3args *args)
 {
 
-	return ((fhandle_t *)&args->where.dir.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->where.dir);
 }
 
 void
@@ -1700,7 +1699,7 @@
 	dbvap = NULL;
 	davap = NULL;
 
-	dvp = nfs3_fhtovp(args->where.dirp, exi);
+	dvp = nfs3_fhtovp(&args->where.dir, exi);
 	if (dvp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -1832,11 +1831,11 @@
 	vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
 }
 
-fhandle_t *
+void *
 rfs3_symlink_getfh(SYMLINK3args *args)
 {
 
-	return ((fhandle_t *)&args->where.dirp->fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->where.dir);
 }
 
 void
@@ -1858,7 +1857,7 @@
 	dbvap = NULL;
 	davap = NULL;
 
-	dvp = nfs3_fhtovp(args->where.dirp, exi);
+	dvp = nfs3_fhtovp(&args->where.dir, exi);
 	if (dvp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -2018,11 +2017,11 @@
 	vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
 }
 
-fhandle_t *
+void *
 rfs3_mknod_getfh(MKNOD3args *args)
 {
 
-	return ((fhandle_t *)&args->where.dirp->fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->where.dir);
 }
 
 void
@@ -2040,7 +2039,7 @@
 	bvap = NULL;
 	avap = NULL;
 
-	vp = nfs3_fhtovp(args->object.dirp, exi);
+	vp = nfs3_fhtovp(&args->object.dir, exi);
 	if (vp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -2143,11 +2142,11 @@
 	vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc);
 }
 
-fhandle_t *
+void *
 rfs3_remove_getfh(REMOVE3args *args)
 {
 
-	return ((fhandle_t *)&args->object.dirp->fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->object.dir);
 }
 
 void
@@ -2164,7 +2163,7 @@
 	bvap = NULL;
 	avap = NULL;
 
-	vp = nfs3_fhtovp(args->object.dirp, exi);
+	vp = nfs3_fhtovp(&args->object.dir, exi);
 	if (vp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -2250,11 +2249,11 @@
 	vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc);
 }
 
-fhandle_t *
+void *
 rfs3_rmdir_getfh(RMDIR3args *args)
 {
 
-	return ((fhandle_t *)&args->object.dirp->fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->object.dir);
 }
 
 void
@@ -2273,7 +2272,7 @@
 	struct vattr tbva;
 	struct vattr *tavap;
 	struct vattr tava;
-	nfs_fh3	*fh3;
+	nfs_fh3 *fh3;
 	struct exportinfo *to_exi;
 	vnode_t *srcvp = NULL;
 
@@ -2283,7 +2282,7 @@
 	tavap = NULL;
 	tvp = NULL;
 
-	fvp = nfs3_fhtovp(args->from.dirp, exi);
+	fvp = nfs3_fhtovp(&args->from.dir, exi);
 	if (fvp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -2301,8 +2300,8 @@
 #endif
 	favap = fbvap;
 
-	fh3 = args->to.dirp;
-	to_exi = checkexport(&fh3->fh3_fsid, (fid_t *)&fh3->fh3_xlen);
+	fh3 = &args->to.dir;
+	to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3));
 	if (to_exi == NULL) {
 		resp->status = NFS3ERR_ACCES;
 		goto out1;
@@ -2314,7 +2313,7 @@
 		goto out1;
 	}
 
-	tvp = nfs3_fhtovp(args->to.dirp, exi);
+	tvp = nfs3_fhtovp(&args->to.dir, exi);
 	if (tvp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -2465,11 +2464,11 @@
 	vattr_to_wcc_data(tbvap, tavap, &resp->resfail.todir_wcc);
 }
 
-fhandle_t *
+void *
 rfs3_rename_getfh(RENAME3args *args)
 {
 
-	return ((fhandle_t *)&args->from.dirp->fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->from.dir);
 }
 
 void
@@ -2510,8 +2509,8 @@
 	vap = VOP_GETATTR(vp, &va, 0, cr) ? NULL : &va;
 #endif
 
-	fh3 = args->link.dirp;
-	to_exi = checkexport(&fh3->fh3_fsid, (fid_t *)&fh3->fh3_xlen);
+	fh3 = &args->link.dir;
+	to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3));
 	if (to_exi == NULL) {
 		resp->status = NFS3ERR_ACCES;
 		goto out1;
@@ -2523,7 +2522,7 @@
 		goto out1;
 	}
 
-	dvp = nfs3_fhtovp(args->link.dirp, exi);
+	dvp = nfs3_fhtovp(&args->link.dir, exi);
 	if (dvp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -2611,11 +2610,11 @@
 	vattr_to_wcc_data(bvap, avap, &resp->resfail.linkdir_wcc);
 }
 
-fhandle_t *
+void *
 rfs3_link_getfh(LINK3args *args)
 {
 
-	return ((fhandle_t *)&args->file.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->file);
 }
 
 /*
@@ -2833,11 +2832,11 @@
 	vattr_to_post_op_attr(vap, &resp->resfail.dir_attributes);
 }
 
-fhandle_t *
+void *
 rfs3_readdir_getfh(READDIR3args *args)
 {
 
-	return ((fhandle_t *)&args->dir.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->dir);
 }
 
 void
@@ -2869,13 +2868,13 @@
  * attributes - NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT
  * status byte for file handle - 1 *  BYTES_PER_XDR_UNIT
  * length of a file handle - 1 * BYTES_PER_XDR_UNIT
- * Maxmum length of a file handle (NFS3_CURFHSIZE)
+ * Maxmum length of a file handle (NFS3_MAXFHSIZE)
  * name length of the entry to the nearest bytes
  */
 #define	NFS3_READDIRPLUS_ENTRY(namelen)	\
 	((1 + 2 + 1 + 2 + 1 + NFS3_SIZEOF_FATTR3 + 1 + 1) * \
 		BYTES_PER_XDR_UNIT + \
-	NFS3_CURFHSIZE + roundup(namelen, BYTES_PER_XDR_UNIT))
+	NFS3_MAXFHSIZE + roundup(namelen, BYTES_PER_XDR_UNIT))
 
 static int rfs3_readdir_unit = MAXBSIZE;
 
@@ -3200,11 +3199,11 @@
 	vattr_to_post_op_attr(vap, &resp->resfail.dir_attributes);
 }
 
-fhandle_t *
+void *
 rfs3_readdirplus_getfh(READDIRPLUS3args *args)
 {
 
-	return ((fhandle_t *)&args->dir.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->dir);
 }
 
 void
@@ -3284,11 +3283,11 @@
 	vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
 }
 
-fhandle_t *
+void *
 rfs3_fsstat_getfh(FSSTAT3args *args)
 {
 
-	return ((fhandle_t *)&args->fsroot.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->fsroot);
 }
 
 /* ARGSUSED */
@@ -3355,11 +3354,11 @@
 	    FSF3_HOMOGENEOUS | FSF3_CANSETTIME;
 }
 
-fhandle_t *
+void *
 rfs3_fsinfo_getfh(FSINFO3args *args)
 {
 
-	return ((fhandle_t *)&args->fsroot.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->fsroot);
 }
 
 /* ARGSUSED */
@@ -3437,11 +3436,11 @@
 	vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
 }
 
-fhandle_t *
+void *
 rfs3_pathconf_getfh(PATHCONF3args *args)
 {
 
-	return ((fhandle_t *)&args->object.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->object);
 }
 
 void
@@ -3534,11 +3533,11 @@
 	vattr_to_wcc_data(bvap, avap, &resp->resfail.file_wcc);
 }
 
-fhandle_t *
+void *
 rfs3_commit_getfh(COMMIT3args *args)
 {
 
-	return ((fhandle_t *)&args->file.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->file);
 }
 
 static int
--- a/usr/src/uts/common/fs/nfs/nfs3_xdr.c	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs3_xdr.c	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -45,6 +44,7 @@
 #include <sys/dnlc.h>
 #include <sys/cred.h>
 #include <sys/time.h>
+#include <sys/sdt.h>
 
 #include <rpc/types.h>
 #include <rpc/xdr.h>
@@ -52,11 +52,6 @@
 #include <nfs/nfs.h>
 #include <nfs/rnode.h>
 
-/* Checks if the fh is 32 bytes and returns TRUE if it is, otherwise FALSE */
-#define	XDR_CHECKFHSIZE(x, len, sz)	\
-	(((int32_t)ntohl(len) == NFS3_CURFHSIZE) ? TRUE : \
-	(xdr_rewind(x, sz), FALSE))
-
 /*
  * These are the XDR routines used to serialize and deserialize
  * the various structures passed as parameters across the network
@@ -154,66 +149,296 @@
 }
 
 /*
- * If the filehandle is not equal to NFS3_CURFHSIZE then
- * rewind/set the pointer back to it's previous location prior to
- * the call.
- * Inlining is only being done for 32 byte fhandles since
- * predominantly the size of the fh is 32 and thus
- * optimizing only this case would be the best.
+ * XDR_INLINE decode a filehandle.
  */
-static void
-xdr_rewind(register XDR *xdrs, uint_t inl_sz)
+bool_t
+xdr_inline_decode_nfs_fh3(uint32_t *ptr, nfs_fh3 *fhp, uint32_t fhsize)
 {
-	uint_t curpos;
+	uchar_t *bp = (uchar_t *)ptr;
+	uchar_t *cp;
+	uint32_t dsize;
+	uintptr_t resid;
+
+	/*
+	 * Check to see if what the client sent us is bigger or smaller
+	 * than what we can ever possibly send out. NFS_FHMAXDATA is
+	 * unfortunately badly named as it is no longer the max and is
+	 * really the min of what is sent over the wire.
+	 */
+	if (fhsize > sizeof (fhandle3_t) || fhsize < (sizeof (fsid_t) +
+	    sizeof (ushort_t) + NFS_FHMAXDATA +
+	    sizeof (ushort_t) + NFS_FHMAXDATA)) {
+		return (FALSE);
+	}
+
+	/*
+	 * All internal parts of a filehandle are in native byte order.
+	 *
+	 * Decode what should be fh3_fsid, it is aligned.
+	 */
+	fhp->fh3_fsid.val[0] = *(uint32_t *)bp;
+	bp += BYTES_PER_XDR_UNIT;
+	fhp->fh3_fsid.val[1] = *(uint32_t *)bp;
+	bp += BYTES_PER_XDR_UNIT;
+
+	/*
+	 * Decode what should be fh3_len.  fh3_len is two bytes, so we're
+	 * unaligned now.
+	 */
+	cp = (uchar_t *)&fhp->fh3_len;
+	*cp++ = *bp++;
+	*cp++ = *bp++;
+	fhsize -= 2 * BYTES_PER_XDR_UNIT + sizeof (ushort_t);
+
+	/*
+	 * For backwards compatability, the fid length may be less than
+	 * NFS_FHMAXDATA, but it was always encoded as NFS_FHMAXDATA bytes.
+	 */
+	dsize = fhp->fh3_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_len;
 
-	curpos = XDR_GETPOS(xdrs);
-	(void) XDR_SETPOS(xdrs, curpos - inl_sz);
+	/*
+	 * Make sure the client isn't sending us a bogus length for fh3x_data.
+	 */
+	if (fhsize < dsize)
+		return (FALSE);
+	bcopy(bp, fhp->fh3_data, dsize);
+	bp += dsize;
+	fhsize -= dsize;
+
+	if (fhsize < sizeof (ushort_t))
+		return (FALSE);
+	cp = (uchar_t *)&fhp->fh3_xlen;
+	*cp++ = *bp++;
+	*cp++ = *bp++;
+	fhsize -= sizeof (ushort_t);
+
+	dsize = fhp->fh3_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_xlen;
+
+	/*
+	 * Make sure the client isn't sending us a bogus length for fh3x_xdata.
+	 */
+	if (fhsize < dsize)
+		return (FALSE);
+	bcopy(bp, fhp->fh3_xdata, dsize);
+	fhsize -= dsize;
+	bp += dsize;
+
+	/*
+	 * We realign things on purpose, so skip any padding
+	 */
+	resid = (uintptr_t)bp % BYTES_PER_XDR_UNIT;
+	if (resid != 0) {
+		if (fhsize < (BYTES_PER_XDR_UNIT - resid))
+			return (FALSE);
+		bp += BYTES_PER_XDR_UNIT - resid;
+		fhsize -= BYTES_PER_XDR_UNIT - resid;
+	}
+
+	/*
+	 * Make sure client didn't send extra bytes
+	 */
+	if (fhsize != 0)
+		return (FALSE);
+	return (TRUE);
 }
 
+static bool_t
+xdr_decode_nfs_fh3(XDR *xdrs, nfs_fh3 *objp)
+{
+	uint32_t fhsize;		/* filehandle size */
+	uint32_t bufsize;
+	rpc_inline_t *ptr;
+	uchar_t *bp;
+
+	ASSERT(xdrs->x_op == XDR_DECODE);
+
+	/*
+	 * Retrieve the filehandle length.
+	 */
+	if (!XDR_GETINT32(xdrs, (int32_t *)&fhsize))
+		return (FALSE);
+
+	bzero(objp->fh3_u.data, sizeof (objp->fh3_u.data));
+	objp->fh3_length = 0;
+
+	/*
+	 * Check to see if what the client sent us is bigger or smaller
+	 * than what we can ever possibly send out. NFS_FHMAXDATA is
+	 * unfortunately badly named as it is no longer the max and is
+	 * really the min of what is sent over the wire.
+	 */
+	if (fhsize > sizeof (fhandle3_t) || fhsize < (sizeof (fsid_t) +
+	    sizeof (ushort_t) + NFS_FHMAXDATA +
+	    sizeof (ushort_t) + NFS_FHMAXDATA)) {
+		if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fhsize))
+			return (FALSE);
+		return (TRUE);
+	}
+
+	/*
+	 * bring in fhsize plus any padding
+	 */
+	bufsize = RNDUP(fhsize);
+	ptr = XDR_INLINE(xdrs, bufsize);
+	bp = (uchar_t *)ptr;
+	if (ptr == NULL) {
+		bp = kmem_alloc(bufsize, KM_SLEEP);
+		if (!xdr_opaque(xdrs, (char *)bp, bufsize)) {
+			kmem_free(bp, bufsize);
+			return (FALSE);
+		}
+	}
+
+	objp->fh3_length = sizeof (fhandle3_t);
+
+	if (xdr_inline_decode_nfs_fh3((uint32_t *)bp, objp, fhsize) == FALSE) {
+		/*
+		 * If in the process of decoding we find the file handle
+		 * is not correctly formed, we need to continue decoding
+		 * and trigger an NFS layer error. Set the nfs_fh3_len to
+		 * zero so it gets caught as a bad length.
+		 */
+		bzero(objp->fh3_u.data, sizeof (objp->fh3_u.data));
+		objp->fh3_length = 0;
+	}
+
+	if (ptr == NULL)
+		kmem_free(bp, bufsize);
+	return (TRUE);
+}
+
+/*
+ * XDR_INLINE encode a filehandle.
+ */
+bool_t
+xdr_inline_encode_nfs_fh3(uint32_t **ptrp, uint32_t *ptr_redzone,
+	nfs_fh3 *fhp)
+{
+	uint32_t *ptr = *ptrp;
+	uchar_t *cp;
+	uint_t otw_len, fsize, xsize;   /* otw, file, and export sizes */
+	uint32_t padword;
+
+	fsize = fhp->fh3_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_len;
+	xsize = fhp->fh3_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_xlen;
+
+	/*
+	 * First get the initial and variable sized part of the filehandle.
+	 */
+	otw_len = sizeof (fhp->fh3_fsid) +
+	    sizeof (fhp->fh3_len) + fsize +
+	    sizeof (fhp->fh3_xlen) + xsize;
+
+	/*
+	 * Round out to a full word.
+	 */
+	otw_len = RNDUP(otw_len);
+	padword = (otw_len / BYTES_PER_XDR_UNIT);	/* includes fhlen */
+
+	/*
+	 * Make sure we don't exceed our buffer.
+	 */
+	if ((ptr + (otw_len / BYTES_PER_XDR_UNIT) + 1) > ptr_redzone)
+		return (FALSE);
+
+	/*
+	 * Zero out the pading.
+	 */
+	ptr[padword] = 0;
+
+	IXDR_PUT_U_INT32(ptr, otw_len);
+
+	/*
+	 * The rest of the filehandle is in native byteorder
+	 */
+	/* fh3_fsid */
+	*ptr++ = (uint32_t)fhp->fh3_fsid.val[0];
+	*ptr++ = (uint32_t)fhp->fh3_fsid.val[1];
+
+	/*
+	 * Since the next pieces are unaligned, we need to
+	 * do bytewise copies.
+	 */
+	cp = (uchar_t *)ptr;
+
+	/* fh3_len + fh3_data */
+	bcopy(&fhp->fh3_len, cp, sizeof (fhp->fh3_len) + fsize);
+	cp += sizeof (fhp->fh3_len) + fsize;
+
+	/* fh3_xlen + fh3_xdata */
+	bcopy(&fhp->fh3_xlen, cp, sizeof (fhp->fh3_xlen) + xsize);
+	cp += sizeof (fhp->fh3_xlen) + xsize;
+
+	/* do necessary rounding/padding */
+	cp = (uchar_t *)RNDUP((uintptr_t)cp);
+	ptr = (uint32_t *)cp;
+
+	/*
+	 * With the above padding, we're word aligned again.
+	 */
+	ASSERT(((uintptr_t)ptr % BYTES_PER_XDR_UNIT) == 0);
+
+	*ptrp = ptr;
+
+	return (TRUE);
+}
+
+static bool_t
+xdr_encode_nfs_fh3(XDR *xdrs, nfs_fh3 *objp)
+{
+	uint_t otw_len, fsize, xsize;   /* otw, file, and export sizes */
+	bool_t ret;
+	rpc_inline_t *ptr;
+	rpc_inline_t *buf = NULL;
+	uint32_t *ptr_redzone;
+
+	ASSERT(xdrs->x_op == XDR_ENCODE);
+
+	fsize = objp->fh3_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : objp->fh3_len;
+	xsize = objp->fh3_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : objp->fh3_xlen;
+
+	/*
+	 * First get the over the wire size, it is the 4 bytes
+	 * for the length, plus the combined size of the
+	 * file handle components.
+	 */
+	otw_len = BYTES_PER_XDR_UNIT + sizeof (objp->fh3_fsid) +
+	    sizeof (objp->fh3_len) + fsize +
+	    sizeof (objp->fh3_xlen) + xsize;
+	/*
+	 * Round out to a full word.
+	 */
+	otw_len = RNDUP(otw_len);
+
+	/*
+	 * Next try to inline the XDR stream, if that fails (rare)
+	 * allocate a buffer to encode the file handle and then
+	 * copy it using xdr_opaque and free the buffer.
+	 */
+	ptr = XDR_INLINE(xdrs, otw_len);
+	if (ptr == NULL)
+		ptr = buf = kmem_alloc(otw_len, KM_SLEEP);
+
+	ptr_redzone = (uint32_t *)(ptr + (otw_len / BYTES_PER_XDR_UNIT));
+	ret = xdr_inline_encode_nfs_fh3((uint32_t **)&ptr, ptr_redzone, objp);
+
+	if (buf != NULL) {
+		if (ret == TRUE)
+			ret = xdr_opaque(xdrs, (char *)buf, otw_len);
+		kmem_free(buf, otw_len);
+	}
+	return (ret);
+}
+
+/*
+ * XDR a NFSv3 filehandle the naive way.
+ */
 bool_t
 xdr_nfs_fh3(XDR *xdrs, nfs_fh3 *objp)
 {
-	int32_t *ptr;
-	int32_t *fhp;
-	uint_t len;
-	uint_t in_size;
-
 	if (xdrs->x_op == XDR_FREE)
 		return (TRUE);
 
-	in_size = RNDUP(sizeof (fhandle_t)) +	1 * BYTES_PER_XDR_UNIT;
-
-	ptr = XDR_INLINE(xdrs, in_size);
-	if (ptr != NULL) {
-		len = ((xdrs->x_op == XDR_DECODE) ? *ptr : objp->fh3_length);
-
-		if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
-			fhp = (int32_t *)&(objp->fh3_u.data);
-			if (xdrs->x_op == XDR_DECODE) {
-				objp->fh3_length = IXDR_GET_U_INT32(ptr);
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp = *ptr;
-			} else {
-				IXDR_PUT_U_INT32(ptr, objp->fh3_length);
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr = *fhp;
-			}
-			return (TRUE);
-		}
-	}
-
 	if (!xdr_u_int(xdrs, &objp->fh3_length))
 		return (FALSE);
 
@@ -224,30 +449,21 @@
 }
 
 /*
- * Will only consider the DECODE case for the fast way
- * since it does not require any additional allocation of
- * memory and thus can just assign the objp to point to
- * the data returned from XDR_INLINE
+ * XDR a NFSv3 filehandle with intelligence on the server.
+ * Encoding goes from our in-memory structure to wire format.
+ * Decoding goes from wire format to our in-memory structure.
  */
 bool_t
-xdr_fastnfs_fh3(register XDR *xdrs, nfs_fh3 **objp)
+xdr_nfs_fh3_server(XDR *xdrs, nfs_fh3 *objp)
 {
-	int32_t *ptr;
-	uint_t in_size;
-
-	if (xdrs->x_op != XDR_DECODE)
-		return (FALSE);
-
-	in_size = RNDUP(sizeof (fhandle_t)) + 1 * BYTES_PER_XDR_UNIT;
-
-	ptr = XDR_INLINE(xdrs, in_size);
-
-	if ((ptr != NULL) && (XDR_CHECKFHSIZE(xdrs, *ptr, in_size))) {
-#ifdef _LITTLE_ENDIAN
-		/* Decode the length */
-		*ptr = (int32_t)ntohl(*(uint32_t *)ptr);
-#endif
-		*objp = (nfs_fh3 *) ptr;
+	switch (xdrs->x_op) {
+	case XDR_ENCODE:
+		return (xdr_encode_nfs_fh3(xdrs, objp));
+	case XDR_DECODE:
+		return (xdr_decode_nfs_fh3(xdrs, objp));
+	case XDR_FREE:
+		if (objp->fh3_u.data != NULL)
+			bzero(objp->fh3_u.data, sizeof (objp->fh3_u.data));
 		return (TRUE);
 	}
 	return (FALSE);
@@ -256,197 +472,20 @@
 bool_t
 xdr_diropargs3(XDR *xdrs, diropargs3 *objp)
 {
-	uint32_t size;
-	int32_t *ptr;
-	int32_t *fhp;
-	uint32_t nodesize;
-	uint32_t in_size;
-	int rndup, i;
-	char *cptr;
-
-	if (xdrs->x_op == XDR_DECODE) {
-		objp->dirp = &objp->dir;
-		/* includes: fh, length of fh, and length of name */
-		in_size = RNDUP(sizeof (fhandle_t)) + 2 * BYTES_PER_XDR_UNIT;
-
-		ptr = XDR_INLINE(xdrs, in_size);
-
-		if (ptr != NULL) {
-		    if (XDR_CHECKFHSIZE(xdrs, *ptr, in_size)) {
-			    fhp = (int32_t *)(objp->dir.fh3_u.data);
-			    /* Get length of fhandle and then fh. */
-			    objp->dir.fh3_length = IXDR_GET_U_INT32(ptr);
-			    *fhp++ = *ptr++;
-			    *fhp++ = *ptr++;
-			    *fhp++ = *ptr++;
-			    *fhp++ = *ptr++;
-			    *fhp++ = *ptr++;
-			    *fhp++ = *ptr++;
-			    *fhp++ = *ptr++;
-			    *fhp = *ptr++;
-
-			    size = IXDR_GET_U_INT32(ptr);
-
-			    if (size >= MAXNAMELEN) {
-				    objp->name = nfs3nametoolong;
-				    if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES,
-						&size))
-					    return (FALSE);
-				    return (TRUE);
-			    }
-			    nodesize = size+1;
-			    if (nodesize == 0)
-				    return (TRUE);
-			    if (objp->name == NULL) {
-				    objp->name = (char *)kmem_alloc(nodesize,
-								    KM_NOSLEEP);
-				    if (objp->name == NULL)
-					    return (FALSE);
-				    objp->flags |= DA_FREENAME;
-			    }
-			    ptr = XDR_INLINE(xdrs, RNDUP(size));
-			    if (ptr == NULL) {
-				if (! xdr_opaque(xdrs, objp->name, size)) {
-					if (objp->flags & DA_FREENAME) {
-						kmem_free(objp->name,
-							nodesize);
-						objp->name = NULL;
-					}
-					return (FALSE);
-				}
-				objp->name[size] = '\0';
-				if (strlen(objp->name) != size) {
-					if (objp->flags & DA_FREENAME) {
-						kmem_free(objp->name,
-							nodesize);
-						objp->name = NULL;
-					}
-					return (FALSE);
-				}
-				return (TRUE);
-			    }
-			    bcopy((char *)ptr, objp->name, size);
-			    objp->name[size] = '\0';
-			    if (strlen(objp->name) != size) {
-				    if (objp->flags & DA_FREENAME) {
-					    kmem_free(objp->name,
-						nodesize);
-					    objp->name = NULL;
-				    }
-				    return (FALSE);
-			    }
-			    return (TRUE);
-		    }
-		}
-		if (objp->name == NULL)
-			objp->flags |= DA_FREENAME;
+	switch (xdrs->x_op) {
+	case XDR_FREE:
+	case XDR_ENCODE:
+		if (!xdr_nfs_fh3(xdrs, objp->dirp))
+			return (FALSE);
+		break;
+	case XDR_DECODE:
+		if (!xdr_nfs_fh3_server(xdrs, &objp->dir))
+			return (FALSE);
+		break;
 	}
-
-	if ((xdrs->x_op == XDR_ENCODE) &&
-	    (objp->dirp->fh3_length == NFS3_CURFHSIZE)) {
-		fhp = (int32_t *)(objp->dirp->fh3_u.data);
-		size = strlen(objp->name);
-		in_size = RNDUP(sizeof (fhandle_t)) +
-			(2 * BYTES_PER_XDR_UNIT) + RNDUP(size);
-
-		ptr = XDR_INLINE(xdrs, in_size);
-		if (ptr != NULL) {
-			IXDR_PUT_U_INT32(ptr, objp->dirp->fh3_length);
-			*ptr++ = *fhp++;
-			*ptr++ = *fhp++;
-			*ptr++ = *fhp++;
-			*ptr++ = *fhp++;
-			*ptr++ = *fhp++;
-			*ptr++ = *fhp++;
-			*ptr++ = *fhp++;
-			*ptr++ = *fhp;
-
-			IXDR_PUT_U_INT32(ptr, (uint32_t)size);
-
-			bcopy(objp->name, (char *)ptr, size);
-			rndup = BYTES_PER_XDR_UNIT -
-				(size % BYTES_PER_XDR_UNIT);
-			if (rndup != BYTES_PER_XDR_UNIT) {
-				cptr = (char *)ptr + size;
-				for (i = 0; i < rndup; i++)
-					*cptr++ = '\0';
-			}
-			return (TRUE);
-		}
-	}
-	if (xdrs->x_op == XDR_FREE) {
-		if ((objp->name == NULL) || (objp->name == nfs3nametoolong))
-			return (TRUE);
-		size = strlen(objp->name);
-		if (objp->flags & DA_FREENAME)
-			kmem_free(objp->name, size + 1);
-		objp->name = NULL;
-		return (TRUE);
-	}
-	/* Normal case */
-	if (!xdr_nfs_fh3(xdrs, objp->dirp))
-		return (FALSE);
 	return (xdr_string3(xdrs, &objp->name, MAXNAMELEN));
 }
 
-bool_t
-xdr_fastdiropargs3(XDR *xdrs, diropargs3 **objp)
-{
-	int32_t *ptr;
-	uint_t size;
-	uint_t nodesize;
-	struct diropargs3 *da;
-	uint_t in_size;
-	uint_t skipsize;
-
-	if (xdrs->x_op != XDR_DECODE)
-		return (FALSE);
-
-	in_size = RNDUP(sizeof (fhandle_t)) +	1 * BYTES_PER_XDR_UNIT;
-
-	/* includes the fh and fh length */
-	ptr = XDR_INLINE(xdrs, in_size);
-
-	if ((ptr != NULL) && (XDR_CHECKFHSIZE(xdrs, *ptr, in_size))) {
-		da = *objp;
-#ifdef _LITTLE_ENDIAN
-		*ptr = (int32_t)ntohl(*(uint32_t *)ptr);
-#endif
-		da->dirp = (nfs_fh3 *)ptr;
-		da->name = NULL;
-		da->flags = 0;
-		if (!XDR_CONTROL(xdrs, XDR_PEEK, (void *)&size)) {
-			da->flags |= DA_FREENAME;
-			return (xdr_string3(xdrs, &da->name, MAXNAMELEN));
-		}
-		if (size >= MAXNAMELEN) {
-			da->name = nfs3nametoolong;
-			skipsize = RNDUP(size) + (1 * BYTES_PER_XDR_UNIT);
-			if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &skipsize))
-				return (FALSE);
-			return (TRUE);
-		}
-		nodesize = size + 1;
-		if (nodesize == 0)
-			return (TRUE);
-		ptr = XDR_INLINE(xdrs, 1 * BYTES_PER_XDR_UNIT + RNDUP(size));
-		if (ptr != NULL) {
-			if ((size % BYTES_PER_XDR_UNIT) != 0)
-				/* Plus 1 skips the size */
-				da->name = (char *)(ptr + 1);
-			else {
-				da->name = (char *)ptr;
-				bcopy((char *)(ptr + 1), da->name, size);
-			}
-			da->name[size] = '\0';
-			return (TRUE);
-		}
-		da->flags |= DA_FREENAME;
-		return (xdr_string3(xdrs, &da->name, MAXNAMELEN));
-	}
-	return (FALSE);
-}
-
 static bool_t
 xdr_fattr3(XDR *xdrs, fattr3 *na)
 {
@@ -918,7 +957,18 @@
 		return (FALSE);
 	switch (objp->handle_follows) {
 	case TRUE:
-		return (xdr_nfs_fh3(xdrs, &objp->handle));
+		switch (xdrs->x_op) {
+		case XDR_ENCODE:
+			if (!xdr_nfs_fh3_server(xdrs, &objp->handle))
+				return (FALSE);
+			break;
+		case XDR_FREE:
+		case XDR_DECODE:
+			if (!xdr_nfs_fh3(xdrs, &objp->handle))
+				return (FALSE);
+			break;
+		}
+		return (TRUE);
 	case FALSE:
 		return (TRUE);
 	default:
@@ -1014,8 +1064,17 @@
 bool_t
 xdr_SETATTR3args(XDR *xdrs, SETATTR3args *objp)
 {
-	if (!xdr_nfs_fh3(xdrs, &objp->object))
-		return (FALSE);
+	switch (xdrs->x_op) {
+	case XDR_FREE:
+	case XDR_ENCODE:
+		if (!xdr_nfs_fh3(xdrs, &objp->object))
+			return (FALSE);
+		break;
+	case XDR_DECODE:
+		if (!xdr_nfs_fh3_server(xdrs, &objp->object))
+			return (FALSE);
+		break;
+	}
 	if (!xdr_sattr3(xdrs, &objp->new_attributes))
 		return (FALSE);
 
@@ -1060,8 +1119,17 @@
 
 	/* xdr_LOOKUP3resok */
 	resokp = &objp->resok;
-	if (!xdr_nfs_fh3(xdrs, &resokp->object))
-		return (FALSE);
+	switch (xdrs->x_op) {
+	case XDR_ENCODE:
+		if (!xdr_nfs_fh3_server(xdrs, &resokp->object))
+			return (FALSE);
+		break;
+	case XDR_FREE:
+	case XDR_DECODE:
+		if (!xdr_nfs_fh3(xdrs, &resokp->object))
+			return (FALSE);
+		break;
+	}
 	if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
 		return (FALSE);
 	return (xdr_post_op_attr(xdrs, &resokp->dir_attributes));
@@ -1095,52 +1163,17 @@
 bool_t
 xdr_ACCESS3args(XDR *xdrs, ACCESS3args *objp)
 {
-	int32_t *ptr;
-	int32_t *fhp;
-	int len;
-	uint_t in_size;
-
-	if (xdrs->x_op == XDR_FREE)
-		return (TRUE);
-
-	in_size = RNDUP(sizeof (fhandle_t)) +	2 * BYTES_PER_XDR_UNIT;
-	ptr = XDR_INLINE(xdrs, in_size);
-
-	if (ptr != NULL) {
-		len =  (xdrs->x_op == XDR_DECODE) ?
-			*ptr : objp->object.fh3_length;
-
-		if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
-			fhp = (int32_t *)&(objp->object.fh3_u.data);
-			if (xdrs->x_op == XDR_DECODE) {
-				objp->object.fh3_length = IXDR_GET_U_INT32(ptr);
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp = *ptr++;
-				objp->access = IXDR_GET_U_INT32(ptr);
-			} else {
-				IXDR_PUT_U_INT32(ptr, objp->object.fh3_length);
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp;
-				IXDR_PUT_U_INT32(ptr, objp->access);
-			}
-			return (TRUE);
-		}
+	switch (xdrs->x_op) {
+	case XDR_FREE:
+	case XDR_ENCODE:
+		if (!xdr_nfs_fh3(xdrs, &objp->object))
+			return (FALSE);
+		break;
+	case XDR_DECODE:
+		if (!xdr_nfs_fh3_server(xdrs, &objp->object))
+			return (FALSE);
+		break;
 	}
-
-	if (!xdr_nfs_fh3(xdrs, &objp->object))
-		return (FALSE);
 	return (xdr_u_int(xdrs, &objp->access));
 }
 
@@ -1184,53 +1217,17 @@
 bool_t
 xdr_READ3args(XDR *xdrs, READ3args *objp)
 {
-	int32_t *ptr;
-	int32_t *fhp;
-	uint_t in_size;
-	int len;
-
-	if (xdrs->x_op == XDR_FREE)
-		return (TRUE);
-
-	in_size = RNDUP(sizeof (fhandle_t)) + 4 * BYTES_PER_XDR_UNIT;
-	ptr = XDR_INLINE(xdrs, in_size);
-	if (ptr != NULL) {
-		len = (xdrs->x_op == XDR_DECODE) ?
-			*ptr : objp->file.fh3_length;
-
-		if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
-			fhp = (int32_t *)& objp->file.fh3_u.data;
-			if (xdrs->x_op == XDR_DECODE) {
-				objp->file.fh3_length = IXDR_GET_U_INT32(ptr);
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp = *ptr++;
-				IXDR_GET_U_HYPER(ptr, objp->offset);
-				objp->count = IXDR_GET_U_INT32(ptr);
-			} else {
-				IXDR_PUT_U_INT32(ptr, objp->file.fh3_length);
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp;
-				IXDR_PUT_U_HYPER(ptr, objp->offset);
-				IXDR_PUT_U_INT32(ptr, objp->count);
-			}
-			return (TRUE);
-		}
+	switch (xdrs->x_op) {
+	case XDR_FREE:
+	case XDR_ENCODE:
+		if (!xdr_nfs_fh3(xdrs, &objp->file))
+			return (FALSE);
+		break;
+	case XDR_DECODE:
+		if (!xdr_nfs_fh3_server(xdrs, &objp->file))
+			return (FALSE);
+		break;
 	}
-
-	if (!xdr_nfs_fh3(xdrs, &objp->file))
-		return (FALSE);
 	if (!xdr_u_longlong_t(xdrs, &objp->offset))
 		return (FALSE);
 	return (xdr_u_int(xdrs, &objp->count));
@@ -1434,78 +1431,17 @@
 bool_t
 xdr_WRITE3args(XDR *xdrs, WRITE3args *objp)
 {
-	int32_t *ptr;
-	int32_t *fhp;
-	uint_t in_size;
-	int len;
-
-	in_size = RNDUP(sizeof (fhandle_t)) + 5 * BYTES_PER_XDR_UNIT;
-	ptr = XDR_INLINE(xdrs, in_size);
-
-	if (ptr != NULL) {
-		len = (xdrs->x_op == XDR_DECODE) ? *ptr : objp->file.fh3_length;
-
-		if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
-			fhp = (int32_t *)&(objp->file.fh3_u.data);
-			if (xdrs->x_op == XDR_DECODE) {
-				objp->file.fh3_length = IXDR_GET_U_INT32(ptr);
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp = *ptr++;
-				IXDR_GET_U_HYPER(ptr, objp->offset);
-				objp->count = IXDR_GET_U_INT32(ptr);
-				objp->stable = IXDR_GET_ENUM(ptr,
-						enum stable_how);
-				if (xdrs->x_ops == &xdrmblk_ops)
-					return (xdrmblk_getmblk(xdrs,
-					&objp->mblk,
-					(uint_t *)&objp->data.data_len));
-				/*
-				 * It is just as efficient to xdr_bytes
-				 * an array of unknown length as to inline
-				 * copy it.
-				 */
-				return (xdr_bytes(xdrs, &objp->data.data_val,
-						(uint_t *)&objp->data.data_len,
-						nfs3tsize()));
-			}
-
-			if (xdrs->x_op == XDR_ENCODE) {
-				IXDR_PUT_U_INT32(ptr, objp->file.fh3_length);
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp;
-				IXDR_PUT_U_HYPER(ptr, objp->offset);
-				IXDR_PUT_U_INT32(ptr, objp->count);
-				IXDR_PUT_ENUM(ptr, objp->stable);
-				return (xdr_bytes(xdrs,
-					(char **)&objp->data.data_val,
-					(uint_t *)&objp->data.data_len,
-					nfs3tsize()));
-			}
-
-			ASSERT(xdrs->x_op == XDR_FREE);
-			if (objp->data.data_val != NULL) {
-				kmem_free(objp->data.data_val,
-					(uint_t)objp->data.data_len);
-				objp->data.data_val = NULL;
-			}
-			return (TRUE);
-		}
+	switch (xdrs->x_op) {
+	case XDR_FREE:
+	case XDR_ENCODE:
+		if (!xdr_nfs_fh3(xdrs, &objp->file))
+			return (FALSE);
+		break;
+	case XDR_DECODE:
+		if (!xdr_nfs_fh3_server(xdrs, &objp->file))
+			return (FALSE);
+		break;
 	}
-
-	if (!xdr_nfs_fh3(xdrs, &objp->file))
-		return (FALSE);
 	if (!xdr_u_longlong_t(xdrs, &objp->offset))
 		return (FALSE);
 	if (!xdr_u_int(xdrs, &objp->count))
@@ -1784,8 +1720,17 @@
 bool_t
 xdr_LINK3args(XDR *xdrs, LINK3args *objp)
 {
-	if (!xdr_nfs_fh3(xdrs, &objp->file))
-		return (FALSE);
+	switch (xdrs->x_op) {
+	case XDR_FREE:
+	case XDR_ENCODE:
+		if (!xdr_nfs_fh3(xdrs, &objp->file))
+			return (FALSE);
+		break;
+	case XDR_DECODE:
+		if (!xdr_nfs_fh3_server(xdrs, &objp->file))
+			return (FALSE);
+		break;
+	}
 	return (xdr_diropargs3(xdrs, &objp->link));
 }
 
@@ -1816,70 +1761,20 @@
 bool_t
 xdr_READDIR3args(XDR *xdrs, READDIR3args *objp)
 {
-	int32_t *ptr;
-	int32_t *fhp;
-	uint_t in_size;
-	int len;
-
 	if (xdrs->x_op == XDR_FREE)
 		return (TRUE);
 
-	in_size = RNDUP(sizeof (fhandle_t)) + NFS3_COOKIEVERFSIZE +
-		4 * BYTES_PER_XDR_UNIT;
-	ptr = XDR_INLINE(xdrs, in_size);
-
-	if (ptr != NULL) {
-		len = (xdrs->x_op == XDR_DECODE) ? *ptr : objp->dir.fh3_length;
-
-		if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
-
-			fhp = (int32_t *)&(objp->dir.fh3_u.data);
-
-			if (xdrs->x_op == XDR_DECODE) {
-				objp->dir.fh3_length = IXDR_GET_U_INT32(ptr);
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp = *ptr++;
-				IXDR_GET_U_HYPER(ptr, objp->cookie);
-				/*
-				 * cookieverf is really an opaque 8 byte
-				 * quantity, but we will treat it as a
-				 * hyper for efficiency, the cost of
-				 * a byteswap here saves bcopys elsewhere
-				 */
-				IXDR_GET_U_HYPER(ptr, objp->cookieverf);
-				objp->count = IXDR_GET_U_INT32(ptr);
-			} else {
-				IXDR_PUT_U_INT32(ptr, objp->dir.fh3_length);
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp;
-				IXDR_PUT_U_HYPER(ptr, objp->cookie);
-				/*
-				 * cookieverf is really an opaque 8 byte
-				 * quantity, but we will treat it as a
-				 * hyper for efficiency, the cost of
-				 * a byteswap here saves bcopys elsewhere
-				 */
-				IXDR_PUT_U_HYPER(ptr, objp->cookieverf);
-				IXDR_PUT_U_INT32(ptr, objp->count);
-			}
-			return (TRUE);
-		}
+	switch (xdrs->x_op) {
+	case XDR_FREE:
+	case XDR_ENCODE:
+		if (!xdr_nfs_fh3(xdrs, &objp->dir))
+			return (FALSE);
+		break;
+	case XDR_DECODE:
+		if (!xdr_nfs_fh3_server(xdrs, &objp->dir))
+			return (FALSE);
+		break;
 	}
-
-	if (!xdr_nfs_fh3(xdrs, &objp->dir))
-		return (FALSE);
 	if (!xdr_u_longlong_t(xdrs, &objp->cookie))
 		return (FALSE);
 	/*
@@ -2125,72 +2020,20 @@
 bool_t
 xdr_READDIRPLUS3args(XDR *xdrs, READDIRPLUS3args *objp)
 {
-	int32_t *ptr;
-	int32_t *fhp;
-	uint_t in_size;
-	int len;
-
 	if (xdrs->x_op == XDR_FREE)
 		return (TRUE);
 
-	in_size = RNDUP(sizeof (fhandle_t)) + NFS3_COOKIEVERFSIZE +
-		5 * BYTES_PER_XDR_UNIT;
-
-	ptr = XDR_INLINE(xdrs, in_size);
-	if (ptr != NULL) {
-		len = (xdrs->x_op == XDR_DECODE) ? *ptr : objp->dir.fh3_length;
-
-		if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
-
-			fhp = (int32_t *)&(objp->dir.fh3_u.data);
-
-			if (xdrs->x_op == XDR_DECODE) {
-				objp->dir.fh3_length = IXDR_GET_U_INT32(ptr);
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp = *ptr++;
-				IXDR_GET_U_HYPER(ptr, objp->cookie);
-				/*
-				 * cookieverf is really an opaque 8 byte
-				 * quantity, but we will treat it as a
-				 * hyper for efficiency, the cost of
-				 * a byteswap here saves bcopys elsewhere
-				 */
-				IXDR_GET_U_HYPER(ptr, objp->cookieverf);
-				objp->dircount = IXDR_GET_U_INT32(ptr);
-				objp->maxcount = IXDR_GET_U_INT32(ptr);
-			} else {
-				IXDR_PUT_U_INT32(ptr, objp->dir.fh3_length);
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp;
-				IXDR_PUT_U_HYPER(ptr, objp->cookie);
-				/*
-				 * cookieverf is really an opaque 8 byte
-				 * quantity, but we will treat it as a
-				 * hyper for efficiency, the cost of
-				 * a byteswap here saves bcopys elsewhere
-				 */
-				IXDR_PUT_U_HYPER(ptr, objp->cookieverf);
-				IXDR_PUT_U_INT32(ptr, objp->dircount);
-				IXDR_PUT_U_INT32(ptr, objp->maxcount);
-			}
-			return (TRUE);
-		}
+	switch (xdrs->x_op) {
+	case XDR_FREE:
+	case XDR_ENCODE:
+		if (!xdr_nfs_fh3(xdrs, &objp->dir))
+			return (FALSE);
+		break;
+	case XDR_DECODE:
+		if (!xdr_nfs_fh3_server(xdrs, &objp->dir))
+			return (FALSE);
+		break;
 	}
-
-	if (!xdr_nfs_fh3(xdrs, &objp->dir))
-		return (FALSE);
 	if (!xdr_u_longlong_t(xdrs, &objp->cookie))
 		return (FALSE);
 	/*
@@ -2204,7 +2047,6 @@
 	if (!xdr_u_int(xdrs, &objp->dircount))
 		return (FALSE);
 	return (xdr_u_int(xdrs, &objp->maxcount));
-
 }
 
 /*
@@ -2557,53 +2399,20 @@
 bool_t
 xdr_COMMIT3args(XDR *xdrs, COMMIT3args *objp)
 {
-	int32_t *ptr;
-	int32_t *fhp;
-	int len;
-	uint_t in_size;
-
 	if (xdrs->x_op == XDR_FREE)
 		return (TRUE);
 
-	in_size = RNDUP(sizeof (fhandle_t)) +	4 * BYTES_PER_XDR_UNIT;
-	ptr = XDR_INLINE(xdrs, in_size);
-
-	if (ptr != NULL) {
-		len = (xdrs->x_op == XDR_DECODE) ? *ptr : objp->file.fh3_length;
-
-		if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
-			fhp = (int32_t *)&(objp->file.fh3_u.data);
-			if (xdrs->x_op == XDR_DECODE) {
-				objp->file.fh3_length = IXDR_GET_U_INT32(ptr);
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp++ = *ptr++;
-				*fhp = *ptr++;
-				IXDR_GET_U_HYPER(ptr, objp->offset);
-				objp->count = IXDR_GET_U_INT32(ptr);
-			} else {
-				IXDR_PUT_U_INT32(ptr, objp->file.fh3_length);
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp++;
-				*ptr++ = *fhp;
-				IXDR_PUT_U_HYPER(ptr, objp->offset);
-				IXDR_PUT_U_INT32(ptr, objp->count);
-			}
-			return (TRUE);
-		}
+	switch (xdrs->x_op) {
+	case XDR_FREE:
+	case XDR_ENCODE:
+		if (!xdr_nfs_fh3(xdrs, &objp->file))
+			return (FALSE);
+		break;
+	case XDR_DECODE:
+		if (!xdr_nfs_fh3_server(xdrs, &objp->file))
+			return (FALSE);
+		break;
 	}
-
-	if (!xdr_nfs_fh3(xdrs, &objp->file))
-		return (FALSE);
 	if (!xdr_u_longlong_t(xdrs, &objp->offset))
 		return (FALSE);
 	return (xdr_u_int(xdrs, &objp->count));
--- a/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,7 +18,7 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -58,13 +57,13 @@
 	 * XXX nfs4_fid() does nothing and returns EREMOTE.
 	 * XXX nfs3_fid()/nfs_fid() returns nfs filehandle as its fid
 	 * which has a bigger length than local fid.
-	 * NFS_FHMAXDATA_EXT is the size of
-	 * fhandle_ext_t.fh_xdata[NFS_FHMAXDATA_EXT].
+	 * NFS_FH4MAXDATA is the size of
+	 * fhandle4_t.fh_xdata[NFS_FH4MAXDATA].
 	 *
 	 * Note: nfs[2,3,4]_fid() only gets called for diskless clients.
 	 */
 	if (error == EREMOTE ||
-	    (error == 0 && fidp->fid_len > NFS_FHMAXDATA_EXT)) {
+	    (error == 0 && fidp->fid_len > NFS_FH4MAXDATA)) {
 
 		va.va_mask = AT_NODEID;
 		error = VOP_GETATTR(vp, &va, 0, CRED());
--- a/usr/src/uts/common/fs/nfs/nfs4_xdr.c	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs4_xdr.c	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -261,7 +260,7 @@
 	uint32_t fhsize;		/* filehandle size */
 	uint32_t bufsize;
 	rpc_inline_t *ptr;
-	uchar_t *buf, *bp;
+	uchar_t *bp;
 
 	ASSERT(xdrs->x_op == XDR_DECODE);
 
@@ -295,9 +294,11 @@
 	ptr = XDR_INLINE(xdrs, bufsize);
 	bp = (uchar_t *)ptr;
 	if (ptr == NULL) {
-		bp = buf = kmem_alloc(bufsize, KM_SLEEP);
-		if (!xdr_opaque(xdrs, (char *)bp, bufsize))
+		bp = kmem_alloc(bufsize, KM_SLEEP);
+		if (!xdr_opaque(xdrs, (char *)bp, bufsize)) {
+			kmem_free(bp, bufsize);
 			return (FALSE);
+		}
 	}
 
 	objp->nfs_fh4_val = kmem_zalloc(sizeof (nfs_fh4_fmt_t), KM_SLEEP);
@@ -317,7 +318,7 @@
 	}
 
 	if (ptr == NULL)
-		kmem_free(buf, bufsize);
+		kmem_free(bp, bufsize);
 	return (TRUE);
 }
 
@@ -363,13 +364,13 @@
 	if ((ptr + (otw_len / BYTES_PER_XDR_UNIT) + 1) > ptr_redzone)
 		return (FALSE);
 
-	IXDR_PUT_U_INT32(ptr, otw_len);
-
 	/*
-	 * Zero out the pading.
+	 * Zero out the padding.
 	 */
 	ptr[padword] = 0;
 
+	IXDR_PUT_U_INT32(ptr, otw_len);
+
 	/*
 	 * The rest of the filehandle is in native byteorder
 	 */
--- a/usr/src/uts/common/fs/nfs/nfs_acl_srv.c	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs_acl_srv.c	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.
+ * Copyright 2006 Sun Microsystems, Inc.
  * All rights reserved.
  * Use is subject to license terms.
  */
@@ -165,7 +164,7 @@
 	}
 }
 
-fhandle_t *
+void *
 acl2_getacl_getfh(GETACL2args *args)
 {
 
@@ -238,7 +237,7 @@
 	resp->status = NFS_OK;
 }
 
-fhandle_t *
+void *
 acl2_setacl_getfh(SETACL2args *args)
 {
 
@@ -277,7 +276,7 @@
 	resp->status = NFS_OK;
 }
 
-fhandle_t *
+void *
 acl2_getattr_getfh(GETATTR2args *args)
 {
 
@@ -373,7 +372,7 @@
 	resp->status = NFS_OK;
 }
 
-fhandle_t *
+void *
 acl2_access_getfh(ACCESS2args *args)
 {
 
@@ -434,7 +433,7 @@
 	resp->status = NFS_OK;
 }
 
-fhandle_t *
+void *
 acl2_getxattrdir_getfh(GETXATTRDIR2args *args)
 {
 	return (&args->fh);
@@ -542,11 +541,11 @@
 	vattr_to_post_op_attr(vap, &resp->resfail.attr);
 }
 
-fhandle_t *
+void *
 acl3_getacl_getfh(GETACL3args *args)
 {
 
-	return ((fhandle_t *)&args->fh.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->fh);
 }
 
 void
@@ -640,11 +639,11 @@
 	vattr_to_post_op_attr(vap, &resp->resfail.attr);
 }
 
-fhandle_t *
+void *
 acl3_setacl_getfh(SETACL3args *args)
 {
 
-	return ((fhandle_t *)&args->fh.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->fh);
 }
 
 /* ARGSUSED */
@@ -700,8 +699,8 @@
 	resp->status = NFS3_OK;
 }
 
-fhandle_t *
+void *
 acl3_getxattrdir_getfh(GETXATTRDIR3args *args)
 {
-	return ((fhandle_t *)&args->fh.fh3_u.nfs_fh3_i.fh3_i);
+	return (&args->fh);
 }
--- a/usr/src/uts/common/fs/nfs/nfs_acl_xdr.c	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs_acl_xdr.c	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -437,8 +436,17 @@
 xdr_GETACL3args(XDR *xdrs, GETACL3args *objp)
 {
 
-	if (!xdr_nfs_fh3(xdrs, &objp->fh))
-		return (FALSE);
+	switch (xdrs->x_op) {
+	case XDR_FREE:
+	case XDR_ENCODE:
+		if (!xdr_nfs_fh3(xdrs, &objp->fh))
+			return (FALSE);
+		break;
+	case XDR_DECODE:
+		if (!xdr_nfs_fh3_server(xdrs, &objp->fh))
+			return (FALSE);
+		break;
+	}
 	if (!xdr_u_int(xdrs, &objp->mask))
 		return (FALSE);
 	return (TRUE);
@@ -487,8 +495,17 @@
 xdr_SETACL3args(XDR *xdrs, SETACL3args *objp)
 {
 
-	if (!xdr_nfs_fh3(xdrs, &objp->fh))
-		return (FALSE);
+	switch (xdrs->x_op) {
+	case XDR_FREE:
+	case XDR_ENCODE:
+		if (!xdr_nfs_fh3(xdrs, &objp->fh))
+			return (FALSE);
+		break;
+	case XDR_DECODE:
+		if (!xdr_nfs_fh3_server(xdrs, &objp->fh))
+			return (FALSE);
+		break;
+	}
 	if (!xdr_secattr(xdrs, &objp->acl))
 		return (FALSE);
 	return (TRUE);
@@ -534,8 +551,17 @@
 bool_t
 xdr_GETXATTRDIR3args(XDR *xdrs, GETXATTRDIR3args *objp)
 {
-	if (!xdr_nfs_fh3(xdrs, &objp->fh))
-		return (FALSE);
+	switch (xdrs->x_op) {
+	case XDR_FREE:
+	case XDR_ENCODE:
+		if (!xdr_nfs_fh3(xdrs, &objp->fh))
+			return (FALSE);
+		break;
+	case XDR_DECODE:
+		if (!xdr_nfs_fh3_server(xdrs, &objp->fh))
+			return (FALSE);
+		break;
+	}
 	if (!xdr_bool(xdrs, &objp->create))
 		return (FALSE);
 	return (TRUE);
@@ -544,8 +570,17 @@
 bool_t
 xdr_GETXATTRDIR3resok(XDR *xdrs, GETXATTRDIR3resok *objp)
 {
-	if (!xdr_nfs_fh3(xdrs, &objp->fh))
-		return (FALSE);
+	switch (xdrs->x_op) {
+	case XDR_ENCODE:
+		if (!xdr_nfs_fh3_server(xdrs, &objp->fh))
+			return (FALSE);
+		break;
+	case XDR_FREE:
+	case XDR_DECODE:
+		if (!xdr_nfs_fh3(xdrs, &objp->fh))
+			return (FALSE);
+		break;
+	}
 	if (!xdr_post_op_attr(xdrs, &objp->attr))
 		return (FALSE);
 	return (TRUE);
--- a/usr/src/uts/common/fs/nfs/nfs_export.c	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs_export.c	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1527,11 +1526,15 @@
 int
 nfs_getfh(struct nfs_getfh_args *args, model_t model, cred_t *cr)
 {
-	fhandle_t fh;
+	nfs_fh3 fh;
+	char buf[NFS3_MAXFHSIZE];
+	char *logptr, logbuf[NFS3_MAXFHSIZE];
+	int l = NFS3_MAXFHSIZE;
 	vnode_t *vp;
 	vnode_t *dvp;
 	struct exportinfo *exi;
 	int error;
+	int vers;
 	STRUCT_HANDLE(nfs_getfh_args, uap);
 
 #ifdef lint
@@ -1588,16 +1591,69 @@
 		}
 	}
 
+	vers = STRUCT_FGET(uap, vers);
 	exi = nfs_vptoexi(dvp, vp, cr, NULL, &error, FALSE);
 	if (!error) {
-		error = makefh(&fh, vp, exi);
+		if (vers == NFS_VERSION) {
+			error = makefh((fhandle_t *)buf, vp, exi);
+			l = NFS_FHSIZE;
+			logptr = buf;
+		} else if (vers == NFS_V3) {
+			int i, sz;
+
+			error = makefh3(&fh, vp, exi);
+			l = fh.fh3_length;
+			logptr = logbuf;
+			if (!error) {
+				i = 0;
+				sz = sizeof (fsid_t);
+				bcopy(&fh.fh3_fsid, &buf[i], sz);
+				i += sz;
+				sz = sizeof (ushort_t);
+				bcopy(&fh.fh3_len, &buf[i], sz);
+				i += sz;
+				sz = fh.fh3_len;
+				bcopy(fh.fh3_data, &buf[i], sz);
+				i += sz;
+				sz = sizeof (ushort_t);
+				bcopy(&fh.fh3_xlen, &buf[i], sz);
+				i += sz;
+				sz = fh.fh3_xlen;
+				bcopy(fh.fh3_xdata, &buf[i], sz);
+				i += sz;
+			}
+			/*
+			 * If we need to do NFS logging, the filehandle
+			 * must be downsized to 32 bytes.
+			 */
+			if (!error && exi->exi_export.ex_flags & EX_LOG) {
+				i = 0;
+				sz = sizeof (fsid_t);
+				bcopy(&fh.fh3_fsid, &logbuf[i], sz);
+				i += sz;
+				sz = sizeof (ushort_t);
+				bcopy(&fh.fh3_len, &logbuf[i], sz);
+				i += sz;
+				sz = NFS_FHMAXDATA;
+				bcopy(fh.fh3_data, &logbuf[i], sz);
+				i += sz;
+				sz = sizeof (ushort_t);
+				bcopy(&fh.fh3_xlen, &logbuf[i], sz);
+				i += sz;
+				sz = NFS_FHMAXDATA;
+				bcopy(fh.fh3_xdata, &logbuf[i], sz);
+				i += sz;
+			}
+		}
 		if (!error && exi->exi_export.ex_flags & EX_LOG) {
-			nfslog_getfh(exi, &fh, STRUCT_FGETP(uap, fname),
-				UIO_USERSPACE, cr);
+			nfslog_getfh(exi, (fhandle_t *)logptr,
+			    STRUCT_FGETP(uap, fname), UIO_USERSPACE, cr);
 		}
 		exi_rele(exi);
 		if (!error) {
-			if (copyout(&fh, STRUCT_FGETP(uap, fhp), sizeof (fh)))
+			if (copyout(&l, STRUCT_FGETP(uap, lenp), sizeof (int)))
+				error = EFAULT;
+			if (copyout(buf, STRUCT_FGETP(uap, fhp), l))
 				error = EFAULT;
 		}
 	}
@@ -1807,18 +1863,23 @@
 makefh3(nfs_fh3 *fh, vnode_t *vp, struct exportinfo *exi)
 {
 	int error;
+	fid_t fid;
 
-	fh->fh3_length = sizeof (fh->fh3_u.nfs_fh3_i);
-	fh->fh3_u.nfs_fh3_i.fh3_i = exi->exi_fh;	/* struct copy */
-
-	error = VOP_FID(vp, (fid_t *)&fh->fh3_len);
+	bzero(&fid, sizeof (fid));
+	fid.fid_len = MAXFIDSZ;
+	error = VOP_FID(vp, &fid);
+	if (error)
+		return (EREMOTE);
 
-	if (error) {
-		/*
-		 * Should be something other than EREMOTE
-		 */
-		return (EREMOTE);
-	}
+	bzero(fh, sizeof (nfs_fh3));
+	fh->fh3_fsid = exi->exi_fsid;
+	fh->fh3_len = fid.fid_len;
+	bcopy(fid.fid_data, fh->fh3_data, fh->fh3_len);
+	fh->fh3_xlen = exi->exi_fid.fid_len;
+	bcopy(exi->exi_fid.fid_data, fh->fh3_xdata, fh->fh3_xlen);
+	fh->fh3_length = sizeof (fsid_t)
+			+ sizeof (ushort_t) + fh->fh3_len
+			+ sizeof (ushort_t) + fh->fh3_xlen;
 	return (0);
 }
 
@@ -2052,12 +2113,13 @@
 		return (vp);
 	}
 
-	if (fh->fh3_length != NFS3_CURFHSIZE)
+	if (fh->fh3_length < NFS3_OLDFHSIZE ||
+	    fh->fh3_length > NFS3_MAXFHSIZE)
 		return (NULL);
 
 	vfsp = exi->exi_vp->v_vfsp;
 	ASSERT(vfsp != NULL);
-	fidp = (fid_t *)&fh->fh3_len;
+	fidp = FH3TOFIDP(fh);
 
 	error = VFS_VGET(vfsp, &vp, fidp);
 	if (error || vp == NULL)
@@ -2081,15 +2143,18 @@
 	vfs_t *vfsp;
 	vnode_t *vp;
 	int error;
+	fid_t *fidp;
 
-	if (fh->fh3_length != NFS3_CURFHSIZE)
+	if (fh->fh3_length < NFS3_OLDFHSIZE ||
+	    fh->fh3_length > NFS3_MAXFHSIZE)
 		return (NULL);
 
 	vfsp = getvfs(&fh->fh3_fsid);
 	if (vfsp == NULL)
 		return (NULL);
+	fidp = FH3TOFIDP(fh);
 
-	error = VFS_VGET(vfsp, &vp, (fid_t *)&(fh->fh3_len));
+	error = VFS_VGET(vfsp, &vp, fidp);
 	VFS_RELE(vfsp);
 	if (error || vp == NULL)
 		return (NULL);
@@ -2357,7 +2422,7 @@
 find_volrnm_fh(struct exportinfo *exi, nfs_fh4 *fh4p)
 {
 	struct ex_vol_rename *p = NULL;
-	fhandle_ext_t *fhp;
+	fhandle4_t *fhp;
 
 	/* XXX shouldn't we assert &exported_lock held? */
 	ASSERT(MUTEX_HELD(&exi->exi_vol_rename_lock));
@@ -2368,7 +2433,7 @@
 	fhp = &((nfs_fh4_fmt_t *)fh4p->nfs_fh4_val)->fh4_i;
 	for (p = exi->exi_vol_rename; p != NULL; p = p->vrn_next) {
 		if (bcmp(fhp, &p->vrn_fh_fmt.fh4_i,
-		    sizeof (fhandle_ext_t)) == 0)
+		    sizeof (fhandle4_t)) == 0)
 			break;
 	}
 	return (p);
--- a/usr/src/uts/common/fs/nfs/nfs_log.c	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs_log.c	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1403,7 +1402,7 @@
 	{xdr_void, xdr_void, FALSE},
 
 	/* NFSPROC3_GETATTR = 1 */
-	{xdr_nfs_fh3, xdr_nfslog_GETATTR3res, FALSE},
+	{xdr_nfslog_nfs_fh3, xdr_nfslog_GETATTR3res, FALSE},
 
 	/* NFSPROC3_SETATTR = 2 */
 	{xdr_nfslog_SETATTR3args, xdr_nfslog_SETATTR3res, TRUE},
@@ -1415,7 +1414,7 @@
 	{xdr_nfslog_ACCESS3args, xdr_nfslog_ACCESS3res, FALSE},
 
 	/* NFSPROC3_READLINK = 5 */
-	{xdr_nfs_fh3, xdr_nfslog_READLINK3res, FALSE},
+	{xdr_nfslog_nfs_fh3, xdr_nfslog_READLINK3res, FALSE},
 
 	/* NFSPROC3_READ = 6 */
 	{xdr_nfslog_READ3args, xdr_nfslog_READ3res, TRUE},
@@ -1530,7 +1529,7 @@
 {
 	struct log_buffer *lb;
 	struct exportinfo *exi_ret = NULL;
-	fhandle_t		*fh = NULL;
+	fhandle_t		*fh;
 	nfs_fh3			*fh3;
 
 	if (exi == NULL)
@@ -1576,8 +1575,8 @@
 			if ((req->rq_proc == NFSPROC3_LOOKUP) &&
 				(((LOOKUP3res *)res)->status == NFS3_OK)) {
 				fh3 = &((LOOKUP3res *)res)->res_u.ok.object;
-				if (fh3->fh3_length == sizeof (fhandle_t))
-					fh = &fh3->fh3_u.nfs_fh3_i.fh3_i;
+				exi_ret = checkexport(&fh3->fh3_fsid,
+					FH3TOXFIDP(fh3));
 			}
 			break;
 
@@ -1587,15 +1586,13 @@
 					res)->dr_status == NFS_OK)) {
 				fh =
 		&((struct nfsdiropres *)res)->dr_u.dr_drok_u.drok_fhandle;
+				exi_ret = checkexport(&fh->fh_fsid,
+					(fid_t *)&fh->fh_xlen);
 			}
 			break;
 		default:
 			break;
 		}
-		if (fh != NULL) {
-			exi_ret = checkexport(&fh->fh_fsid,
-				(fid_t *)&fh->fh_xlen);
-		}
 	}
 
 	if (exi_ret != NULL && exi_ret->exi_export.ex_flags & EX_LOG) {
--- a/usr/src/uts/common/fs/nfs/nfs_log_xdr.c	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs_log_xdr.c	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 1999-2003 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -448,7 +447,7 @@
 {
 	char *name;
 
-	if (!xdr_nfs_fh3(xdrs, objp->dirp))
+	if (!xdr_nfslog_nfs_fh3(xdrs, &objp->dir))
 		return (FALSE);
 	if (objp->name != nfs3nametoolong)
 		name = objp->name;
@@ -469,7 +468,7 @@
 		return (FALSE);
 	switch (objp->status) {
 	case NFS3_OK:
-		if (!xdr_nfs_fh3(xdrs, &objp->res_u.ok.object))
+		if (!xdr_nfslog_nfs_fh3(xdrs, &objp->res_u.ok.object))
 			return (FALSE);
 		break;
 	}
@@ -547,7 +546,7 @@
 bool_t
 xdr_nfslog_ACCESS3args(XDR *xdrs, ACCESS3args *objp)
 {
-	return (xdr_nfs_fh3(xdrs, &objp->object));
+	return (xdr_nfslog_nfs_fh3(xdrs, &objp->object));
 }
 
 bool_t
@@ -559,7 +558,7 @@
 bool_t
 xdr_nfslog_SETATTR3args(XDR *xdrs, SETATTR3args *objp)
 {
-	if (!xdr_nfs_fh3(xdrs, &objp->object))
+	if (!xdr_nfslog_nfs_fh3(xdrs, &objp->object))
 		return (FALSE);
 	return (xdr_set_size3(xdrs, &objp->new_attributes.size));
 }
@@ -587,7 +586,7 @@
 bool_t
 xdr_nfslog_READ3args(XDR *xdrs, READ3args *objp)
 {
-	if (!xdr_nfs_fh3(xdrs, &objp->file))
+	if (!xdr_nfslog_nfs_fh3(xdrs, &objp->file))
 		return (FALSE);
 	if (!xdr_uint64(xdrs, &objp->offset))
 		return (FALSE);
@@ -623,7 +622,7 @@
 bool_t
 xdr_nfslog_WRITE3args(XDR *xdrs, WRITE3args *objp)
 {
-	if (!xdr_nfs_fh3(xdrs, &objp->file))
+	if (!xdr_nfslog_nfs_fh3(xdrs, &objp->file))
 		return (FALSE);
 	if (!xdr_uint64(xdrs, &objp->offset))
 		return (FALSE);
@@ -761,7 +760,7 @@
 bool_t
 xdr_nfslog_LINK3args(XDR *xdrs, LINK3args *objp)
 {
-	if (!xdr_nfs_fh3(xdrs, &objp->file))
+	if (!xdr_nfslog_nfs_fh3(xdrs, &objp->file))
 		return (FALSE);
 	return (xdr_nfslog_diropargs3(xdrs, &objp->link));
 }
@@ -775,7 +774,7 @@
 bool_t
 xdr_nfslog_READDIR3args(XDR *xdrs, READDIR3args *objp)
 {
-	return (xdr_nfs_fh3(xdrs, &objp->dir));
+	return (xdr_nfslog_nfs_fh3(xdrs, &objp->dir));
 }
 
 bool_t
@@ -787,7 +786,7 @@
 bool_t
 xdr_nfslog_READDIRPLUS3args(XDR *xdrs, READDIRPLUS3args *objp)
 {
-	if (!xdr_nfs_fh3(xdrs, &objp->dir))
+	if (!xdr_nfslog_nfs_fh3(xdrs, &objp->dir))
 		return (FALSE);
 	if (!xdr_uint32(xdrs, &objp->dircount))
 		return (FALSE);
@@ -855,7 +854,7 @@
 bool_t
 xdr_nfslog_FSSTAT3args(XDR *xdrs, FSSTAT3args *objp)
 {
-	return (xdr_nfs_fh3(xdrs, &objp->fsroot));
+	return (xdr_nfslog_nfs_fh3(xdrs, &objp->fsroot));
 }
 
 bool_t
@@ -867,7 +866,7 @@
 bool_t
 xdr_nfslog_FSINFO3args(XDR *xdrs, FSINFO3args *objp)
 {
-	return (xdr_nfs_fh3(xdrs, &objp->fsroot));
+	return (xdr_nfslog_nfs_fh3(xdrs, &objp->fsroot));
 }
 
 bool_t
@@ -879,7 +878,7 @@
 bool_t
 xdr_nfslog_PATHCONF3args(XDR *xdrs, PATHCONF3args *objp)
 {
-	return (xdr_nfs_fh3(xdrs, &objp->object));
+	return (xdr_nfslog_nfs_fh3(xdrs, &objp->object));
 }
 
 bool_t
@@ -891,7 +890,7 @@
 bool_t
 xdr_nfslog_COMMIT3args(XDR *xdrs, COMMIT3args *objp)
 {
-	if (!xdr_nfs_fh3(xdrs, &objp->file))
+	if (!xdr_nfslog_nfs_fh3(xdrs, &objp->file))
 		return (FALSE);
 	if (!xdr_uint64(xdrs, &objp->offset))
 		return (FALSE);
@@ -903,3 +902,18 @@
 {
 	return (xdr_enum(xdrs, (enum_t *)&objp->status));
 }
+
+bool_t
+xdr_nfslog_nfs_fh3(XDR *xdrs, nfs_fh3 *objp)
+{
+	nfs_fh3 fh;
+
+	if (objp->fh3_len > NFS_FHMAXDATA || objp->fh3_xlen > NFS_FHMAXDATA) {
+		fh = *objp;
+		fh.fh3_len = NFS_FHMAXDATA;
+		fh.fh3_xlen = NFS_FHMAXDATA;
+		fh.fh3_length = NFS3_OLDFHSIZE;
+		return (xdr_nfs_fh3_server(xdrs, &fh));
+	}
+	return (xdr_nfs_fh3_server(xdrs, objp));
+}
--- a/usr/src/uts/common/fs/nfs/nfs_server.c	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs_server.c	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -153,11 +152,11 @@
  * supports RPC_PUBLICFH_OK, and if the filesystem is explicitly exported
  * public (i.e., not the placeholder).
  */
-#define	PUBLICFH_CHECK(disp, exi, fh) \
+#define	PUBLICFH_CHECK(disp, exi, fsid, xfid) \
 		((disp->dis_flags & RPC_PUBLICFH_OK) && \
 		((exi->exi_export.ex_flags & EX_PUBLIC) || \
 		(exi == exi_public && exportmatch(exi_root, \
-		&fh->fh_fsid, (fid_t *)&fh->fh_xlen))))
+		fsid, xfid))))
 
 static void	nfs_srv_shutdown_all(int);
 static void	rfs4_server_start(int);
@@ -813,7 +812,7 @@
 
 	/* RFS3_GETATTR = 1 */
 	{rfs3_getattr,
-	    xdr_nfs_fh3, xdr_fastnfs_fh3, sizeof (GETATTR3args),
+	    xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (GETATTR3args),
 	    xdr_GETATTR3res, NULL_xdrproc_t, sizeof (GETATTR3res),
 	    nullfree, (RPC_IDEMPOTENT | RPC_ALLOWANON),
 	    rfs3_getattr_getfh},
@@ -841,7 +840,7 @@
 
 	/* RFS3_READLINK = 5 */
 	{rfs3_readlink,
-	    xdr_nfs_fh3, xdr_fastnfs_fh3, sizeof (READLINK3args),
+	    xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (READLINK3args),
 	    xdr_READLINK3res, NULL_xdrproc_t, sizeof (READLINK3res),
 	    rfs3_readlink_free, RPC_IDEMPOTENT,
 	    rfs3_readlink_getfh},
@@ -932,21 +931,21 @@
 
 	/* RFS3_FSSTAT = 18 */
 	{rfs3_fsstat,
-	    xdr_nfs_fh3, xdr_fastnfs_fh3, sizeof (FSSTAT3args),
+	    xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (FSSTAT3args),
 	    xdr_FSSTAT3res, NULL_xdrproc_t, sizeof (FSSTAT3res),
 	    nullfree, RPC_IDEMPOTENT,
 	    rfs3_fsstat_getfh},
 
 	/* RFS3_FSINFO = 19 */
 	{rfs3_fsinfo,
-	    xdr_nfs_fh3, xdr_fastnfs_fh3, sizeof (FSINFO3args),
+	    xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (FSINFO3args),
 	    xdr_FSINFO3res, NULL_xdrproc_t, sizeof (FSINFO3res),
 	    nullfree, RPC_IDEMPOTENT|RPC_ALLOWANON,
 	    rfs3_fsinfo_getfh},
 
 	/* RFS3_PATHCONF = 20 */
 	{rfs3_pathconf,
-	    xdr_nfs_fh3, xdr_fastnfs_fh3, sizeof (PATHCONF3args),
+	    xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (PATHCONF3args),
 	    xdr_PATHCONF3res, NULL_xdrproc_t, sizeof (PATHCONF3res),
 	    nullfree, RPC_IDEMPOTENT,
 	    rfs3_pathconf_getfh},
@@ -1461,12 +1460,13 @@
 #ifdef DEBUG
 	if (rfs_no_fast_xdrargs || (auth_flavor == RPCSEC_GSS) ||
 	    disp->dis_fastxdrargs == NULL_xdrproc_t ||
-	    !SVC_GETARGS(xprt, disp->dis_fastxdrargs, (char *)&args)) {
+	    !SVC_GETARGS(xprt, disp->dis_fastxdrargs, (char *)&args))
 #else
 	if ((auth_flavor == RPCSEC_GSS) ||
 	    disp->dis_fastxdrargs == NULL_xdrproc_t ||
-	    !SVC_GETARGS(xprt, disp->dis_fastxdrargs, (char *)&args)) {
+	    !SVC_GETARGS(xprt, disp->dis_fastxdrargs, (char *)&args))
 #endif
+	{
 		bzero(args, disp->dis_argsz);
 		if (!SVC_GETARGS(xprt, disp->dis_xdrargs, args)) {
 			svcerr_decode(xprt);
@@ -1495,9 +1495,27 @@
 	 * setting the credential if everything is ok.
 	 */
 	if (disp->dis_getfh != NULL) {
-		fhandle_t *fh;
+		void *fh;
+		fsid_t *fsid;
+		fid_t *fid, *xfid;
+		fhandle_t *fh2;
+		nfs_fh3 *fh3;
 
 		fh = (*disp->dis_getfh)(args);
+		switch (req->rq_vers) {
+		case NFS_VERSION:
+			fh2 = (fhandle_t *)fh;
+			fsid = &fh2->fh_fsid;
+			fid = (fid_t *)&fh2->fh_len;
+			xfid = (fid_t *)&fh2->fh_xlen;
+			break;
+		case NFS_V3:
+			fh3 = (nfs_fh3 *)fh;
+			fsid = &fh3->fh3_fsid;
+			fid = FH3TOFIDP(fh3);
+			xfid = FH3TOXFIDP(fh3);
+			break;
+		}
 
 		/*
 		 * Fix for bug 1038302 - corbin
@@ -1519,8 +1537,7 @@
 		 * Added anon_ok argument to checkauth().
 		 */
 
-		if ((dis_flags & RPC_ALLOWANON) &&
-		    EQFID((fid_t *)&fh->fh_len, (fid_t *)&fh->fh_xlen))
+		if ((dis_flags & RPC_ALLOWANON) && EQFID(fid, xfid))
 			anon_ok = 1;
 		else
 			anon_ok = 0;
@@ -1543,10 +1560,10 @@
 		}
 #endif
 
-		exi = checkexport(&fh->fh_fsid, (fid_t *)&fh->fh_xlen);
+		exi = checkexport(fsid, xfid);
 
 		if (exi != NULL) {
-			publicfh_ok = PUBLICFH_CHECK(disp, exi, fh);
+			publicfh_ok = PUBLICFH_CHECK(disp, exi, fsid, xfid);
 
 			/*
 			 * Don't allow non-V4 clients access
@@ -1686,10 +1703,11 @@
 	 * Serialize and send results struct
 	 */
 #ifdef DEBUG
-	if (rfs_no_fast_xdrres == 0 && res != (char *)&res_buf) {
+	if (rfs_no_fast_xdrres == 0 && res != (char *)&res_buf)
 #else
-	if (res != (char *)&res_buf) {
+	if (res != (char *)&res_buf)
 #endif
+	{
 		if (!svc_sendreply(xprt, disp->dis_fastxdrres, res)) {
 			cmn_err(CE_NOTE, "%s: bad sendreply", pgmname);
 			error++;
--- a/usr/src/uts/common/fs/nfs/nfs_srv.c	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs_srv.c	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -135,7 +134,7 @@
 	TRACE_1(TR_FAC_NFS, TR_RFS_GETATTR_END,
 		"rfs_getattr_end:(%S)", "done");
 }
-fhandle_t *
+void *
 rfs_getattr_getfh(fhandle_t *fhp)
 {
 	return (fhp);
@@ -344,7 +343,7 @@
 	TRACE_1(TR_FAC_NFS, TR_RFS_SETATTR_END,
 		"rfs_setattr_end:(%S)", "done");
 }
-fhandle_t *
+void *
 rfs_setattr_getfh(struct nfssaargs *args)
 {
 	return (&args->saa_fh);
@@ -486,7 +485,7 @@
 	TRACE_1(TR_FAC_NFS, TR_RFS_LOOKUP_END,
 		"rfs_lookup_end:(%S)", "done");
 }
-fhandle_t *
+void *
 rfs_lookup_getfh(struct nfsdiropargs *da)
 {
 	return (da->da_fhandle);
@@ -612,7 +611,7 @@
 	TRACE_1(TR_FAC_NFS, TR_RFS_READLINK_END,
 		"rfs_readlink_end:(%S)", "done");
 }
-fhandle_t *
+void *
 rfs_readlink_getfh(fhandle_t *fhp)
 {
 	return (fhp);
@@ -923,7 +922,7 @@
 	}
 }
 
-fhandle_t *
+void *
 rfs_read_getfh(struct nfsreadargs *ra)
 {
 	return (&ra->ra_fhandle);
@@ -1715,7 +1714,7 @@
 		"rfs_write_end:(%S)", "async");
 }
 
-fhandle_t *
+void *
 rfs_write_getfh(struct nfswriteargs *wa)
 {
 	return (&wa->wa_fhandle);
@@ -1989,7 +1988,7 @@
 	TRACE_1(TR_FAC_NFS, TR_RFS_CREATE_END,
 		"rfs_create_end:(%S)", "done");
 }
-fhandle_t *
+void *
 rfs_create_getfh(struct nfscreatargs *args)
 {
 	return (args->ca_da.da_fhandle);
@@ -2095,7 +2094,7 @@
 		"rfs_remove_end:(%S)", "done");
 }
 
-fhandle_t *
+void *
 rfs_remove_getfh(struct nfsdiropargs *da)
 {
 	return (da->da_fhandle);
@@ -2276,7 +2275,7 @@
 	TRACE_1(TR_FAC_NFS, TR_RFS_RENAME_END,
 		"rfs_rename_end:(%S)", "done");
 }
-fhandle_t *
+void *
 rfs_rename_getfh(struct nfsrnmargs *args)
 {
 	return (args->rna_from.da_fhandle);
@@ -2384,7 +2383,7 @@
 	TRACE_1(TR_FAC_NFS, TR_RFS_LINK_END,
 		"rfs_link_end:(%S)", "done");
 }
-fhandle_t *
+void *
 rfs_link_getfh(struct nfslinkargs *args)
 {
 	return (args->la_from);
@@ -2486,7 +2485,7 @@
 	TRACE_1(TR_FAC_NFS, TR_RFS_SYMLINK_END,
 		"rfs_symlink_end:(%S)", "done");
 }
-fhandle_t *
+void *
 rfs_symlink_getfh(struct nfsslargs *args)
 {
 	return (args->sla_from.da_fhandle);
@@ -2600,7 +2599,7 @@
 	TRACE_1(TR_FAC_NFS, TR_RFS_MKDIR_END,
 		"rfs_mkdir_end:(%S)", "done");
 }
-fhandle_t *
+void *
 rfs_mkdir_getfh(struct nfscreatargs *args)
 {
 	return (args->ca_da.da_fhandle);
@@ -2682,7 +2681,7 @@
 	TRACE_1(TR_FAC_NFS, TR_RFS_RMDIR_END,
 		"rfs_rmdir_end:(%S)", "done");
 }
-fhandle_t *
+void *
 rfs_rmdir_getfh(struct nfsdiropargs *da)
 {
 	return (da->da_fhandle);
@@ -2815,7 +2814,7 @@
 	TRACE_1(TR_FAC_NFS, TR_RFS_READDIR_END,
 		"rfs_readdir_end:(%S)", "done");
 }
-fhandle_t *
+void *
 rfs_readdir_getfh(struct nfsrddirargs *rda)
 {
 	return (&rda->rda_fh);
@@ -2864,7 +2863,7 @@
 	TRACE_1(TR_FAC_NFS, TR_RFS_STATFS_END,
 		"rfs_statfs_end:(%S)", "done");
 }
-fhandle_t *
+void *
 rfs_statfs_getfh(fhandle_t *fh)
 {
 	return (fh);
--- a/usr/src/uts/common/nfs/nfs.h	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/uts/common/nfs/nfs.h	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -392,50 +391,62 @@
 /*
  * "Legacy" filehandles use NFS_FHMAXDATA (10) byte fids. Filesystems that
  * return a larger fid than NFS_FHMAXDATA, such as ZFS's .zfs snapshot
- * directory, can use up to NFS_FHMAXDATA_EXT bytes for their fid.
+ * directory, can use up to (((64 - 8) / 2) - 2) bytes for their fid.
+ * This currently holds for both NFSv3 and NFSv4.
  */
 #define	NFS_FHMAXDATA		10
-#define	NFS_FHMAXDATA_EXT	26
+#define	NFS_FH3MAXDATA		26
+#define	NFS_FH4MAXDATA		26
 
 /*
- * The current nfs file handle size for version 3 is currently 32 which is
- * the same in version 2. It is the object returned from makefh
- * (fhandle_t) which is size of struct svcfh.
- * Thus, if the size of struct svcfh changes or if Version 3 uses some other
+ * The original nfs file handle size for version 3 was 32 which was
+ * the same in version 2; now we're making it bigger to to deal with
+ * ZFS snapshot FIDs.
+ *
+ * If the size of fhandle3_t changes or if Version 3 uses some other
  * filehandle format, this constant may need to change.
  */
 
-#define	NFS3_CURFHSIZE	32
+#define	NFS3_OLDFHSIZE	32
+#define	NFS3_MAXFHSIZE	64
 
 /*
  * This is the actual definition of a legacy filehandle.  There is some
  * dependence on this layout in NFS-related code, particularly in the
  * user-level lock manager, so be careful about changing it.
  *
- * Currently NFSv2 and NFSv3 only use this structure.
+ * Currently only NFSv2 uses this structure.
  */
 
-struct svcfh {
+typedef struct svcfh {
 	fsid_t	fh_fsid;			/* filesystem id */
 	ushort_t fh_len;			/* file number length */
 	char	fh_data[NFS_FHMAXDATA];		/* and data */
 	ushort_t fh_xlen;			/* export file number length */
 	char	fh_xdata[NFS_FHMAXDATA];	/* and data */
-};
-
-typedef struct svcfh fhandle_t;
+} fhandle_t;
 
 /*
- * This is the actual definition of a extended filehandle.  This is currently
- * only used for NFSv4.
+ * This is the in-memory structure for an NFSv3 extended filehandle.
  */
-typedef struct fhandle_ext {
+typedef struct {
+	fsid_t	_fh3_fsid;			/* filesystem id */
+	ushort_t _fh3_len;			/* file number length */
+	char	_fh3_data[NFS_FH3MAXDATA];		/* and data */
+	ushort_t _fh3_xlen;			/* export file number length */
+	char	_fh3_xdata[NFS_FH3MAXDATA];	/* and data */
+} fhandle3_t;
+
+/*
+ * This is the in-memory structure for an NFSv4 extended filehandle.
+ */
+typedef struct {
 	fsid_t	fhx_fsid;			/* filesystem id */
 	ushort_t fhx_len;			/* file number length */
-	char	fhx_data[NFS_FHMAXDATA_EXT];	/* and data */
+	char	fhx_data[NFS_FH4MAXDATA];	/* and data */
 	ushort_t fhx_xlen;			/* export file number length */
-	char	fhx_xdata[NFS_FHMAXDATA_EXT];	/* and data */
-} fhandle_ext_t;
+	char	fhx_xdata[NFS_FH4MAXDATA];	/* and data */
+} fhandle4_t;
 
 /*
  * Arguments to remote write and writecache
@@ -795,54 +806,54 @@
 
 extern void rfs_getattr(fhandle_t *, struct nfsattrstat *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs_getattr_getfh(fhandle_t *);
+extern void *rfs_getattr_getfh(fhandle_t *);
 extern void rfs_setattr(struct nfssaargs *, struct nfsattrstat *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs_setattr_getfh(struct nfssaargs *);
+extern void *rfs_setattr_getfh(struct nfssaargs *);
 extern void rfs_lookup(struct nfsdiropargs *, struct nfsdiropres *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs_lookup_getfh(struct nfsdiropargs *);
+extern void *rfs_lookup_getfh(struct nfsdiropargs *);
 extern void rfs_readlink(fhandle_t *, struct nfsrdlnres *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs_readlink_getfh(fhandle_t *);
+extern void *rfs_readlink_getfh(fhandle_t *);
 extern void rfs_rlfree(struct nfsrdlnres *);
 extern void rfs_read(struct nfsreadargs *, struct nfsrdresult *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs_read_getfh(struct nfsreadargs *);
+extern void *rfs_read_getfh(struct nfsreadargs *);
 extern void rfs_rdfree(struct nfsrdresult *);
 extern void rfs_write_sync(struct nfswriteargs *, struct nfsattrstat *,
 			struct exportinfo *, struct svc_req *, cred_t *);
 extern void rfs_write(struct nfswriteargs *, struct nfsattrstat *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs_write_getfh(struct nfswriteargs *);
+extern void *rfs_write_getfh(struct nfswriteargs *);
 extern void rfs_create(struct nfscreatargs *, struct nfsdiropres *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs_create_getfh(struct nfscreatargs *);
+extern void *rfs_create_getfh(struct nfscreatargs *);
 extern void rfs_remove(struct nfsdiropargs *, enum nfsstat *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs_remove_getfh(struct nfsdiropargs *);
+extern void *rfs_remove_getfh(struct nfsdiropargs *);
 extern void rfs_rename(struct nfsrnmargs *, enum nfsstat *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs_rename_getfh(struct nfsrnmargs *);
+extern void *rfs_rename_getfh(struct nfsrnmargs *);
 extern void rfs_link(struct nfslinkargs *, enum nfsstat *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs_link_getfh(struct nfslinkargs *);
+extern void *rfs_link_getfh(struct nfslinkargs *);
 extern void rfs_symlink(struct nfsslargs *, enum nfsstat *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs_symlink_getfh(struct nfsslargs *);
+extern void *rfs_symlink_getfh(struct nfsslargs *);
 extern void rfs_mkdir(struct nfscreatargs *, struct nfsdiropres *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs_mkdir_getfh(struct nfscreatargs *);
+extern void *rfs_mkdir_getfh(struct nfscreatargs *);
 extern void rfs_rmdir(struct nfsdiropargs *, enum nfsstat *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs_rmdir_getfh(struct nfsdiropargs *);
+extern void *rfs_rmdir_getfh(struct nfsdiropargs *);
 extern void rfs_readdir(struct nfsrddirargs *, struct nfsrddirres *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs_readdir_getfh(struct nfsrddirargs *);
+extern void *rfs_readdir_getfh(struct nfsrddirargs *);
 extern void rfs_rddirfree(struct nfsrddirres *);
 extern void rfs_statfs(fhandle_t *, struct nfsstatfs *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs_statfs_getfh(fhandle_t *);
+extern void *rfs_statfs_getfh(fhandle_t *);
 extern void rfs_srvrinit(void);
 extern void rfs_srvrfini(void);
 
@@ -1008,21 +1019,22 @@
 
 typedef uint64 writeverf3;
 
-struct nfs_fh3 {
+typedef struct nfs_fh3 {
 	uint_t fh3_length;
 	union nfs_fh3_u {
 		struct nfs_fh3_i {
-			fhandle_t fh3_i;
+			fhandle3_t fh3_i;
 		} nfs_fh3_i;
 		char data[NFS3_FHSIZE];
 	} fh3_u;
-};
-#define	fh3_fsid	fh3_u.nfs_fh3_i.fh3_i.fh_fsid
-#define	fh3_len		fh3_u.nfs_fh3_i.fh3_i.fh_len /* fid length */
-#define	fh3_data	fh3_u.nfs_fh3_i.fh3_i.fh_data /* fid bytes */
-#define	fh3_xlen	fh3_u.nfs_fh3_i.fh3_i.fh_xlen
-#define	fh3_xdata	fh3_u.nfs_fh3_i.fh3_i.fh_xdata
-typedef struct nfs_fh3 nfs_fh3;
+} nfs_fh3;
+#define	fh3_fsid	fh3_u.nfs_fh3_i.fh3_i._fh3_fsid
+#define	fh3_len		fh3_u.nfs_fh3_i.fh3_i._fh3_len
+#define	fh3_data	fh3_u.nfs_fh3_i.fh3_i._fh3_data
+#define	fh3_xlen	fh3_u.nfs_fh3_i.fh3_i._fh3_xlen
+#define	fh3_xdata	fh3_u.nfs_fh3_i.fh3_i._fh3_xdata
+#define	FH3TOFIDP(fh)	((fid_t *)&((fh)->fh3_len))
+#define	FH3TOXFIDP(fh)	((fid_t *)&((fh)->fh3_xlen))
 
 /*
  * Two elements were added to the
@@ -2056,6 +2068,8 @@
 /* the NFS Version 3 XDR functions */
 
 extern bool_t xdr_nfs_fh3(XDR *, nfs_fh3 *);
+extern bool_t xdr_nfslog_nfs_fh3(XDR *, nfs_fh3 *);
+extern bool_t xdr_nfs_fh3_server(XDR *, nfs_fh3 *);
 extern bool_t xdr_diropargs3(XDR *, diropargs3 *);
 extern bool_t xdr_post_op_attr(XDR *, post_op_attr *);
 extern bool_t xdr_post_op_fh3(XDR *, post_op_fh3 *);
@@ -2113,71 +2127,71 @@
 
 extern void rfs3_getattr(GETATTR3args *, GETATTR3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_getattr_getfh(GETATTR3args *);
+extern void *rfs3_getattr_getfh(GETATTR3args *);
 extern void rfs3_setattr(SETATTR3args *, SETATTR3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_setattr_getfh(SETATTR3args *);
+extern void *rfs3_setattr_getfh(SETATTR3args *);
 extern void rfs3_lookup(LOOKUP3args *, LOOKUP3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_lookup_getfh(LOOKUP3args *);
+extern void *rfs3_lookup_getfh(LOOKUP3args *);
 extern void rfs3_access(ACCESS3args *, ACCESS3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_access_getfh(ACCESS3args *);
+extern void *rfs3_access_getfh(ACCESS3args *);
 extern void rfs3_readlink(READLINK3args *, READLINK3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_readlink_getfh(READLINK3args *);
+extern void *rfs3_readlink_getfh(READLINK3args *);
 extern void rfs3_readlink_free(READLINK3res *);
 extern void rfs3_read(READ3args *, READ3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_read_getfh(READ3args *);
+extern void *rfs3_read_getfh(READ3args *);
 extern void rfs3_read_free(READ3res *);
 extern void rfs3_write(WRITE3args *, WRITE3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_write_getfh(WRITE3args *);
+extern void *rfs3_write_getfh(WRITE3args *);
 extern void rfs3_create(CREATE3args *, CREATE3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_create_getfh(CREATE3args *);
+extern void *rfs3_create_getfh(CREATE3args *);
 extern void rfs3_mkdir(MKDIR3args *, MKDIR3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_mkdir_getfh(MKDIR3args *);
+extern void *rfs3_mkdir_getfh(MKDIR3args *);
 extern void rfs3_symlink(SYMLINK3args *, SYMLINK3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_symlink_getfh(SYMLINK3args *);
+extern void *rfs3_symlink_getfh(SYMLINK3args *);
 extern void rfs3_mknod(MKNOD3args *, MKNOD3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_mknod_getfh(MKNOD3args *);
+extern void *rfs3_mknod_getfh(MKNOD3args *);
 extern void rfs3_remove(REMOVE3args *, REMOVE3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_remove_getfh(REMOVE3args *);
+extern void *rfs3_remove_getfh(REMOVE3args *);
 extern void rfs3_rmdir(RMDIR3args *, RMDIR3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_rmdir_getfh(RMDIR3args *);
+extern void *rfs3_rmdir_getfh(RMDIR3args *);
 extern void rfs3_rename(RENAME3args *, RENAME3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_rename_getfh(RENAME3args *);
+extern void *rfs3_rename_getfh(RENAME3args *);
 extern void rfs3_link(LINK3args *, LINK3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_link_getfh(LINK3args *);
+extern void *rfs3_link_getfh(LINK3args *);
 extern void rfs3_readdir(READDIR3args *, READDIR3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_readdir_getfh(READDIR3args *);
+extern void *rfs3_readdir_getfh(READDIR3args *);
 extern void rfs3_readdir_free(READDIR3res *);
 extern void rfs3_readdirplus(READDIRPLUS3args *, READDIRPLUS3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_readdirplus_getfh(READDIRPLUS3args *);
+extern void *rfs3_readdirplus_getfh(READDIRPLUS3args *);
 extern void rfs3_readdirplus_free(READDIRPLUS3res *);
 extern void rfs3_fsstat(FSSTAT3args *, FSSTAT3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_fsstat_getfh(FSSTAT3args *);
+extern void *rfs3_fsstat_getfh(FSSTAT3args *);
 extern void rfs3_fsinfo(FSINFO3args *, FSINFO3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_fsinfo_getfh(FSINFO3args *);
+extern void *rfs3_fsinfo_getfh(FSINFO3args *);
 extern void rfs3_pathconf(PATHCONF3args *, PATHCONF3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_pathconf_getfh(PATHCONF3args *);
+extern void *rfs3_pathconf_getfh(PATHCONF3args *);
 extern void rfs3_commit(COMMIT3args *, COMMIT3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *rfs3_commit_getfh(COMMIT3args *);
+extern void *rfs3_commit_getfh(COMMIT3args *);
 extern void rfs3_srvrinit(void);
 extern void rfs3_srvrfini(void);
 
--- a/usr/src/uts/common/nfs/nfs4.h	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/uts/common/nfs/nfs4.h	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -944,7 +943,7 @@
 #ifdef VOLATILE_FH_TEST
 
 struct nfs_fh4_fmt {
-	fhandle_ext_t	fh4_i;
+	fhandle4_t	fh4_i;
 	uint32_t	fh4_flag;
 	uint32_t	fh4_volatile_id;
 };
@@ -952,7 +951,7 @@
 #else /* VOLATILE_FH_TEST */
 
 struct nfs_fh4_fmt {
-	fhandle_ext_t	fh4_i;
+	fhandle4_t	fh4_i;
 	uint32_t	fh4_flag;
 };
 
--- a/usr/src/uts/common/nfs/nfs_acl.h	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/uts/common/nfs/nfs_acl.h	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- *	Copyright 2004 Sun Microsystems, Inc.
+ *	Copyright 2006 Sun Microsystems, Inc.
  *	All rights reserved.
  *	Use is subject to license terms.
  */
@@ -330,31 +329,31 @@
 /* the service procedures */
 extern void acl2_getacl(GETACL2args *, GETACL2res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *acl2_getacl_getfh(GETACL2args *);
+extern void *acl2_getacl_getfh(GETACL2args *);
 extern void acl2_getacl_free(GETACL2res *);
 extern void acl2_setacl(SETACL2args *, SETACL2res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *acl2_setacl_getfh(SETACL2args *);
+extern void *acl2_setacl_getfh(SETACL2args *);
 extern void acl2_getattr(GETATTR2args *, GETATTR2res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *acl2_getattr_getfh(GETATTR2args *);
+extern void *acl2_getattr_getfh(GETATTR2args *);
 extern void acl2_access(ACCESS2args *, ACCESS2res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *acl2_access_getfh(ACCESS2args *);
+extern void *acl2_access_getfh(ACCESS2args *);
 extern void acl2_getxattrdir(GETXATTRDIR2args *, GETXATTRDIR2res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *acl2_getxattrdir_getfh(GETXATTRDIR2args *);
+extern void *acl2_getxattrdir_getfh(GETXATTRDIR2args *);
 
 extern void acl3_getacl(GETACL3args *, GETACL3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *acl3_getacl_getfh(GETACL3args *);
+extern void *acl3_getacl_getfh(GETACL3args *);
 extern void acl3_getacl_free(GETACL3res *);
 extern void acl3_setacl(SETACL3args *, SETACL3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *acl3_setacl_getfh(SETACL3args *);
+extern void *acl3_setacl_getfh(SETACL3args *);
 extern void acl3_getxattrdir(GETXATTRDIR3args *, GETXATTRDIR3res *,
 			struct exportinfo *, struct svc_req *, cred_t *);
-extern fhandle_t *acl3_getxattrdir_getfh(GETXATTRDIR3args *);
+extern void *acl3_getxattrdir_getfh(GETXATTRDIR3args *);
 
 #endif
 
--- a/usr/src/uts/common/nfs/nfs_dispatch.h	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/uts/common/nfs/nfs_dispatch.h	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -46,7 +45,7 @@
  * Indexed by version, proc
  */
 
-struct rpcdisp {
+typedef struct rpcdisp {
 	void	  (*dis_proc)();	/* proc to call */
 	xdrproc_t dis_xdrargs;		/* xdr routine to get args */
 	xdrproc_t dis_fastxdrargs;	/* `fast' xdr routine to get args */
@@ -56,8 +55,8 @@
 	int	  dis_ressz;		/* size of results */
 	void	  (*dis_resfree)();	/* frees space allocated by proc */
 	int	  dis_flags;		/* flags, see below */
-	fhandle_t *(*dis_getfh)();	/* returns the fhandle for the req */
-};
+	void	  *(*dis_getfh)();	/* returns the fhandle for the req */
+} rpcdisp_t;
 
 #define	RPC_IDEMPOTENT	0x1	/* idempotent or not */
 /*
@@ -70,12 +69,12 @@
 #define	RPC_AVOIDWORK	0x8	/* do work avoidance for dups */
 #define	RPC_PUBLICFH_OK	0x10	/* allow use of public filehandle */
 
-struct rpc_disptable {
+typedef struct rpc_disptable {
 	int dis_nprocs;
 	char **dis_procnames;
 	kstat_named_t **dis_proccntp;
 	struct rpcdisp *dis_table;
-};
+} rpc_disptable_t;
 
 void	rpc_null(caddr_t *, caddr_t *);
 
--- a/usr/src/uts/common/nfs/nfssys.h	Mon Mar 13 17:04:18 2006 -0800
+++ b/usr/src/uts/common/nfs/nfssys.h	Mon Mar 13 17:10:47 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -47,11 +46,11 @@
  * implemented, but the entries are kept as placeholders for binary
  * compatibility.
  */
-enum nfssys_op	{ OLD_NFS_SVC, OLD_ASYNC_DAEMON, EXPORTFS, NFS_GETFH,
+enum nfssys_op	{ OLD_NFS_SVC, OLD_ASYNC_DAEMON, EXPORTFS, OLD_NFS_GETFH,
     OLD_NFS_CNVT, NFS_REVAUTH, OLD_NFS_FH_TO_FID, OLD_LM_SVC, KILL_LOCKMGR,
     LOG_FLUSH, SVCPOOL_CREATE, NFS_SVC, LM_SVC, SVCPOOL_WAIT, SVCPOOL_RUN,
     NFS4_SVC, RDMA_SVC_INIT, NFS4_CLR_STATE, NFS_IDMAP,
-    NFS_SVC_REQUEST_QUIESCE };
+    NFS_SVC_REQUEST_QUIESCE, NFS_GETFH };
 
 struct nfs_svc_args {
 	int		fd;		/* Connection endpoint */
@@ -87,12 +86,16 @@
 
 struct nfs_getfh_args {
 	char		*fname;
-	fhandle_t	*fhp;
+	int		vers;
+	int		*lenp;
+	char		*fhp;
 };
 
 #ifdef _SYSCALL32
 struct nfs_getfh_args32 {
 	caddr32_t	fname;
+	int32_t		vers;
+	caddr32_t	lenp;
 	caddr32_t	fhp;
 };
 #endif