PERFORCE change 178885 for review

Efstratios Karatzas gpf at FreeBSD.org
Thu May 27 14:41:58 UTC 2010


http://p4web.freebsd.org/@@178885?ac=10

Change 178885 by gpf at gpf_desktop on 2010/05/27 14:41:11

	- removed some debuging printf()s
	
	- moved vn_fullpath_nocache(9) to sys/kern/vfs_cache.c.
	This is the temporary home, till and if I find a more suitable one.
	From now on, this file should be looked up for the latest version 
	of the KPI, not the LKM that I uploaded a few weeks ago.
	
	- What is stored inside the filehandle is fs specific. Therefore, I 
	thought a VFS op would be the best way to extract the parent "hint".
	Introduced VFS_FHHINT() that does this job for us. I made sure that 
	a default implementation for this vfs op is available, and that every 
	filesystem that uses VFS_FHTOVP() would also have this new VFS op mapped 
	to the default implementation in sys/kern/vfs_default.c so that we won't
	kernel-panic when some fs other than UFS tries to dereference the mp
	for that operation. For now, only UFS really needs it.
	
	- A problem of old got solved. In my NFS test, during the first few operations 
	after a new file was created, vn_fullpath(9) was unable to acquire a 
	path. This problem was with both UFS & ZFS.
	
	Now, I've added a call to vn_fullpath_nocache() inside nfs server code for the
	write operation and it works just fine; we are able to acquire paths when we 
	do something like "echo message > new_file". 
	In the next few hours, I'll alter all 
	all of nfs server code so that every time that the cache fails us, this 
	KPI will be used instead as a last resort.
	
	- fixed/added some KASSERTS here and there.

Affected files ...

.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c#3 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/cd9660/cd9660_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/ext2fs/ext2_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/hpfs/hpfs_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/msdosfs/msdosfs_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/ntfs/ntfs_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/nullfs/null_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/tmpfs/tmpfs_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/udf/udf_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/unionfs/union_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/gnu/fs/reiserfs/reiserfs_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/gnu/fs/xfs/FreeBSD/xfs_mountops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/kern/vfs_cache.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/kern/vfs_default.c#3 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/nfsserver/nfs_serv.c#9 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/sys/mount.h#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/sys/vnode.h#3 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/ufs/ffs/ffs_vfsops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/ufs/ffs/ffs_vnops.c#4 edit

Differences ...

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c#2 (text+ko) ====

@@ -112,6 +112,7 @@
 	.vfs_sync =		zfs_sync,
 	.vfs_checkexp =		zfs_checkexp,
 	.vfs_fhtovp =		zfs_fhtovp,
+	.vfs_fhhint =		vfs_stdfhhint,
 };
 
 VFS_SET(zfs_vfsops, zfs, VFCF_JAIL | VFCF_DELEGADMIN);

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c#3 (text+ko) ====

@@ -3772,13 +3772,7 @@
 
 	ZFS_ENTER(zfsvfs);
 	ZFS_VERIFY_ZP(zp);
-	gen = (uint32_t)zp->z_gen;
-	
-	printf("EIMAI H VOP_VPTOFH TOU KWLOZFS\n");
-	printf("ID %llu\n", zp->z_id);
-	printf("PARENT ID %llu\n", zp->z_phys->zp_parent);
-	/* gpf shit */
-	
+	gen = (uint32_t)zp->z_gen;	
 
 	size = (zfsvfs->z_parent != zfsvfs) ? LONG_FID_LEN : SHORT_FID_LEN;
 	fidp->fid_len = size;
@@ -5016,6 +5010,10 @@
 	struct vnode *dvp;
 	int error;
 	
+	KASSERT(ap->a_vp != NULL, ("VOP_GEPARENT: null vp"));
+	if (ap->a_flags & WANTPARENT)
+		KASSERT(ap->a_buf != NULL, ("VOP_GEPARENT: null buffer"));
+
 	zp = VTOZ(ap->a_vp);
 	mp = ap->a_vp->v_mount;
 	dvp = NULL;
@@ -5030,6 +5028,7 @@
 		error = ENOENT;
 		goto out;
 	}
+	/* scan the directory for a matching dirent */
 	else if (ap->a_flags & WANTNAME) {
 		struct uio io;
 		struct iovec iov;
@@ -5108,7 +5107,7 @@
 	if (error == 0 && dvp != NULL) {
 		*(ap->a_vpp) = dvp;
 	}
-	else if (error) {
+	else {
 		*(ap->a_vpp) = NULL;
 	}
 	

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/cd9660/cd9660_vfsops.c#2 (text+ko) ====

@@ -84,6 +84,7 @@
 	.vfs_statfs =		cd9660_statfs,
 	.vfs_unmount =		cd9660_unmount,
 	.vfs_vget =		cd9660_vget,
+	.vfs_fhhint =		vfs_stdfhhint,
 };
 VFS_SET(cd9660_vfsops, cd9660, VFCF_READONLY);
 MODULE_VERSION(cd9660, 1);

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/ext2fs/ext2_vfsops.c#2 (text+ko) ====

@@ -86,6 +86,7 @@
 	.vfs_sync =		ext2_sync,
 	.vfs_unmount =		ext2_unmount,
 	.vfs_vget =		ext2_vget,
+	.vfs_fhhint =		vfs_stdfhhint,
 };
 
 VFS_SET(ext2fs_vfsops, ext2fs, 0);

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/hpfs/hpfs_vfsops.c#2 (text+ko) ====

@@ -538,5 +538,6 @@
 	.vfs_statfs =		hpfs_statfs,
 	.vfs_unmount =		hpfs_unmount,
 	.vfs_vget =		hpfs_vget,
+	.vfs_fhhint =		vfs_stdfhhint,
 };
 VFS_SET(hpfs_vfsops, hpfs, 0);

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/msdosfs/msdosfs_vfsops.c#2 (text+ko) ====

@@ -986,6 +986,7 @@
 	.vfs_statfs =		msdosfs_statfs,
 	.vfs_sync =		msdosfs_sync,
 	.vfs_unmount =		msdosfs_unmount,
+	.vfs_fhhint =		vfs_stdfhhint,
 };
 
 VFS_SET(msdosfs_vfsops, msdosfs, 0);

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/ntfs/ntfs_vfsops.c#2 (text+ko) ====

@@ -787,6 +787,7 @@
 	.vfs_uninit =	ntfs_uninit,
 	.vfs_unmount =	ntfs_unmount,
 	.vfs_vget =	ntfs_vget,
+	.vfs_fhhint =	vfs_stdfhhint,
 };
 VFS_SET(ntfs_vfsops, ntfs, 0);
 MODULE_VERSION(ntfs, 1);

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/nullfs/null_vfsops.c#2 (text+ko) ====

@@ -359,6 +359,7 @@
 	.vfs_uninit =		nullfs_uninit,
 	.vfs_unmount =		nullfs_unmount,
 	.vfs_vget =		nullfs_vget,
+	.vfs_fhhint =		vfs_stdfhhint,
 };
 
 VFS_SET(null_vfsops, nullfs, VFCF_LOOPBACK);

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/tmpfs/tmpfs_vfsops.c#2 (text+ko) ====

@@ -414,5 +414,6 @@
 	.vfs_root =			tmpfs_root,
 	.vfs_statfs =			tmpfs_statfs,
 	.vfs_fhtovp =			tmpfs_fhtovp,
+	.vfs_fhhint =			vfs_stdfhhint,
 };
 VFS_SET(tmpfs_vfsops, tmpfs, 0);

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/udf/udf_vfsops.c#2 (text+ko) ====

@@ -129,6 +129,7 @@
 	.vfs_uninit =		udf_uninit,
 	.vfs_unmount =		udf_unmount,
 	.vfs_vget =		udf_vget,
+	.vfs_fhhint =		vfs_stdfhhint,
 };
 VFS_SET(udf_vfsops, udf, VFCF_READONLY);
 

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/unionfs/union_vfsops.c#2 (text+ko) ====

@@ -519,6 +519,7 @@
 	.vfs_uninit =		unionfs_uninit,
 	.vfs_unmount =		unionfs_unmount,
 	.vfs_vget =		unionfs_vget,
+	.vfs_fhhint =		vfs_stdfhhint,
 };
 
 VFS_SET(unionfs_vfsops, unionfs, VFCF_LOOPBACK);

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/gnu/fs/reiserfs/reiserfs_vfsops.c#2 (text+ko) ====

@@ -1114,6 +1114,7 @@
 	//.vfs_checkexp	= reiserfs_checkexp,
 	//.vfs_extattrctl = reiserfs_extattrctl,
 	.vfs_fhtovp	= reiserfs_fhtovp,
+	.vfs_fhhint 	= vfs_stdfhhint,
 	//.vfs_quotactl	= reiserfs_quotactl,
 	.vfs_root	= reiserfs_root,
 	//.vfs_start	= reiserfs_start,

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/gnu/fs/xfs/FreeBSD/xfs_mountops.c#2 (text+ko) ====

@@ -419,6 +419,7 @@
 	.vfs_init =	_xfs_init,
 	.vfs_uninit =	_xfs_uninit,
 	.vfs_extattrctl = _xfs_extattrctl,
+	.vfs_fhhint =	vfs_stdfhhint,
 };
 
 VFS_SET(xfs_fsops, xfs, 0);

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/kern/vfs_cache.c#2 (text+ko) ====

@@ -1226,3 +1226,151 @@
 	buf[l] = '\0';
 	return (0);
 }
+
+/*
+ * vn_fullpath_nocache
+ * 
+ * Retrieve the full filesystem path that corresponds to a vnode without use of the 
+ * name cache.
+ * - A directory hint (UFS file_id of the directory that contains the vnode) may be 
+ *   supplied to facilitate the search if our target is not a directory itself.
+ * - flags should be set to PARENT_HINT, if the directory hint is supplied
+ *   and to EXHAUSTIVE_SEARCH, if we are willing to go intro great trouble to get this path.
+ * 
+ * Locks: no locks required.
+ * 
+ * Author's note: This only works for UFS filesystems (for now).
+ * Oh, also EXHAUSTIVE_SEARCH will kernel panic :-D
+ */
+int
+vn_fullpath_nocache(struct vnode *vp, char **fullpath, char **freepath, uint64_t directory_hint, char flags)
+{	
+	struct vnode *dvp, *upper_dvp;
+	struct mount *mp;
+	struct thread * td;
+	char *buf, *pch;
+	char fname[MNAMELEN];
+	int error, buflen, vfslocked, fnamelen;
+
+	KASSERT(vp != NULL, ("vn_fullpath_nocache: null vp"));
+	
+	dvp = NULL;
+	buf = NULL;
+	*freepath = NULL;
+	
+	if (vp->v_type == VBAD) {
+		error = ENOENT;
+		goto out;
+	}
+	
+	vref(vp);
+	error = 0;
+	td = curthread;
+	mp = vp->v_mount;
+	fnamelen = sizeof(fname);
+	buf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+	buflen = MAXPATHLEN - 1;
+	buf[MAXPATHLEN-1] = '\0';
+	
+	/*
+	 * - If our target is a directory, move on to the part where we traverse the '..' entries.
+	 * - If not, try to find its' parent through VOP_GETPARENT
+	 */
+	if (vp->v_type != VDIR) {
+		/* XXXgpf: perhaps locking vp is redundant */
+		vn_lock(vp, LK_SHARED);
+		error = VOP_GETPARENT(vp, &dvp, directory_hint, flags, fname, &fnamelen);
+		VOP_UNLOCK(vp, 0);
+		if (error) {
+			dvp = NULL;
+			goto out;
+		}
+
+		/* we have found a parent directory and a name for our vnode, save the name */
+		pch = buf + buflen - strlen(fname);
+		if (pch < buf) {
+			error = EOVERFLOW;
+			if (dvp != NULL)
+				vput(dvp);
+			goto out;
+		}
+		strcpy(pch, fname);
+		buflen -= strlen(fname);
+		buf[--buflen] = '/';		
+	}
+	/* if our target is a dir, do the initial preparation */
+	else {
+		dvp = vp;
+		vref(dvp);
+		vn_lock(dvp, LK_SHARED);
+	}
+	
+	/*
+	 * We have found 'a' directory that contains our target or our target is a directory.
+	 * In any case, just traverse the '..' nodes and construct a path via VOP_VPTOCNP(9)
+	 */
+	while (dvp != rootvnode) {
+		/*
+		 * If we've found a vnode that is the root of a filesystem
+		 * Use the path that the filesystem was mounted on to complete our fullpath
+		 * 
+		 * XXXgpf: how safe is it to use the path from the statistics of a mounted fs? 
+		 * the size of the f_mntonname field seems kinda small :-S
+		 */
+		if ((dvp->v_vflag & VV_ROOT) != 0) {
+			char *pch, *fs_path;
+			int fs_path_len;
+			
+			vfslocked = VFS_LOCK_GIANT(dvp->v_mount);
+
+			*fullpath = buf + buflen;
+			
+			fs_path = dvp->v_mount->mnt_stat.f_mntonname;
+			fs_path_len = strlen(fs_path);
+			
+			if (buflen - fs_path_len - 1 < 0) {
+				vput(dvp);
+				error = EOVERFLOW;
+				VFS_UNLOCK_GIANT(vfslocked);
+				goto out;
+			}
+			
+			pch = buf + buflen - fs_path_len;
+			memcpy(pch, fs_path, fs_path_len);
+			buflen -= fs_path_len;
+			
+			VFS_UNLOCK_GIANT(vfslocked);
+			
+			break;
+		}
+		
+		error = VOP_VPTOCNP(dvp, &upper_dvp, td->td_ucred, buf, &buflen);
+		if (error) {
+			uprintf("VOP_VPTOCNP failure %d\n", error);
+			break;
+		}
+
+		buf[--buflen] = '/';		
+		if (dvp != NULL) 
+			vput(dvp);
+		
+		vdrop(upper_dvp);
+		dvp = upper_dvp;
+		vn_lock(dvp, LK_SHARED);
+		vref(dvp);
+	} /* while */
+
+	vput(dvp);	
+	*fullpath = buf + buflen;
+	*freepath = buf;
+
+out:
+	if (error != 0) {
+		*freepath = NULL;
+		if (buf != NULL)
+			free(buf, M_TEMP);
+	}	
+	vrele(vp);
+		
+	return error;
+}

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/kern/vfs_default.c#3 (text+ko) ====

@@ -955,6 +955,12 @@
 }
 
 int
+vfs_stdfhhint (struct mount *mp, struct fid *fhp, uint64_t *hint)
+{
+	return (EOPNOTSUPP);
+}
+
+int
 vfs_stdinit (vfsp)
 	struct vfsconf *vfsp;
 {

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/nfsserver/nfs_serv.c#9 (text+ko) ====

@@ -101,6 +101,14 @@
 #include <nfs/xdr_subs.h>
 #include <nfsserver/nfsm_subs.h>
 
+/* 
+ * XXXgpf: should relocate them someplace else
+ * I just dont know where:S 
+ */
+#define PARENTHINT 0x0001
+#define EXHAUSTSEARCH 0x0002
+#define WANTNAME 0x0004
+
 #ifdef NFSRV_DEBUG
 #define nfsdbprintf(info)	printf info
 #else
@@ -1390,6 +1398,22 @@
 				AUDIT_ARG_UPATH1(td, fullpath);
 				free(freepath, M_TEMP);
 			}
+			/* if our cache fails us */
+			else if (fhp != NULL) {
+				uint64_t parent_hint;
+				printf("going for hint\n");
+				/* get the hint stored inside the file handle */
+				VFS_FHHINT(mntp, &(fhp->fh_fid), &parent_hint);
+				printf("got hint, going to cache\n");
+				vn_fullpath_nocache(new_vp, &fullpath, &freepath,
+					parent_hint, PARENTHINT | WANTNAME);
+				printf("got cache %p\n", freepath);
+				if (freepath != NULL) {
+					AUDIT_ARG_UPATH1(td, fullpath);
+					free(freepath, M_TEMP);
+				}
+				printf("all done!\n");
+			}
 		}
 	}
 	

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/sys/mount.h#2 (text+ko) ====

@@ -567,6 +567,7 @@
 typedef	int vfs_vget_t(struct mount *mp, ino_t ino, int flags,
 		    struct vnode **vpp);
 typedef	int vfs_fhtovp_t(struct mount *mp, struct fid *fhp, struct vnode **vpp);
+typedef	int vfs_fhhint_t(struct mount *mp, struct fid *fhp, uint64_t *hint);
 typedef	int vfs_checkexp_t(struct mount *mp, struct sockaddr *nam,
 		    int *extflagsp, struct ucred **credanonp,
 		    int *numsecflavors, int **secflavors);
@@ -590,6 +591,7 @@
 	vfs_sync_t		*vfs_sync;
 	vfs_vget_t		*vfs_vget;
 	vfs_fhtovp_t		*vfs_fhtovp;
+	vfs_fhhint_t		*vfs_fhhint;
 	vfs_checkexp_t		*vfs_checkexp;
 	vfs_init_t		*vfs_init;
 	vfs_uninit_t		*vfs_uninit;
@@ -612,6 +614,8 @@
 	(*(MP)->mnt_op->vfs_vget)(MP, INO, FLAGS, VPP)
 #define VFS_FHTOVP(MP, FIDP, VPP) \
 	(*(MP)->mnt_op->vfs_fhtovp)(MP, FIDP, VPP)
+#define VFS_FHHINT(MP, FIDP, HINT) \
+	(*(MP)->mnt_op->vfs_fhhint)(MP, FIDP, HINT)
 #define VFS_CHECKEXP(MP, NAM, EXFLG, CRED, NUMSEC, SEC)	\
 	(*(MP)->mnt_op->vfs_checkexp)(MP, NAM, EXFLG, CRED, NUMSEC, SEC)
 #define	VFS_EXTATTRCTL(MP, C, FN, NS, N)				\
@@ -763,6 +767,7 @@
 vfs_sync_t		vfs_stdnosync;
 vfs_vget_t		vfs_stdvget;
 vfs_fhtovp_t		vfs_stdfhtovp;
+vfs_fhhint_t		vfs_stdfhhint;
 vfs_checkexp_t		vfs_stdcheckexp;
 vfs_init_t		vfs_stdinit;
 vfs_uninit_t		vfs_stduninit;

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/sys/vnode.h#3 (text+ko) ====

@@ -609,6 +609,8 @@
 	    char **retbuf, char **freebuf);
 int	vn_fullpath_global(struct thread *td, struct vnode *vn,
 	    char **retbuf, char **freebuf);
+int	vn_fullpath_nocache(struct vnode *vp, char **fullpath, 
+	    char **freepath, uint64_t directory_hint, char flags);
 int	vn_commname(struct vnode *vn, char *buf, u_int buflen);
 int	vaccess(enum vtype type, mode_t file_mode, uid_t file_uid,
 	    gid_t file_gid, accmode_t accmode, struct ucred *cred,

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/ufs/ffs/ffs_vfsops.c#2 (text+ko) ====

@@ -88,11 +88,13 @@
 static vfs_mount_t ffs_mount;
 static vfs_statfs_t ffs_statfs;
 static vfs_fhtovp_t ffs_fhtovp;
+static vfs_fhhint_t ffs_fhhint;
 static vfs_sync_t ffs_sync;
 
 static struct vfsops ufs_vfsops = {
 	.vfs_extattrctl =	ffs_extattrctl,
 	.vfs_fhtovp =		ffs_fhtovp,
+	.vfs_fhhint =		ffs_fhhint,
 	.vfs_init =		ffs_init,
 	.vfs_mount =		ffs_mount,
 	.vfs_cmount =		ffs_cmount,
@@ -1631,6 +1633,19 @@
 }
 
 /*
+ * Get Parent Directory Hint from the File Handle
+ */
+static int
+ffs_fhhint(struct mount *mp, struct fid *fhp, uint64_t *hint)
+{
+	struct ufid *ufhp;
+
+	ufhp = (struct ufid *)fhp;
+	*hint = ufhp->ufid_dino;	
+	return (0);
+}
+
+/*
  * Initialize the filesystem.
  */
 static int

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/ufs/ffs/ffs_vnops.c#4 (text+ko) ====

@@ -1933,13 +1933,16 @@
 {
 	struct mount *mp;
 	struct vnode *vp, *dvp;
-	int error, flags;
+	int error, flags;	
 	
 	error = 0;
 	vp = ap->a_vp;
 	mp = vp->v_mount;
 	flags = ap->a_flags;
 
+	KASSERT(vp != NULL, ("VOP_GEPARENT: null vp"));
+	if (flags & WANTNAME)
+		KASSERT(ap->a_buf != NULL, ("VOP_GEPARENT: null buffer"));
 	/* XXXgpf:is this check necessary? */
 	if (vp->v_type == VBAD) {
 		error = ENOENT;
@@ -2011,7 +2014,7 @@
 	if (error == 0 && dvp != NULL) {
 		*(ap->a_vpp) = dvp;
 	}
-	else if (error) {
+	else {
 		*(ap->a_vpp) = NULL;
 	}
 


More information about the p4-projects mailing list