[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: patches to move sys_getfh to vfs_syscalls.c?



Artur Grabowski <art@stacken.kth.se> writes:
> Hmm.. I was supposed to do that ages ago..

:-)

> How about fhopen?

Patches included below.

a) breaks up the vfs operation vfs_fhtovp into two: fhtovp that maps a
filehandle into a vnode and check_exp that verifies if the filesystem
is exported to a particular client
b) introduces the new system calls fhopen, fhstat, fhstatfs that are
like open but with a file handle instead of a file name.
c) as a bonus, LFS is buildable again.

The reason for this patches is to allow applications to handle files
by their handles instead of names.  By doing getfh() on the file and
remembering that, the application doesn't need to perform an expensive
name -> vp mapping everytime it needs to read an file.

These patches are largely based on the work by Bill Studenmund in
NetBSD.

Comments/thought/objections/questions about these?

/assar

Index: adosfs/advfsops.c
===================================================================
RCS file: /cvs/src/sys/adosfs/advfsops.c,v
retrieving revision 1.15
diff -u -w -r1.15 advfsops.c
--- adosfs/advfsops.c	1999/05/31 17:34:44	1.15
+++ adosfs/advfsops.c	2000/02/01 22:55:10
@@ -61,8 +61,8 @@
 int	 adosfs_statfs __P((struct mount *, struct statfs *, struct proc *));
 int	 adosfs_sync __P((struct mount *, int, struct ucred *, struct proc *));
 int	 adosfs_vget __P((struct mount *, ino_t, struct vnode **));
-int	 adosfs_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
-    struct vnode **, int *, struct ucred **));
+int	 adosfs_fhtovp __P((struct mount *, struct fid *, struct vnode **));
+
 int	 adosfs_vptofh __P((struct vnode *, struct fid *));
 
 int	 adosfs_mountfs __P((struct vnode *, struct mount *, struct proc *));
@@ -659,13 +659,10 @@
 };
 
 int
-adosfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
+adosfs_fhtovp(mp, fhp, vpp)
 	struct mount *mp;
 	struct fid *fhp;
-	struct mbuf *nam;
 	struct vnode **vpp;
-	int *exflagsp;
-	struct ucred **credanonp;
 {
 	struct ifid *ifhp = (struct ifid *)fhp;
 	struct adosfsmount *amp = VFSTOADOSFS(mp);
@@ -680,13 +677,6 @@
 	printf("adfhtovp(%x, %x, %x)\n", mp, fhp, vpp);
 #endif
 	
-	/*
-	 * Get the export permission structure for this <mp, client> tuple.
-	 */
-	np = vfs_export_lookup(mp, &amp->export, nam);
-	if (np == NULL)
-		return (EACCES);
-
 	if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) {
 		*vpp = NULLVP;
 		return (error);
Index: isofs/cd9660/cd9660_extern.h
===================================================================
RCS file: /cvs/src/sys/isofs/cd9660/cd9660_extern.h,v
retrieving revision 1.3
diff -u -w -r1.3 cd9660_extern.h
--- isofs/cd9660/cd9660_extern.h	1999/07/01 02:20:20	1.3
+++ isofs/cd9660/cd9660_extern.h	2000/02/01 22:55:36
@@ -93,8 +93,7 @@
 int cd9660_statfs __P((struct mount *, struct statfs *, struct proc *));
 int cd9660_sync __P((struct mount *, int, struct ucred *, struct proc *));
 int cd9660_vget __P((struct mount *, ino_t, struct vnode **));
-int cd9660_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
-	    struct vnode **, int *, struct ucred **));
+int cd9660_fhtovp __P((struct mount *, struct fid *, struct vnode **));
 int cd9660_vptofh __P((struct vnode *, struct fid *));
 int cd9660_init __P((struct vfsconf *));
 #define cd9660_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
Index: isofs/cd9660/cd9660_vfsops.c
===================================================================
RCS file: /cvs/src/sys/isofs/cd9660/cd9660_vfsops.c,v
retrieving revision 1.18
diff -u -w -r1.18 cd9660_vfsops.c
--- isofs/cd9660/cd9660_vfsops.c	1999/08/17 10:56:07	1.18
+++ isofs/cd9660/cd9660_vfsops.c	2000/02/01 22:55:37
@@ -670,18 +670,13 @@
 
 /* ARGSUSED */
 int
-cd9660_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
+cd9660_fhtovp(mp, fhp, vpp)
 	register struct mount *mp;
 	struct fid *fhp;
-	struct mbuf *nam;
 	struct vnode **vpp;
-	int *exflagsp;
-	struct ucred **credanonp;
 {
 	struct ifid *ifhp = (struct ifid *)fhp;
 	register struct iso_node *ip;
-	register struct netcred *np;
-	register struct iso_mnt *imp = VFSTOISOFS(mp);
 	struct vnode *nvp;
 	int error;
 	
@@ -690,13 +685,6 @@
 	    ifhp->ifid_start);
 #endif
 	
-	/*
-	 * Get the export permission structure for this <mp, client> tuple.
-	 */
-	np = vfs_export_lookup(mp, &imp->im_export, nam);
-	if (np == NULL)
-		return (EACCES);
-
 	if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) {
 		*vpp = NULLVP;
 		return (error);
@@ -708,8 +696,6 @@
 		return (ESTALE);
 	}
 	*vpp = nvp;
-	*exflagsp = np->netc_exflags;
-	*credanonp = &np->netc_anon;
 	return (0);
 }
 
Index: kern/init_sysent.c
===================================================================
RCS file: /cvs/src/sys/kern/init_sysent.c,v
retrieving revision 1.41
diff -u -w -r1.41 init_sysent.c
--- kern/init_sysent.c	1999/08/08 00:32:22	1.41
+++ kern/init_sysent.c	2000/02/01 22:55:38
@@ -687,5 +682,11 @@
 	    sys_fstatfs },			/* 262 = fstatfs */
 	{ 1, s(struct sys_pipe_args),
 	    sys_pipe },				/* 263 = pipe */
+	{ 2, s(struct sys_fhopen_args),
+	    sys_fhopen },			/* 264 = fhopen */
+	{ 2, s(struct sys_fhstat_args),
+	    sys_fhstat },			/* 265 = fhstat */
+	{ 2, s(struct sys_fhstatfs_args),
+	    sys_fhstatfs },			/* 266 = fhstatfs */
 };
 
Index: kern/syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/syscalls.c,v
retrieving revision 1.41
diff -u -w -r1.41 syscalls.c
--- kern/syscalls.c	1999/08/08 00:32:22	1.41
+++ kern/syscalls.c	2000/02/01 22:55:39
@@ -358,4 +354,7 @@
 	"statfs",			/* 261 = statfs */
 	"fstatfs",			/* 262 = fstatfs */
 	"pipe",			/* 263 = pipe */
+	"fhopen",			/* 264 = fhopen */
+	"fhstat",			/* 265 = fhstat */
+	"fhstatfs",			/* 266 = fhstatfs */
 };
Index: kern/syscalls.master
===================================================================
RCS file: /cvs/src/sys/kern/syscalls.master,v
retrieving revision 1.37
diff -u -w -r1.37 syscalls.master
--- kern/syscalls.master	1999/06/07 07:17:42	1.37
+++ kern/syscalls.master	2000/02/01 22:55:40
@@ -520,3 +516,8 @@
 			    struct statfs *buf); }
 262	STD		{ int sys_fstatfs(int fd, struct statfs *buf); }
 263	STD		{ int sys_pipe(int *fdp); }
+264	STD		{ int sys_fhopen(const fhandle_t *fhp, int flags); }
+265	STD		{ int sys_fhstat(const fhandle_t *fhp, \
+			    struct stat *sb); }
+266	STD		{ int sys_fhstatfs(const fhandle_t *fhp, \
+			    struct statfs *buf); }
Index: kern/vfs_conf.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_conf.c,v
retrieving revision 1.13
diff -u -w -r1.13 vfs_conf.c
--- kern/vfs_conf.c	1999/02/15 05:05:33	1.13
+++ kern/vfs_conf.c	2000/02/01 22:55:41
@@ -46,6 +46,10 @@
 #include <ufs/ffs/ffs_extern.h>
 #endif
 
+#ifdef LFS
+#include <ufs/lfs/lfs_extern.h>
+#endif
+
 #ifdef EXT2FS
 #include <ufs/ext2fs/ext2fs_extern.h>
 #endif
Index: kern/vfs_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.61
diff -u -w -r1.61 vfs_syscalls.c
--- kern/vfs_syscalls.c	2000/02/01 04:03:14	1.61
+++ kern/vfs_syscalls.c	2000/02/01 22:55:44
@@ -948,6 +948,251 @@
 }
 
 /*
+ * Get file handle system call
+ */
+int
+sys_getfh(p, v, retval)
+	struct proc *p;
+	register void *v;
+	register_t *retval;
+{
+	register struct sys_getfh_args /* {
+		syscallarg(char *) fname;
+		syscallarg(fhandle_t *) fhp;
+	} */ *uap = v;
+	register struct vnode *vp;
+	fhandle_t fh;
+	int error;
+	struct nameidata nd;
+
+	/*
+	 * Must be super user
+	 */
+	error = suser(p->p_ucred, &p->p_acflag);
+	if(error)
+		return (error);
+	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+	    SCARG(uap, fname), p);
+	error = namei(&nd);
+	if (error)
+		return (error);
+	vp = nd.ni_vp;
+	bzero((caddr_t)&fh, sizeof(fh));
+	fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
+	error = VFS_VPTOFH(vp, &fh.fh_fid);
+	vput(vp);
+	if (error)
+		return (error);
+	error = copyout((caddr_t)&fh, (caddr_t)SCARG(uap, fhp), sizeof (fh));
+	return (error);
+}
+
+/*
+ * Open a file given a file handle.
+ *
+ * Check permissions, allocate an open file structure,
+ * and call the device open routine if any.
+ */
+int
+sys_fhopen(p, v, retval)
+	struct proc *p;
+	void *v;
+	register_t *retval;
+{
+	register struct sys_fhopen_args /* {
+		syscallarg(const fhandle_t *) fhp;
+		syscallarg(int) flags;
+	} */ *uap = v;
+	struct filedesc *fdp = p->p_fd;
+	struct file *fp;
+	struct vnode *vp = NULL;
+	struct mount *mp;
+	struct ucred *cred = p->p_ucred;
+	int flags;
+	struct file *nfp;
+	int type, indx, error=0;
+	struct flock lf;
+	struct vattr va;
+	fhandle_t fh;
+
+	/*
+	 * Must be super user
+	 */
+	if ((error = suser(p->p_ucred, &p->p_acflag)))
+		return (error);
+
+	flags = FFLAGS(SCARG(uap, flags));
+	if ((flags & (FREAD | FWRITE)) == 0)
+		return (EINVAL);
+	if ((flags & O_CREAT))
+		return (EINVAL);
+
+	if ((error = falloc(p, &nfp, &indx)) != 0)
+		return (error);
+	fp = nfp;
+	if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
+		goto bad;
+
+	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
+		error = ESTALE;
+		goto bad;
+	}
+
+	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)) != 0) {
+		vp = NULL;	/* most likely unnecessary sanity for bad: */
+		goto bad;
+	}
+
+	/* Now do an effective vn_open */
+
+	if (vp->v_type == VSOCK) {
+		error = EOPNOTSUPP;
+		goto bad;
+	}
+	if (flags & FREAD) {
+		if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0)
+			goto bad;
+	}
+	if (flags & (FWRITE | O_TRUNC)) {
+		if (vp->v_type == VDIR) {
+			error = EISDIR;
+			goto bad;
+		}
+		if ((error = vn_writechk(vp)) != 0 ||
+		    (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0)
+			goto bad;
+	}
+	if (flags & O_TRUNC) {
+		VOP_UNLOCK(vp, 0, p);				/* XXX */
+		VOP_LEASE(vp, p, cred, LEASE_WRITE);
+		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);	/* XXX */
+		VATTR_NULL(&va);
+		va.va_size = 0;
+		if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0)
+			goto bad;
+	}
+	if ((error = VOP_OPEN(vp, flags, cred, p)) != 0)
+		goto bad;
+	if (flags & FWRITE)
+		vp->v_writecount++;
+
+	/* done with modified vn_open, now finish what sys_open does. */
+
+	fp->f_flag = flags & FMASK;
+	fp->f_type = DTYPE_VNODE;
+	fp->f_ops = &vnops;
+	fp->f_data = (caddr_t)vp;
+	if (flags & (O_EXLOCK | O_SHLOCK)) {
+		lf.l_whence = SEEK_SET;
+		lf.l_start = 0;
+		lf.l_len = 0;
+		if (flags & O_EXLOCK)
+			lf.l_type = F_WRLCK;
+		else
+			lf.l_type = F_RDLCK;
+		type = F_FLOCK;
+		if ((flags & FNONBLOCK) == 0)
+			type |= F_WAIT;
+		VOP_UNLOCK(vp, 0, p);
+		error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
+		if (error) {
+			(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
+			ffree(fp);
+			fdremove(fdp, indx);
+			return (error);
+		}
+		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+		fp->f_flag |= FHASLOCK;
+	}
+	VOP_UNLOCK(vp, 0, p);
+	*retval = indx;
+	return (0);
+
+bad:
+	ffree(fp);
+	fdremove(fdp, indx);
+	if (vp != NULL)
+		vput(vp);
+	return (error);
+}
+
+/* ARGSUSED */
+int
+sys_fhstat(p, v, retval)
+	struct proc *p;
+	void *v;
+	register_t *retval;
+{
+	register struct sys_fhstat_args /* {
+		syscallarg(const fhandle_t *) fhp;
+		syscallarg(struct stat *) sb;
+	} */ *uap = v;
+	struct stat sb;
+	int error;
+	fhandle_t fh;
+	struct mount *mp;
+	struct vnode *vp;
+
+	/*
+	 * Must be super user
+	 */
+	if ((error = suser(p->p_ucred, &p->p_acflag)))
+		return (error);
+
+	if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
+		return (error);
+
+	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
+		return (ESTALE);
+	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
+		return (error);
+	error = vn_stat(vp, &sb, p);
+	vput(vp);
+	if (error)
+		return (error);
+	error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
+	return (error);
+}
+
+/* ARGSUSED */
+int
+sys_fhstatfs(p, v, retval)
+	struct proc *p;
+	void *v;
+	register_t *retval;
+{
+	register struct sys_fhstatfs_args /*
+		syscallarg(const fhandle_t *) fhp;
+		syscallarg(struct statfs *) buf;
+	} */ *uap = v;
+	struct statfs sp;
+	fhandle_t fh;
+	struct mount *mp;
+	struct vnode *vp;
+	int error;
+
+	/*
+	 * Must be super user
+	 */
+	if ((error = suser(p->p_ucred, &p->p_acflag)))
+		return (error);
+
+	if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
+		return (error);
+
+	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
+		return (ESTALE);
+	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
+		return (error);
+	mp = vp->v_mount;
+	vput(vp);
+	if ((error = VFS_STATFS(mp, &sp, p)) != 0)
+		return (error);
+	sp.f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+	return (copyout(&sp, SCARG(uap, buf), sizeof(sp)));
+}
+
+/*
  * Create a special file.
  */
 /* ARGSUSED */
Index: miscfs/fdesc/fdesc_vfsops.c
===================================================================
RCS file: /cvs/src/sys/miscfs/fdesc/fdesc_vfsops.c,v
retrieving revision 1.7
diff -u -w -r1.7 fdesc_vfsops.c
--- miscfs/fdesc/fdesc_vfsops.c	1999/05/31 17:34:49	1.7
+++ miscfs/fdesc/fdesc_vfsops.c	2000/02/01 22:55:46
@@ -68,8 +68,7 @@
 int	fdesc_statfs __P((struct mount *, struct statfs *, struct proc *));
 int	fdesc_sync __P((struct mount *, int, struct ucred *, struct proc *));
 int	fdesc_vget __P((struct mount *, ino_t, struct vnode **));
-int	fdesc_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
-			  struct vnode **, int *, struct ucred **));
+int	fdesc_fhtovp __P((struct mount *, struct fid *, struct vnode **));
 int	fdesc_vptofh __P((struct vnode *, struct fid *));
 
 /*
@@ -242,7 +241,7 @@
 }
 
 #define fdesc_fhtovp ((int (*) __P((struct mount *, struct fid *, \
-	    struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
+	    struct vnode **)))eopnotsupp)
 #define fdesc_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
 	    struct proc *)))eopnotsupp)
 #define fdesc_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
@@ -251,6 +250,9 @@
 	    eopnotsupp)
 #define fdesc_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
  
+#define fdesc_checkexp ((int (*) __P((struct mount *, struct mbuf *,	\
+	int *, struct ucred **)))eopnotsupp)
+
 struct vfsops fdesc_vfsops = {
 	fdesc_mount,
 	fdesc_start,
@@ -263,6 +265,6 @@
 	fdesc_fhtovp,
 	fdesc_vptofh,
 	fdesc_init,
-	fdesc_sysctl
+	fdesc_sysctl,
+	fdesc_checkexp
 };
-
Index: miscfs/kernfs/kernfs.h
===================================================================
RCS file: /cvs/src/sys/miscfs/kernfs/kernfs.h,v
retrieving revision 1.7
diff -u -w -r1.7 kernfs.h
--- miscfs/kernfs/kernfs.h	1998/12/28 05:51:38	1.7
+++ miscfs/kernfs/kernfs.h	2000/02/01 22:55:46
@@ -78,7 +78,7 @@
 #define	VTOKERN(vp) ((struct kernfs_node *)(vp)->v_data)
 
 #define kernfs_fhtovp ((int (*) __P((struct mount *, struct fid *, \
-	    struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
+	    struct vnode **)))eopnotsupp)
 #define kernfs_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
 	    struct proc *)))eopnotsupp)
 #define kernfs_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
@@ -88,6 +88,8 @@
 #define kernfs_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
 #define kernfs_sync ((int (*) __P((struct mount *, int, struct ucred *, \
 				   struct proc *)))nullop)
+#define kernfs_checkexp ((int (*) __P((struct mount *, struct mbuf *,	\
+	int *, struct ucred **)))eopnotsupp)
 
 extern int (**kernfs_vnodeop_p) __P((void *));
 extern struct vfsops kernfs_vfsops;
Index: miscfs/kernfs/kernfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/miscfs/kernfs/kernfs_vfsops.c,v
retrieving revision 1.12
diff -u -w -r1.12 kernfs_vfsops.c
--- miscfs/kernfs/kernfs_vfsops.c	1999/05/31 17:34:49	1.12
+++ miscfs/kernfs/kernfs_vfsops.c	2000/02/01 22:55:47
@@ -285,5 +285,6 @@
 	kernfs_fhtovp,
 	kernfs_vptofh,
 	kernfs_init,
-	kernfs_sysctl
+	kernfs_sysctl,
+	kernfs_checkexp
 };
Index: miscfs/nullfs/null_vfsops.c
===================================================================
RCS file: /cvs/src/sys/miscfs/nullfs/null_vfsops.c,v
retrieving revision 1.10
diff -u -w -r1.10 null_vfsops.c
--- miscfs/nullfs/null_vfsops.c	1999/05/31 17:34:49	1.10
+++ miscfs/nullfs/null_vfsops.c	2000/02/01 22:55:48
@@ -67,8 +67,7 @@
 int	nullfs_statfs __P((struct mount *, struct statfs *, struct proc *));
 int	nullfs_sync __P((struct mount *, int, struct ucred *, struct proc *));
 int	nullfs_vget __P((struct mount *, ino_t, struct vnode **));
-int	nullfs_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
-			   struct vnode **, int *, struct ucred **));
+int	nullfs_fhtovp __P((struct mount *, struct fid *, struct vnode **));
 int	nullfs_vptofh __P((struct vnode *, struct fid *));
 /*
  * Mount null layer
@@ -351,13 +350,10 @@
 }
 
 int
-nullfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
+nullfs_fhtovp(mp, fidp, vpp)
 	struct mount *mp;
 	struct fid *fidp;
-	struct mbuf *nam;
 	struct vnode **vpp;
-	int *exflagsp;
-	struct ucred**credanonp;
 {
 
 	return (EOPNOTSUPP);
@@ -375,6 +371,9 @@
 #define nullfs_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
            size_t, struct proc *)))eopnotsupp)
 
+#define nullfs_checkexp ((int (*) __P((struct mount *, struct mbuf *,	\
+	int *, struct ucred **)))eopnotsupp)
+
 struct vfsops null_vfsops = {
 	nullfs_mount,
 	nullfs_start,
@@ -387,5 +386,6 @@
 	nullfs_fhtovp,
 	nullfs_vptofh,
 	nullfs_init,
-	nullfs_sysctl
+	nullfs_sysctl,
+	nullfs_checkexp
 };
Index: miscfs/portal/portal_vfsops.c
===================================================================
RCS file: /cvs/src/sys/miscfs/portal/portal_vfsops.c,v
retrieving revision 1.7
diff -u -w -r1.7 portal_vfsops.c
--- miscfs/portal/portal_vfsops.c	1999/05/31 17:34:50	1.7
+++ miscfs/portal/portal_vfsops.c	2000/02/01 22:55:48
@@ -247,7 +247,7 @@
 				  struct proc *)))nullop)
 
 #define portal_fhtovp ((int (*) __P((struct mount *, struct fid *, \
-	    struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
+	    struct vnode **)))eopnotsupp)
 #define portal_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
 	    struct proc *)))eopnotsupp)
 #define portal_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
@@ -255,6 +255,8 @@
 #define portal_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
 	    eopnotsupp)
 #define portal_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
+#define portal_checkexp ((int (*) __P((struct mount *, struct mbuf *,	\
+	int *, struct ucred **)))eopnotsupp)
 
 struct vfsops portal_vfsops = {
 	portal_mount,
@@ -268,5 +270,6 @@
 	portal_fhtovp,
 	portal_vptofh,
 	portal_init,
-	portal_sysctl
+	portal_sysctl,
+	portal_checkexp
 };
Index: miscfs/procfs/procfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/miscfs/procfs/procfs_vfsops.c,v
retrieving revision 1.10
diff -u -w -r1.10 procfs_vfsops.c
--- miscfs/procfs/procfs_vfsops.c	1999/05/31 17:34:50	1.10
+++ miscfs/procfs/procfs_vfsops.c	2000/02/01 22:55:49
@@ -184,7 +184,7 @@
 				  struct proc *)))nullop)
 
 #define procfs_fhtovp ((int (*) __P((struct mount *, struct fid *, \
-	    struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
+	    struct vnode **)))eopnotsupp)
 #define procfs_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
 	    struct proc *)))eopnotsupp)
 #define procfs_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
@@ -192,6 +192,8 @@
 #define procfs_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
 	    eopnotsupp)
 #define procfs_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
+#define procfs_checkexp ((int (*) __P((struct mount *, struct mbuf *,	\
+	int *, struct ucred **)))eopnotsupp)
 
 struct vfsops procfs_vfsops = {
 	procfs_mount,
@@ -205,5 +207,6 @@
 	procfs_fhtovp,
 	procfs_vptofh,
 	procfs_init,
-	procfs_sysctl
+	procfs_sysctl,
+	procfs_checkexp
 };
Index: miscfs/umapfs/umap_vfsops.c
===================================================================
RCS file: /cvs/src/sys/miscfs/umapfs/umap_vfsops.c,v
retrieving revision 1.14
diff -u -w -r1.14 umap_vfsops.c
--- miscfs/umapfs/umap_vfsops.c	1999/05/31 17:34:50	1.14
+++ miscfs/umapfs/umap_vfsops.c	2000/02/01 22:55:49
@@ -66,8 +66,7 @@
 int	umapfs_statfs __P((struct mount *, struct statfs *, struct proc *));
 int	umapfs_sync __P((struct mount *, int, struct ucred *, struct proc *));
 int	umapfs_vget __P((struct mount *, ino_t, struct vnode **));
-int	umapfs_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
-			   struct vnode **, int *, struct ucred **));
+int	umapfs_fhtovp __P((struct mount *, struct fid *, struct vnode **));
 int	umapfs_vptofh __P((struct vnode *, struct fid *));
 
 /*
@@ -391,15 +390,12 @@
 }
 
 int
-umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
+umapfs_fhtovp(mp, fidp, vpp)
 	struct mount *mp;
 	struct fid *fidp;
-	struct mbuf *nam;
 	struct vnode **vpp;
-	int *exflagsp;
-	struct ucred**credanonp;
 {
-	return VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp, credanonp);
+	return VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, vpp);
 }
 
 int
@@ -412,8 +408,9 @@
 
 #define umapfs_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
 	    size_t, struct proc *)))eopnotsupp)
+#define umapfs_checkexp ((int (*) __P((struct mount *, struct mbuf *,	\
+	int *, struct ucred **)))eopnotsupp)
  
-
 struct vfsops umap_vfsops = {
 	umapfs_mount,
 	umapfs_start,
@@ -426,5 +423,6 @@
 	umapfs_fhtovp,
 	umapfs_vptofh,
 	umapfs_init,
-	umapfs_sysctl
+	umapfs_sysctl,
+	umapfs_checkexp
 };
Index: miscfs/union/union_vfsops.c
===================================================================
RCS file: /cvs/src/sys/miscfs/union/union_vfsops.c,v
retrieving revision 1.9
diff -u -w -r1.9 union_vfsops.c
--- miscfs/union/union_vfsops.c	1999/05/31 17:34:50	1.9
+++ miscfs/union/union_vfsops.c	2000/02/01 22:55:50
@@ -480,7 +480,7 @@
 				  struct proc *)))nullop)
 
 #define union_fhtovp ((int (*) __P((struct mount *, struct fid *, \
-	    struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
+	    struct vnode **)))eopnotsupp)
 #define union_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
 	    struct proc *)))eopnotsupp)
 #define union_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
@@ -488,6 +488,8 @@
 #define union_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
 	    eopnotsupp)
 #define union_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
+#define union_checkexp ((int (*) __P((struct mount *, struct mbuf *,	\
+	int *, struct ucred **)))eopnotsupp)
 
 struct vfsops union_vfsops = {
 	union_mount,
@@ -501,5 +503,6 @@
 	union_fhtovp,
 	union_vptofh,
 	union_init,
-	union_sysctl
+	union_sysctl,
+	union_checkexp
 };
Index: msdosfs/msdosfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/msdosfs/msdosfs_vfsops.c,v
retrieving revision 1.18
diff -u -w -r1.18 msdosfs_vfsops.c
--- msdosfs/msdosfs_vfsops.c	1999/05/31 17:34:51	1.18
+++ msdosfs/msdosfs_vfsops.c	2000/02/01 22:55:51
@@ -77,9 +77,10 @@
 int msdosfs_root __P((struct mount *, struct vnode **));
 int msdosfs_statfs __P((struct mount *, struct statfs *, struct proc *));
 int msdosfs_sync __P((struct mount *, int, struct ucred *, struct proc *));
-int msdosfs_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
-		        struct vnode **, int *, struct ucred **));
+int msdosfs_fhtovp __P((struct mount *, struct fid *, struct vnode **));
 int msdosfs_vptofh __P((struct vnode *, struct fid *));
+int msdosfs_check_export __P((struct mount *mp, struct mbuf *nam,
+			      int *extflagsp, struct ucred **credanonp));
 
 int msdosfs_mountfs __P((struct vnode *, struct mount *, struct proc *,
 			 struct msdosfs_args *));
@@ -776,31 +777,22 @@
 }
 
 int
-msdosfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
+msdosfs_fhtovp(mp, fhp, vpp)
 	struct mount *mp;
 	struct fid *fhp;
-	struct mbuf *nam;
 	struct vnode **vpp;
-	int *exflagsp;
-	struct ucred **credanonp;
 {
 	struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
 	struct defid *defhp = (struct defid *) fhp;
 	struct denode *dep;
-	struct netcred *np;
 	int error;
 
-	np = vfs_export_lookup(mp, &pmp->pm_export, nam);
-	if (np == NULL)
-		return (EACCES);
 	error = deget(pmp, defhp->defid_dirclust, defhp->defid_dirofs, &dep);
 	if (error) {
 		*vpp = NULLVP;
 		return (error);
 	}
 	*vpp = DETOV(dep);
-	*exflagsp = np->netc_exflags;
-	*credanonp = &np->netc_anon;
 	return (0);
 }
 
@@ -821,6 +813,28 @@
 	return (0);
 }
 
+int
+msdosfs_check_export(mp, nam, exflagsp, credanonp)
+	register struct mount *mp;
+	struct mbuf *nam;
+	int *exflagsp;
+	struct ucred **credanonp;
+{
+	register struct netcred *np;
+	register struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
+
+	/*
+	 * Get the export permission structure for this <mp, client> tuple.
+	 */
+	np = vfs_export_lookup(mp, &pmp->pm_export, nam);
+	if (np == NULL)
+		return (EACCES);
+
+	*exflagsp = np->netc_exflags;
+	*credanonp = &np->netc_anon;
+	return (0);
+}
+
 #define msdosfs_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
 		      eopnotsupp)
 
@@ -842,5 +856,6 @@
 	msdosfs_fhtovp,
 	msdosfs_vptofh,
 	msdosfs_init,
-	msdosfs_sysctl
+	msdosfs_sysctl,
+	msdosfs_check_export
 };
Index: msdosfs/msdosfsmount.h
===================================================================
RCS file: /cvs/src/sys/msdosfs/msdosfsmount.h,v
retrieving revision 1.10
diff -u -w -r1.10 msdosfsmount.h
--- msdosfs/msdosfsmount.h	1998/02/08 22:41:44	1.10
+++ msdosfs/msdosfsmount.h	2000/02/01 22:55:51
@@ -205,6 +205,6 @@
 int msdosfs_quotactl __P((struct mount *, int, uid_t, caddr_t, struct proc *));
 int msdosfs_statfs __P((struct mount *, struct statfs *, struct proc *));
 int msdosfs_sync __P((struct mount *, int, struct ucred *, struct proc *));
-int msdosfs_fhtovp __P((struct mount *, struct fid *, struct mbuf *, struct vnode **, int *, struct ucred **));
+int msdosfs_fhtovp __P((struct mount *, struct fid *, struct vnode **));
 int msdosfs_vptofh __P((struct vnode *, struct fid *));
 int msdosfs_init __P((struct vfsconf *));
Index: nfs/nfs_subs.c
===================================================================
RCS file: /cvs/src/sys/nfs/nfs_subs.c,v
retrieving revision 1.27
diff -u -w -r1.27 nfs_subs.c
--- nfs/nfs_subs.c	1999/04/28 09:28:17	1.27
+++ nfs/nfs_subs.c	2000/02/01 22:55:55
@@ -1690,7 +1690,7 @@
 /*
  * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
  * 	- look up fsid in mount list (if not found ret error)
- *	- get vp and export rights by calling VFS_FHTOVP()
+ *	- get vp and export rights by calling VFS_FHTOVP() and VFS_CHECKEXP()
  *	- if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
  *	- if not lockflag unlock it with VOP_UNLOCK()
  */
@@ -1717,7 +1717,10 @@
 
 	if (!mp)
 		return (ESTALE);
-	error = VFS_FHTOVP(mp, &fhp->fh_fid, nam, vpp, &exflags, &credanon);
+	error = VFS_CHECKEXP(mp, nam, &exflags, &credanon);
+	if (error)
+		return (error);
+	error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp);
 	if (error)
 		return (error);
 
Index: nfs/nfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/nfs/nfs_vfsops.c,v
retrieving revision 1.29
diff -u -w -r1.29 nfs_vfsops.c
--- nfs/nfs_vfsops.c	2000/01/06 03:35:37	1.29
+++ nfs/nfs_vfsops.c	2000/02/01 22:56:00
@@ -74,6 +74,9 @@
 
 int nfs_sysctl
     __P((int *, u_int, void *, size_t *, void *, size_t, struct proc *));
+int nfs_checkexp
+    __P((struct mount *mp, struct mbuf *nam,
+	 int *extflagsp, struct ucred **credanonp));
 
 /*
  * nfs vfs operations.
@@ -90,7 +93,8 @@
 	nfs_fhtovp,
 	nfs_vptofh,
 	nfs_vfs_init,
-	nfs_sysctl
+	nfs_sysctl,
+	nfs_checkexp
 };
 
 extern u_int32_t nfs_procids[NFS_NPROCS];
@@ -967,13 +971,10 @@
  */
 /* ARGSUSED */
 int
-nfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
+nfs_fhtovp(mp, fhp, vpp)
 	register struct mount *mp;
 	struct fid *fhp;
-	struct mbuf *nam;
 	struct vnode **vpp;
-	int *exflagsp;
-	struct ucred **credanonp;
 {
 
 	return (EINVAL);
@@ -1019,5 +1020,19 @@
 	struct proc *p;
 {
 
+	return (EOPNOTSUPP);
+}
+
+/*
+ * check export permission, not supported
+ */
+/* ARGUSED */
+int
+nfs_checkexp(mp, nam, exflagsp, credanonp)
+	register struct mount *mp;
+	struct mbuf *nam;
+	int *exflagsp;
+	struct ucred **credanonp;
+{
 	return (EOPNOTSUPP);
 }
Index: nfs/nfsmount.h
===================================================================
RCS file: /cvs/src/sys/nfs/nfsmount.h,v
retrieving revision 1.6
diff -u -w -r1.6 nfsmount.h
--- nfs/nfsmount.h	1999/06/10 05:55:15	1.6
+++ nfs/nfsmount.h	2000/02/01 22:56:02
@@ -116,8 +116,7 @@
 int	nfs_sync __P((struct mount *mp, int waitfor, struct ucred *cred,
 		struct proc *p));
 int	nfs_vget __P((struct mount *, ino_t, struct vnode **));
-int	nfs_fhtovp __P((struct mount *mp, struct fid *fhp, struct mbuf *nam,
-		struct vnode **vpp, int *exflagsp, struct ucred **credanonp));
+int	nfs_fhtovp __P((struct mount *mp, struct fid *fhp, struct vnode **vpp));
 int	nfs_vptofh __P((struct vnode *vp, struct fid *fhp));
 int	nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
 			struct proc *));
Index: sys/mount.h
===================================================================
RCS file: /cvs/src/sys/sys/mount.h,v
retrieving revision 1.32
diff -u -w -r1.32 mount.h
--- sys/mount.h	1999/12/05 06:56:34	1.32
+++ sys/mount.h	2000/02/01 22:56:09
@@ -456,12 +456,13 @@
 	int	(*vfs_vget)	__P((struct mount *mp, ino_t ino,
 				    struct vnode **vpp));
 	int	(*vfs_fhtovp)	__P((struct mount *mp, struct fid *fhp,
-				    struct mbuf *nam, struct vnode **vpp,
-				    int *exflagsp, struct ucred **credanonp));
+				     struct vnode **vpp));
 	int	(*vfs_vptofh)	__P((struct vnode *vp, struct fid *fhp));
 	int	(*vfs_init)	__P((struct vfsconf *));
 	int     (*vfs_sysctl)   __P((int *, u_int, void *, size_t *, void *,
 				     size_t, struct proc *));
+	int	(*vfs_checkexp) __P((struct mount *mp, struct mbuf *nam,
+				    int *extflagsp, struct ucred **credanonp));
 };
 
 #define VFS_MOUNT(MP, PATH, DATA, NDP, P) \
@@ -473,9 +474,11 @@
 #define VFS_STATFS(MP, SBP, P)	  (*(MP)->mnt_op->vfs_statfs)(MP, SBP, P)
 #define VFS_SYNC(MP, WAIT, C, P)  (*(MP)->mnt_op->vfs_sync)(MP, WAIT, C, P)
 #define VFS_VGET(MP, INO, VPP)	  (*(MP)->mnt_op->vfs_vget)(MP, INO, VPP)
-#define VFS_FHTOVP(MP, FIDP, NAM, VPP, EXFLG, CRED) \
-	(*(MP)->mnt_op->vfs_fhtovp)(MP, FIDP, NAM, VPP, EXFLG, CRED)
+#define VFS_FHTOVP(MP, FIDP, VPP) \
+	(*(MP)->mnt_op->vfs_fhtovp)(MP, FIDP, VPP)
 #define	VFS_VPTOFH(VP, FIDP)	  (*(VP)->v_mount->mnt_op->vfs_vptofh)(VP, FIDP)
+#define VFS_CHECKEXP(MP, NAM, EXFLG, CRED) \
+	(*(MP)->mnt_op->vfs_checkexp)(MP, NAM, EXFLG, CRED)
 #endif /* _KERNEL */
 
 /*
@@ -563,7 +566,11 @@
 int	mount __P((const char *, const char *, int, void *));
 int	statfs __P((const char *, struct statfs *));
 int	unmount __P((const char *, int));
-
+#if !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)
+int	fhopen __P((const fhandle_t *, int));
+int	fhstat __P((const fhandle_t *, struct stat *));
+int	fhstatfs __P((const fhandle_t *, struct statfs *));
+#endif /* !_POSIX_C_SOURCE */
 
 __END_DECLS
 
Index: sys/syscall.h
===================================================================
RCS file: /cvs/src/sys/sys/syscall.h,v
retrieving revision 1.40
diff -u -w -r1.40 syscall.h
--- sys/syscall.h	1999/08/08 00:32:21	1.40
+++ sys/syscall.h	2000/02/01 22:56:10
@@ -614,4 +614,13 @@
 /* syscall: "pipe" ret: "int" args: "int *" */
 #define	SYS_pipe	263
 
-#define	SYS_MAXSYSCALL	264
+/* syscall: "fhopen" ret: "int" args: "const fhandle_t *" "int" */
+#define	SYS_fhopen	264
+
+/* syscall: "fhstat" ret: "int" args: "const fhandle_t *" "struct stat *" */
+#define	SYS_fhstat	265
+
+/* syscall: "fhstatfs" ret: "int" args: "const fhandle_t *" "struct statfs *" */
+#define	SYS_fhstatfs	266
+
+#define	SYS_MAXSYSCALL	267
Index: sys/syscallargs.h
===================================================================
RCS file: /cvs/src/sys/sys/syscallargs.h,v
retrieving revision 1.41
diff -u -w -r1.41 syscallargs.h
--- sys/syscallargs.h	1999/08/08 00:32:22	1.41
+++ sys/syscallargs.h	2000/02/01 22:56:17
@@ -1064,6 +1064,21 @@
 	syscallarg(int *) fdp;
 };
 
+struct sys_fhopen_args {
+	syscallarg(const fhandle_t *) fhp;
+	syscallarg(int) flags;
+};
+
+struct sys_fhstat_args {
+	syscallarg(const fhandle_t *) fhp;
+	syscallarg(struct stat *) sb;
+};
+
+struct sys_fhstatfs_args {
+	syscallarg(const fhandle_t *) fhp;
+	syscallarg(struct statfs *) buf;
+};
+
 /*
  * System call prototypes.
  */
@@ -1337,3 +1349,6 @@
 int	sys_statfs	__P((struct proc *, void *, register_t *));
 int	sys_fstatfs	__P((struct proc *, void *, register_t *));
 int	sys_pipe	__P((struct proc *, void *, register_t *));
+int	sys_fhopen	__P((struct proc *, void *, register_t *));
+int	sys_fhstat	__P((struct proc *, void *, register_t *));
+int	sys_fhstatfs	__P((struct proc *, void *, register_t *));
Index: ufs/ext2fs/ext2fs_extern.h
===================================================================
RCS file: /cvs/src/sys/ufs/ext2fs/ext2fs_extern.h,v
retrieving revision 1.5
diff -u -w -r1.5 ext2fs_extern.h
--- ufs/ext2fs/ext2fs_extern.h	1998/02/08 22:41:48	1.5
+++ ufs/ext2fs/ext2fs_extern.h	2000/02/01 22:56:17
@@ -110,11 +110,12 @@
 int ext2fs_statfs __P((struct mount *, struct statfs *, struct proc *));
 int ext2fs_sync __P((struct mount *, int, struct ucred *, struct proc *));
 int ext2fs_vget __P((struct mount *, ino_t, struct vnode **));
-int ext2fs_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
-			struct vnode **, int *, struct ucred **));
+int ext2fs_fhtovp __P((struct mount *, struct fid *, struct vnode **));
 int ext2fs_vptofh __P((struct vnode *, struct fid *));
 int ext2fs_sbupdate __P((struct ufsmount *, int));
 int ext2fs_cgupdate __P((struct ufsmount *, int));
+int ext2fs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
+		       struct proc *));
 
 /* ext2fs_readwrite.c */
 int ext2fs_read __P((void *));
Index: ufs/ext2fs/ext2fs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/ufs/ext2fs/ext2fs_vfsops.c,v
retrieving revision 1.10
diff -u -w -r1.10 ext2fs_vfsops.c
--- ufs/ext2fs/ext2fs_vfsops.c	1999/05/31 17:34:53	1.10
+++ ufs/ext2fs/ext2fs_vfsops.c	2000/02/01 22:56:21
@@ -67,8 +67,6 @@
 #include <ufs/ext2fs/ext2fs_extern.h>
 
 int ext2fs_sbupdate __P((struct ufsmount *, int));
-int ext2fs_check_export __P((struct mount *, struct ufid *, struct mbuf *,
-	struct vnode **, int *, struct ucred **));
 
 struct vfsops ext2fs_vfsops = {
 	ext2fs_mount,
@@ -82,58 +80,13 @@
 	ext2fs_fhtovp,
 	ext2fs_vptofh,
 	ext2fs_init,
+	ext2fs_sysctl,
+	ufs_check_export
 };
 
 extern u_long ext2gennumber;
 
 /*
- * This is the generic part of fhtovp called after the underlying
- * filesystem has validated the file handle.
- *
- * Verify that a host should have access to a filesystem, and if so
- * return a vnode for the presented file handle.
- */
-int
-ext2fs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)
-	register struct mount *mp;
-	struct ufid *ufhp;
-	struct mbuf *nam;
-	struct vnode **vpp;
-	int *exflagsp;
-	struct ucred **credanonp;
-{
-	register struct inode *ip;
-	register struct netcred *np;
-	register struct ufsmount *ump = VFSTOUFS(mp);
-	struct vnode *nvp;
-	int error;
-
-	/*
-	 * Get the export permission structure for this <mp, client> tuple.
-	 */
-	np = vfs_export_lookup(mp, &ump->um_export, nam);
-	if (np == NULL)
-		return (EACCES);
-
-	if ((error = VFS_VGET(mp, ufhp->ufid_ino, &nvp)) != 0) {
-		*vpp = NULLVP;
-		return (error);
-	}
-	ip = VTOI(nvp);
-	if (ip->i_e2fs_mode == 0 || ip->i_e2fs_dtime != 0 || 
-		ip->i_e2fs_gen != ufhp->ufid_gen) {
-		vput(nvp);
-		*vpp = NULLVP;
-		return (ESTALE);
-	}
-	*vpp = nvp;
-	*exflagsp = np->netc_exflags;
-	*credanonp = &np->netc_anon;
-	return (0);
-}   
-
-
-/*
  * Called by main() when ext2fs is going to be mounted as root.
  *
  * Name is updated by mount(8) after booting.
@@ -947,14 +900,14 @@
  *   those rights via. exflagsp and credanonp
  */
 int
-ext2fs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
+ext2fs_fhtovp(mp, fhp, vpp)
 	register struct mount *mp;
 	struct fid *fhp;
-	struct mbuf *nam;
 	struct vnode **vpp;
-	int *exflagsp;
-	struct ucred **credanonp;
 {
+	register struct inode *ip;
+	struct vnode *nvp;
+	int error;
 	register struct ufid *ufhp;
 	struct m_ext2fs *fs;
 
@@ -962,9 +915,22 @@
 	fs = VFSTOUFS(mp)->um_e2fs;
 	if ((ufhp->ufid_ino < EXT2_FIRSTINO && ufhp->ufid_ino != EXT2_ROOTINO) ||
 		ufhp->ufid_ino >= fs->e2fs_ncg * fs->e2fs.e2fs_ipg)
+		return (ESTALE);
+
+	if ((error = VFS_VGET(mp, ufhp->ufid_ino, &nvp)) != 0) {
+		*vpp = NULLVP;
+		return (error);
+	}
+	ip = VTOI(nvp);
+	if (ip->i_e2fs_mode == 0 || ip->i_e2fs_dtime != 0 || 
+		ip->i_e2fs_gen != ufhp->ufid_gen) {
+		vput(nvp);
+		*vpp = NULLVP;
 		return (ESTALE);
-	return (ext2fs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
 }
+	*vpp = nvp;
+	return (0);
+}
 
 /*
  * Vnode pointer to File handle
@@ -984,6 +950,23 @@
 	ufhp->ufid_ino = ip->i_number;
 	ufhp->ufid_gen = ip->i_e2fs_gen;
 	return (0);
+}
+
+/*
+ * no sysctl for ext2fs
+ */
+
+int
+ext2fs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
+	int *name;
+	u_int namelen;
+	void *oldp;
+	size_t *oldlenp;
+	void *newp;
+	size_t newlen;
+	struct proc *p;
+{
+	return (EOPNOTSUPP);
 }
 
 /*
Index: ufs/ffs/ffs_extern.h
===================================================================
RCS file: /cvs/src/sys/ufs/ffs/ffs_extern.h,v
retrieving revision 1.8
diff -u -w -r1.8 ffs_extern.h
--- ufs/ffs/ffs_extern.h	1999/12/05 08:30:38	1.8
+++ ufs/ffs/ffs_extern.h	2000/02/01 22:56:21
@@ -115,8 +115,7 @@
 int ffs_statfs __P((struct mount *, struct statfs *, struct proc *));
 int ffs_sync __P((struct mount *, int, struct ucred *, struct proc *));
 int ffs_vget __P((struct mount *, ino_t, struct vnode **));
-int ffs_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
-		    struct vnode **, int *, struct ucred **));
+int ffs_fhtovp __P((struct mount *, struct fid *, struct vnode **));
 int ffs_vptofh __P((struct vnode *, struct fid *));
 int ffs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
 		    struct proc *));
Index: ufs/ffs/ffs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.27
diff -u -w -r1.27 ffs_vfsops.c
--- ufs/ffs/ffs_vfsops.c	2000/01/14 19:17:56	1.27
+++ ufs/ffs/ffs_vfsops.c	2000/02/01 22:56:29
@@ -80,7 +80,8 @@
 	ffs_fhtovp,
 	ffs_vptofh,
 	ffs_init,
-	ffs_sysctl
+	ffs_sysctl,
+	ufs_check_export
 };
 
 extern u_long nextgennumber;
@@ -1083,17 +1084,12 @@
  * - check that the inode number is valid
  * - call ffs_vget() to get the locked inode
  * - check for an unallocated inode (i_mode == 0)
- * - check that the given client host has export rights and return
- *   those rights via. exflagsp and credanonp
  */
 int
-ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
+ffs_fhtovp(mp, fhp, vpp)
 	register struct mount *mp;
 	struct fid *fhp;
-	struct mbuf *nam;
 	struct vnode **vpp;
-	int *exflagsp;
-	struct ucred **credanonp;
 {
 	register struct ufid *ufhp;
 	struct fs *fs;
@@ -1103,7 +1099,7 @@
 	if (ufhp->ufid_ino < ROOTINO ||
 	    ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
 		return (ESTALE);
-	return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
+	return (ufs_fhtovp(mp, ufhp, vpp));
 }
 
 /*
Index: ufs/lfs/lfs_extern.h
===================================================================
RCS file: /cvs/src/sys/ufs/lfs/lfs_extern.h,v
retrieving revision 1.4
diff -u -w -r1.4 lfs_extern.h
--- ufs/lfs/lfs_extern.h	1998/02/08 22:41:51	1.4
+++ ufs/lfs/lfs_extern.h	2000/02/01 22:56:29
@@ -119,9 +119,10 @@
 int lfs_statfs __P((struct mount *, struct statfs *, struct proc *));
 int lfs_sync __P((struct mount *, int, struct ucred *, struct proc *));
 int lfs_vget __P((struct mount *, ino_t, struct vnode **));
-int lfs_fhtovp __P((struct mount *, struct fid *, struct mbuf *, struct vnode **, int *, struct ucred **));
+int lfs_fhtovp __P((struct mount *, struct fid *, struct vnode **));
 int lfs_vptofh __P((struct vnode *, struct fid *));
-
+int lfs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
+		    struct proc *));
 
 int lfs_valloc		__P((void *));
 int lfs_vfree		__P((void *));
Index: ufs/lfs/lfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/ufs/lfs/lfs_vfsops.c,v
retrieving revision 1.11
diff -u -w -r1.11 lfs_vfsops.c
--- ufs/lfs/lfs_vfsops.c	1999/05/31 17:34:55	1.11
+++ ufs/lfs/lfs_vfsops.c	2000/02/01 22:56:31
@@ -76,6 +76,8 @@
 	lfs_fhtovp,
 	lfs_vptofh,
 	lfs_init,
+	lfs_sysctl,
+	ufs_check_export
 };
 
 int
@@ -567,8 +569,6 @@
  * - check that the inode number is valid
  * - call lfs_vget() to get the locked inode
  * - check for an unallocated inode (i_mode == 0)
- * - check that the given client host has export rights and return
- *   those rights via. exflagsp and credanonp
  *
  * XXX
  * use ifile to see if inode is allocated instead of reading off disk
@@ -576,20 +576,17 @@
  * generational number.
  */
 int
-lfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
+lfs_fhtovp(mp, fhp, vpp)
 	register struct mount *mp;
 	struct fid *fhp;
-	struct mbuf *nam;
 	struct vnode **vpp;
-	int *exflagsp;
-	struct ucred **credanonp;
 {
 	register struct ufid *ufhp;
 
 	ufhp = (struct ufid *)fhp;
 	if (ufhp->ufid_ino < ROOTINO)
 		return (ESTALE);
-	return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
+	return (ufs_fhtovp(mp, ufhp, nam, vpp, exflagsp, credanonp));
 }
 
 /*
@@ -619,4 +616,21 @@
 lfs_init()
 {
 	ufs_init();
+}
+
+/*
+ * no sysctl for lfs
+ */
+
+int
+lfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
+	int *name;
+	u_int namelen;
+	void *oldp;
+	size_t *oldlenp;
+	void *newp;
+	size_t newlen;
+	struct proc *p;
+{
+	return (EOPNOTSUPP);
 }
Index: ufs/mfs/mfs_extern.h
===================================================================
RCS file: /cvs/src/sys/ufs/mfs/mfs_extern.h,v
retrieving revision 1.7
diff -u -w -r1.7 mfs_extern.h
--- ufs/mfs/mfs_extern.h	1998/08/06 19:35:09	1.7
+++ ufs/mfs/mfs_extern.h	2000/02/01 22:56:33
@@ -44,6 +44,7 @@
 struct ucred;
 struct vnode;
 struct vfsconf;
+struct mbuf;
 
 __BEGIN_DECLS
 /* mfs_vfsops.c */
@@ -55,6 +56,8 @@
 int	mfs_statfs	__P((struct mount *, struct statfs *, struct proc *));
 
 int	mfs_init	__P((struct vfsconf *));
+int	mfs_checkexp	__P((struct mount *mp, struct mbuf *nam,
+			     int *extflagsp, struct ucred **credanonp));
 
 /* mfs_vnops.c */
 int	mfs_open	__P((void *));
Index: ufs/mfs/mfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/ufs/mfs/mfs_vfsops.c,v
retrieving revision 1.11
diff -u -w -r1.11 mfs_vfsops.c
--- ufs/mfs/mfs_vfsops.c	1999/12/06 07:28:06	1.11
+++ ufs/mfs/mfs_vfsops.c	2000/02/01 22:56:36
@@ -81,7 +81,8 @@
 	ffs_fhtovp,
 	ffs_vptofh,
 	mfs_init,
-	ffs_sysctl
+	ffs_sysctl,
+	mfs_checkexp
 };
 
 /*
@@ -298,4 +299,18 @@
 		bcopy(&mp->mnt_stat.mount_info.mfs_args,
 		    &sbp->mount_info.mfs_args, sizeof(struct mfs_args));
 	return (error);
+}
+
+/*
+ * check export permission, not supported
+ */
+/* ARGUSED */
+int
+mfs_checkexp(mp, nam, exflagsp, credanonp)
+	register struct mount *mp;
+	struct mbuf *nam;
+	int *exflagsp;
+	struct ucred **credanonp;
+{
+	return (EOPNOTSUPP);
 }
Index: ufs/ufs/ufs_extern.h
===================================================================
RCS file: /cvs/src/sys/ufs/ufs/ufs_extern.h,v
retrieving revision 1.8
diff -u -w -r1.8 ufs_extern.h
--- ufs/ufs/ufs_extern.h	1998/08/06 19:35:13	1.8
+++ ufs/ufs/ufs_extern.h	2000/02/01 22:56:37
@@ -158,8 +158,9 @@
 int ufs_start __P((struct mount *, int, struct proc *));
 int ufs_root __P((struct mount *, struct vnode **));
 int ufs_quotactl __P((struct mount *, int, uid_t, caddr_t, struct proc *));
-int ufs_check_export __P((struct mount *, struct ufid *, struct mbuf *,
-			  struct vnode **, int *, struct ucred **));
+int ufs_fhtovp __P((struct mount *, struct ufid *, struct vnode **));
+int ufs_check_export __P((struct mount *, struct mbuf *, int *,
+		struct ucred **));
 
 /* ufs_vnops.c */
 int ufs_vinit __P((struct mount *, int (**) __P((void *)),
Index: ufs/ufs/ufs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/ufs/ufs/ufs_vfsops.c,v
retrieving revision 1.6
diff -u -w -r1.6 ufs_vfsops.c
--- ufs/ufs/ufs_vfsops.c	1997/11/06 05:59:28	1.6
+++ ufs/ufs/ufs_vfsops.c	2000/02/01 22:56:40
@@ -167,6 +167,32 @@
 
 
 /*
+ * Verify a remote client has export rights and return these rights via.
+ * exflagsp and credanonp.
+ */
+int
+ufs_check_export(mp, nam, exflagsp, credanonp)
+	register struct mount *mp;
+	struct mbuf *nam;
+	int *exflagsp;
+	struct ucred **credanonp;
+{
+	register struct netcred *np;
+	register struct ufsmount *ump = VFSTOUFS(mp);
+
+	/*
+	 * Get the export permission structure for this <mp, client> tuple.
+	 */
+	np = vfs_export_lookup(mp, &ump->um_export, nam);
+	if (np == NULL)
+		return (EACCES);
+
+	*exflagsp = np->netc_exflags;
+	*credanonp = &np->netc_anon;
+	return (0);
+}
+
+/*
  * Initial UFS filesystems, done only once.
  */
 int
@@ -188,32 +214,17 @@
 /*
  * This is the generic part of fhtovp called after the underlying
  * filesystem has validated the file handle.
- *
- * Verify that a host should have access to a filesystem, and if so
- * return a vnode for the presented file handle.
  */
 int
-ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)
+ufs_fhtovp(mp, ufhp, vpp)
 	register struct mount *mp;
 	struct ufid *ufhp;
-	struct mbuf *nam;
 	struct vnode **vpp;
-	int *exflagsp;
-	struct ucred **credanonp;
 {
 	register struct inode *ip;
-	register struct netcred *np;
-	register struct ufsmount *ump = VFSTOUFS(mp);
 	struct vnode *nvp;
 	int error;
 
-	/*
-	 * Get the export permission structure for this <mp, client> tuple.
-	 */
-	np = vfs_export_lookup(mp, &ump->um_export, nam);
-	if (np == NULL)
-		return (EACCES);
-
 	if ((error = VFS_VGET(mp, ufhp->ufid_ino, &nvp)) != 0) {
 		*vpp = NULLVP;
 		return (error);
@@ -225,7 +236,5 @@
 		return (ESTALE);
 	}
 	*vpp = nvp;
-	*exflagsp = np->netc_exflags;
-	*credanonp = &np->netc_anon;
 	return (0);
 }
Index: xfs/xfs_vfsops-bsd.c
===================================================================
RCS file: /cvs/src/sys/xfs/xfs_vfsops-bsd.c,v
retrieving revision 1.2
diff -u -w -r1.2 xfs_vfsops-bsd.c
--- xfs/xfs_vfsops-bsd.c	2000/02/01 04:12:19	1.2
+++ xfs/xfs_vfsops-bsd.c	2000/02/01 22:56:43
@@ -126,10 +126,7 @@
 int
 xfs_fhtovp(struct mount * mp,
 	   struct fid * fhp,
-	   struct mbuf * nam,
-	   struct vnode ** vpp,
-	   int *exflagsp,
-	   struct ucred ** credanonp)
+	   struct vnode ** vpp)
 {
 #ifdef ARLA_KNFS
     static struct ucred fhtovpcred;
@@ -187,12 +184,6 @@
 	fhtovpcred.cr_ngroups = 0;
       
 	*vpp = vp;
-#ifdef MNT_EXPUBLIC
-	*exflagsp = MNT_EXPUBLIC;
-#else
-	*exflagsp = 0;
-#endif
-	*credanonp = &fhtovpcred;
 
 	XFSDEB(XDEBVFOPS, ("xfs_fhtovp done\n"));
 
Index: xfs/xfs_vfsops-bsd.h
===================================================================
RCS file: /cvs/src/sys/xfs/xfs_vfsops-bsd.h,v
retrieving revision 1.1
diff -u -w -r1.1 xfs_vfsops-bsd.h
--- xfs/xfs_vfsops-bsd.h	1999/04/30 01:59:01	1.1
+++ xfs/xfs_vfsops-bsd.h	2000/02/01 22:56:44
@@ -74,10 +74,7 @@
 int
 xfs_fhtovp(struct mount * mp,
 	   struct fid * fhp,
-	   struct mbuf * nam,
-	   struct vnode ** vpp,
-	   int *exflagsp,
-	   struct ucred ** credanonp);
+	   struct vnode ** vpp);
 
 int
 xfs_vptofh(struct vnode * vp,
Index: xfs/xfs_vfsops-openbsd.c
===================================================================
RCS file: /cvs/src/sys/xfs/xfs_vfsops-openbsd.c,v
retrieving revision 1.1
diff -u -w -r1.1 xfs_vfsops-openbsd.c
--- xfs/xfs_vfsops-openbsd.c	1999/04/30 01:59:01	1.1
+++ xfs/xfs_vfsops-openbsd.c	2000/02/01 22:56:44
@@ -81,6 +81,22 @@
     return 0;
 }
 
+static int
+xfs_sysctl (int *name, u_int namelen, void *oldp, size_t *oldlenp,
+	    void *newp, size_t newlen, struct proc *p)
+{
+    XFSDEB(XDEBVFOPS, ("xfs_sysctl\n"));
+    return EOPNOTSUPP;
+}
+
+static int
+xfs_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp,
+	     struct ucred **credanonp)
+{
+    XFSDEB(XDEBVFOPS, ("xfs_checkexp\n"));
+    return (EOPNOTSUPP);
+}
+
 struct vfsops xfs_vfsops = {
     xfs_mount,
     xfs_start,
@@ -93,7 +109,8 @@
     xfs_fhtovp,
     xfs_vptofh,
     xfs_init,
-    NULL,
+    xfs_sysctl,
+    xfs_checkexp
 };
 
 static struct vfsconf xfs_vfc = {