Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 May 2010 21:06:26 GMT
From:      Efstratios Karatzas <gpf@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 178836 for review
Message-ID:  <201005262106.o4QL6QvV019237@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@178836?ac=10

Change 178836 by gpf@gpf_desktop on 2010/05/26 21:05:34

	- changed how vn_fullpath_nocache(9) works internally.
	       now the fs specific part whose job is to find a parent directory
	       for our file has broken off to its own VOP(), VOP_GETPARENT.
	       VOP_GETPARENT works for UFS & ZFS.
	Please refer to the comment headers above the functions in question 
	for more information on how to use them.
	
	UFS: use directory inode hint or do an exhaustive search.
	(exhaustive search still kernel panics)
	
	ZFS: use the directory znode number that is stored inside the physical 
	part of the znode.
	note: there are other ways we could do this such as 
	zfs_obj_to_path() but there's no documentation to be found and my 
	zfs magic is limited for the time being.
	
	Still, vn_fullpath_nocache() performs well under UFS & ZFS - any 
	feedback welcome.
	
	- oh and removed a trailing white space in praudit.c

Affected files ...

.. //depot/projects/soc2010/gpf_audit/freebsd/src/contrib/openbsm/bin/praudit/praudit.c#3 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/kern/vfs_default.c#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/kern/vnode_if.src#3 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/sys/vnode.h#2 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/ufs/ffs/ffs_vnops.c#3 edit
.. //depot/projects/soc2010/gpf_audit/vn_fullpath_nocache.c#4 edit

Differences ...

==== //depot/projects/soc2010/gpf_audit/freebsd/src/contrib/openbsm/bin/praudit/praudit.c#3 (text) ====

@@ -152,7 +152,7 @@
 
 		case 'x':
 			xml = 1;
-			break;	
+			break;
 
 		case '?':
 		default:

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

@@ -40,6 +40,7 @@
 #include <sys/uio.h>
 #include <sys/atomic.h>
 #include <sys/namei.h>
+#include <sys/dirent.h>
 #include <sys/mman.h>
 #include <sys/cmn_err.h>
 #include <sys/errno.h>
@@ -3772,6 +3773,12 @@
 	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 */
+	
 
 	size = (zfsvfs->z_parent != zfsvfs) ? LONG_FID_LEN : SHORT_FID_LEN;
 	fidp->fid_len = size;
@@ -4963,6 +4970,151 @@
 	return (EOPNOTSUPP);
 }
 
+/* 
+ * XXXgpf: should relocate them someplace else
+ * I just dont know where:S 
+ */
+#define PARENTHINT 0x0001
+#define EXHAUSTSEARCH 0x0002
+#define WANTNAME 0x0004
+
+/*
+ * VOP_GETPARENT
+ * 
+ * int VOP_GETPARENT(struct vnode *vp, struct vnode **dvp, uint64_t hint, 
+ * 	int flags, char *buf, int *buflen);
+ * 
+ * Find a parent directory -dvp- with vp as a child. The parent hint is used to 
+ * facilitate the search.
+ * 
+ * Flags should be set to:
+ * 	- PARENTHIT: if a hint ino_t of a directory is supplied to facilitate the search
+ * 	- EXHAUSTSEARCH: if we are willing to search the whole filesystem to find the directory
+ * 	- WANTNAME: if we want to copy the name used to reference the file inside the dir, to buf
+ * 
+ * ZFS note: only WANTNAME is actually checked in ZFS code
+ * 
+ * Locks: vp should be locked on entry and will still be locked on exit.
+ * On success, dvp will be locked and have its reference count incremented.
+ * 
+ */
+int
+zfs_freebsd_getparent(struct vop_getparent_args *ap)
+/*
+vop_getparent {
+	IN struct vnode *a_vp;
+	OUT struct vnode **a_vpp;
+	IN uint64_t a_hint;
+	IN int a_flags;
+	INOUT char *a_buf;
+	INOUT int *a_buflen;
+};
+*/
+{
+	znode_t	*zp;
+	struct mount *mp;
+	struct vnode *dvp;
+	int error;
+	
+	zp = VTOZ(ap->a_vp);
+	mp = ap->a_vp->v_mount;
+	dvp = NULL;
+
+	if (zp->z_phys == NULL) {
+		error = ENOENT;
+		goto out;
+	}
+	/* grab directory vnode that should contain this znode */
+	error = VFS_VGET(mp, zp->z_phys->zp_parent, LK_SHARED, &dvp);
+	if (error) {
+		error = ENOENT;
+		goto out;
+	}
+	else if (ap->a_flags & WANTNAME) {
+		struct uio io;
+		struct iovec iov;
+		struct dirent *dp, *edp;
+		struct thread *td;
+		char *dirbuf;	
+		u_int64_t dirbuflen;
+		int error, eofflag;
+		char foundit;
+
+		foundit = 0;
+		dirbuflen = ((struct znode *)dvp->v_data)->z_blksz;
+		dirbuf = malloc(dirbuflen, M_TEMP, M_WAITOK);
+		td = curthread;
+		
+		/* prep the call to VOP_READDIR() */
+		iov.iov_base = dirbuf;
+		iov.iov_len = dirbuflen;
+		io.uio_iov = &iov;
+		io.uio_iovcnt = 1;
+		io.uio_offset = 0;
+		io.uio_resid = dirbuflen;
+		io.uio_segflg = UIO_SYSSPACE;
+		io.uio_rw = UIO_READ;
+		io.uio_td = td;
+		eofflag = 0;
+
+		error = VOP_READDIR(dvp, &io, td->td_ucred, &eofflag, NULL, NULL);
+		if (error) {
+			error = EIO;
+			goto out;
+		}
+		
+		/* search for the correct znode number inside the directory */
+		edp = (struct dirent *)&dirbuf[dirbuflen - io.uio_resid];
+		for (dp = (struct dirent *)dirbuf; dp < edp; ) {
+			if (dp->d_reclen > 0) {	
+				/* found it */
+				if (zp->z_id == ((struct dirent *)dp)->d_fileno) {
+					char *pch;
+					int len;
+
+					pch = ((struct dirent *)dp)->d_name;
+					len = strlen(pch);
+
+					if (len >= *(ap->a_buflen)) {
+						error = EOVERFLOW;
+						goto out;
+					}
+
+					strlcpy(ap->a_buf, ((struct dirent *)dp)->d_name, *(ap->a_buflen));
+					*(ap->a_buflen) -= len + 1;
+					foundit = 1;
+					break;
+				}
+				dp = (struct dirent *)((char *)dp + dp->d_reclen);
+			} 
+			else {
+				error = EIO;
+				break;
+			}
+		}
+				
+		if (dirbuf != NULL) {
+			free(dirbuf, M_TEMP);
+		}
+		
+		if (foundit == 0 && error != 0) {
+			error = ENOENT;
+			if (dvp)
+				vput(dvp);
+		}
+	} /* WANTNAME */
+
+out:	
+	if (error == 0 && dvp != NULL) {
+		*(ap->a_vpp) = dvp;
+	}
+	else if (error) {
+		*(ap->a_vpp) = NULL;
+	}
+	
+	return (error);
+}
+
 struct vop_vector zfs_vnodeops;
 struct vop_vector zfs_fifoops;
 
@@ -5005,6 +5157,7 @@
 	.vop_getacl =		zfs_freebsd_getacl,
 	.vop_setacl =		zfs_freebsd_setacl,
 	.vop_aclcheck =		zfs_freebsd_aclcheck,
+	.vop_getparent = 	zfs_freebsd_getparent,
 };
 
 struct vop_vector zfs_fifoops = {

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

@@ -120,6 +120,7 @@
 	.vop_unlock =		vop_stdunlock,
 	.vop_vptocnp =		vop_stdvptocnp,
 	.vop_vptofh =		vop_stdvptofh,
+	.vop_getparent =	vop_stdgetparent,
 };
 
 /*
@@ -841,6 +842,12 @@
 	return (error);
 }
 
+int
+vop_stdgetparent(struct vop_getparent_args *ap)
+{
+	return (EOPNOTSUPP);
+}
+
 /*
  * vfs default ops
  * used to fill the vfs function table to get reasonable default return values.

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

@@ -612,3 +612,15 @@
 	INOUT char *buf;
 	INOUT int *buflen;
 };
+
+%% getparent		vp	L L L
+%% getparent		vpp	- L -
+
+vop_getparent {
+	IN struct vnode *vp;
+	OUT struct vnode **vpp;
+	IN uint64_t hint;
+	IN int flags;
+	INOUT char *buf;
+	INOUT int *buflen;
+};

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

@@ -693,6 +693,7 @@
 int	vop_stdpoll(struct vop_poll_args *);
 int	vop_stdvptocnp(struct vop_vptocnp_args *ap);
 int	vop_stdvptofh(struct vop_vptofh_args *ap);
+int	vop_stdgetparent(struct vop_getparent_args *ap);
 int	vop_eopnotsupp(struct vop_generic_args *ap);
 int	vop_ebadf(struct vop_generic_args *ap);
 int	vop_einval(struct vop_generic_args *ap);

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

@@ -69,6 +69,7 @@
 #include <sys/systm.h>
 #include <sys/buf.h>
 #include <sys/conf.h>
+#include <sys/dirent.h>
 #include <sys/extattr.h>
 #include <sys/kernel.h>
 #include <sys/limits.h>
@@ -119,8 +120,8 @@
 static vop_openextattr_t	ffs_openextattr;
 static vop_setextattr_t	ffs_setextattr;
 static vop_vptofh_t	ffs_vptofh;
+static vop_getparent_t	ffs_getparent;
 
-
 /* Global vfs data structures for ufs. */
 struct vop_vector ffs_vnodeops1 = {
 	.vop_default =		&ufs_vnodeops,
@@ -131,6 +132,7 @@
 	.vop_reallocblks =	ffs_reallocblks,
 	.vop_write =		ffs_write,
 	.vop_vptofh =		ffs_vptofh,
+	.vop_getparent = 	ffs_getparent,
 };
 
 struct vop_vector ffs_fifoops1 = {
@@ -156,6 +158,7 @@
 	.vop_openextattr =	ffs_openextattr,
 	.vop_setextattr =	ffs_setextattr,
 	.vop_vptofh =		ffs_vptofh,
+	.vop_getparent = 	ffs_getparent,
 };
 
 struct vop_vector ffs_fifoops2 = {
@@ -1789,3 +1792,228 @@
 	}
 	return (0);
 }
+
+/* 
+ * XXXgpf: should relocate them someplace else
+ * I just dont know where:S 
+ */
+#define PARENTHINT 0x0001
+#define EXHAUSTSEARCH 0x0002
+#define WANTNAME 0x0004
+
+/*
+ * XXXgpf: used by VOP_GETPARENT
+ * 
+ * find the name that is used to reference vp inside the directory vnode dvp.
+ * flags should be set to WANTNAME if the filename should be copied to
+ * the supplied buffer.
+ * 
+ * locks: dvp must be locked on entry and will still be locked on exit
+ * 
+ * returns:
+ * 	- ENOENT	a file that corresponds to vp was not found inside dvp,
+ * 			or dvp is not a directory vnode
+ * 	- EIO		error occured while reading the directory
+ * 	- EOVERFLOW	result does not fit in buffer "name"
+ */
+static int
+dir_ilookup(struct vnode *vp, struct vnode *dvp, char *name, int *namelen, int flags)
+{
+	struct uio io;
+	struct iovec iov;
+	struct dirent *dp, *edp;
+	struct thread *td;
+	char *dirbuf;	
+	u_int64_t dirbuflen;
+	int error, eofflag;
+	char foundit;
+	
+	if (dvp->v_type != VDIR) {
+		return ENOENT;
+	}
+
+	foundit = 0;
+	dirbuflen = ((struct inode *)dvp->v_data)->i_size;
+	dirbuf = malloc(dirbuflen, M_TEMP, M_WAITOK);
+	td = curthread;
+	
+	/* prep the call to VOP_READDIR() */
+	iov.iov_base = dirbuf;
+	iov.iov_len = dirbuflen;
+	io.uio_iov = &iov;
+	io.uio_iovcnt = 1;
+	io.uio_offset = 0;
+	io.uio_resid = dirbuflen;
+	io.uio_segflg = UIO_SYSSPACE;
+	io.uio_rw = UIO_READ;
+	io.uio_td = td;
+	eofflag = 0;
+
+	error = VOP_READDIR(dvp, &io, td->td_ucred, &eofflag, NULL, NULL);
+	if (error) {
+		error = EIO;
+		goto out;
+	}
+	
+	/* search for the correct inode number inside the directory */
+	edp = (struct dirent *)&dirbuf[dirbuflen - io.uio_resid];
+	for (dp = (struct dirent *)dirbuf; dp < edp; ) {
+		if (dp->d_reclen > 0) {	
+			/* found it */
+			if ( ((struct inode *)vp->v_data)->i_number == ((struct dirent *)dp)->d_fileno) {
+				char *pch;
+				int len;
+				
+				if (flags & WANTNAME) { 
+					pch = ((struct dirent *)dp)->d_name;
+					len = strlen(pch);
+				
+					if (len >= *namelen) {
+						error = EOVERFLOW;
+						goto out;
+					}
+
+					strlcpy(name, ((struct dirent *)dp)->d_name, *namelen);
+					*namelen -= len + 1;
+				}
+				
+				foundit = 1;
+				break;
+			}
+			dp = (struct dirent *)((char *)dp + dp->d_reclen);
+		} 
+		else {
+			error = EIO;
+			break;
+		}
+	}
+
+out:	
+	if (dirbuf != NULL) {
+		free(dirbuf, M_TEMP);
+	}
+	
+	if (foundit == 0 && error != 0) {
+		error = ENOENT;
+	}
+	
+	return error;
+}
+
+/*
+ * VOP_GETPARENT
+ * 
+ * int VOP_GETPARENT(struct vnode *vp, struct vnode **dvp, uint64_t hint, 
+ * 	int flags, char *buf, int *buflen);
+ * 
+ * Find a parent directory -dvp- with vp as a child. The parent hint is used to 
+ * facilitate the search.
+ * 
+ * Flags should be set to:
+ * 	- PARENTHIT: if a hint ino_t of a directory is supplied to facilitate the search
+ * 	- EXHAUSTSEARCH: if we are willing to search the whole filesystem to find the directory
+ * 	- WANTNAME: if we want to copy the name used to reference the file inside the dir, to buf
+ * 
+ * Locks: vp should be locked on entry and will still be locked on exit.
+ * On success, dvp will be locked and have its reference count incremented.
+ * 
+ */
+static int
+ffs_getparent(struct vop_getparent_args *ap)
+/*
+vop_getparent {
+	IN struct vnode *a_vp;
+	OUT struct vnode **a_vpp;
+	IN uint64_t a_hint;
+	IN int a_flags;
+	INOUT char *a_buf;
+	INOUT int *a_buflen;
+};
+*/
+{
+	struct mount *mp;
+	struct vnode *vp, *dvp;
+	int error, flags;
+	
+	error = 0;
+	vp = ap->a_vp;
+	mp = vp->v_mount;
+	flags = ap->a_flags;
+
+	/* XXXgpf:is this check necessary? */
+	if (vp->v_type == VBAD) {
+		error = ENOENT;
+		dvp = NULL;
+		goto out;
+	}	
+
+	/* grab the parent directory using the directory_hint */
+	if (flags & PARENTHINT) {
+		error = VFS_VGET(mp, ap->a_hint, LK_SHARED, &dvp);
+		/* in case of failure, proceed to exhaustive search */
+		if (error) {
+			dvp = NULL;
+		}
+		else if (flags & WANTNAME) {
+			/* grab the name that is being used to reference vp */
+			error = dir_ilookup(vp, dvp, ap->a_buf, ap->a_buflen, flags);
+			if (error) {
+				vput(dvp);
+				dvp = NULL;
+			}
+		}
+	}		
+	
+	/* 
+	 * if our target is not a directory and we haven't found 'a' parent directory, 
+	 * do an exhaustive search on the filesystem
+	 */
+	if ((flags & EXHAUSTSEARCH) && dvp == NULL) {
+		/*
+		 * XXXgpf: this actually does not work because when the thread will try to sleep,
+		 * e.g. in VOP_READDIR, the kernel will panic because we have ilocked mp >.<
+		 * 
+		 * Not, it also kernel panics because we have locked vp >.<'
+		 */
+		MNT_ILOCK(mp);
+		if (!TAILQ_EMPTY(&mp->mnt_nvnodelist)) {
+			struct vnode *tvp;
+
+			TAILQ_FOREACH(tvp, &mp->mnt_nvnodelist, v_nmntvnodes) {
+				if (tvp->v_type == VDIR) {
+					vn_lock(tvp, LK_SHARED);
+					/* grab the name that is being used to reference vp */
+					error = dir_ilookup(vp, tvp, ap->a_buf, ap->a_buflen, flags);
+					
+					/* found it */
+					if (error == 0) {
+						dvp = tvp;
+						vref(dvp);
+						break;
+					}
+					VOP_UNLOCK(tvp, 0);
+				}
+			}
+		}
+		MNT_IUNLOCK(mp);
+		
+		/* we failed to find a directory that contains the vnode, exit */
+		if (error != 0) {
+			error = ENOENT;
+		}
+	}	
+	/* we failed to find a directory that contains the vnode, exit */
+	else if (dvp == NULL) {
+		error = ENOENT;
+	}
+
+out:
+	if (error == 0 && dvp != NULL) {
+		*(ap->a_vpp) = dvp;
+	}
+	else if (error) {
+		*(ap->a_vpp) = NULL;
+	}
+
+	return error;
+}

==== //depot/projects/soc2010/gpf_audit/vn_fullpath_nocache.c#4 (text+ko) ====

@@ -45,108 +45,14 @@
 #include <ufs/ufs/quota.h>
 #include <ufs/ufs/inode.h>
 
-#define PARENT_HINT 0x0001
-#define EXHAUSTIVE_SEARCH 0x0002
-
-/*
- * find the name that is used to reference vp inside the directory vnode dvp 
- * locks: dvp must be locked on entry and will still be locked on exit
- * 
- * works for UFS
- * 
- * returns:
- * 	- ENOENT	a file that corresponds to vp was not found inside dvp
- * 	- EIO		error occured while reading the directory
- * 	- EOVERFLOW	result does not fit in buffer "name"
+/* 
+ * XXXgpf: should relocate them someplace else
+ * I just dont know where:S 
  */
-static int
-dir_ilookup(struct vnode *vp, struct vnode *dvp, char *name, int *namelen)
-{
-	struct uio io;
-	struct iovec iov;
-	struct dirent *dp, *edp;
-	struct thread *td;
-	char *dirbuf;	
-	u_int64_t dirbuflen;
-	int error, eofflag;
-	char foundit;
-	
-	KASSERT("vp != NULL", "dir_ilookup: vp == NULL");
-	KASSERT("dvp != NULL", "dir_ilookup: dvp == NULL");
-	KASSERT("name != NULL", "dir_ilookup: name == NULL");
-
-	/* XXXgpf: temporary, must be a better way to check this than f_type or f_fstypename */
-	if (strcmp(vp->v_mount->mnt_stat.f_fstypename, "ufs")) {
-		uprintf("only ufs supported\n");
-		return 1;
-	}
-
-	foundit = 0;
-	dirbuflen = ((struct inode *)dvp->v_data)->i_size;
-	dirbuf = malloc(dirbuflen, M_TEMP, M_WAITOK);
-	td = curthread;
-	
-	/* prep the call to VOP_READDIR() */
-	iov.iov_base = dirbuf;
-	iov.iov_len = dirbuflen;
-	io.uio_iov = &iov;
-	io.uio_iovcnt = 1;
-	io.uio_offset = 0;
-	io.uio_resid = dirbuflen;
-	io.uio_segflg = UIO_SYSSPACE;
-	io.uio_rw = UIO_READ;
-	io.uio_td = td;
-	eofflag = 0;
-
-	error = VOP_READDIR(dvp, &io, td->td_ucred, &eofflag, NULL, NULL);
-	if (error) {
-		uprintf("VOP_READDIR failure %d\n", error);
-		error = EIO;
-		goto out;
-	}
-	
-	/* search for the correct inode number inside the directory */
-	edp = (struct dirent *)&dirbuf[dirbuflen - io.uio_resid];
-	for (dp = (struct dirent *)dirbuf; dp < edp; ) {
-		if (dp->d_reclen > 0) {	
-			/* found it */
-			if ( ((struct inode *)vp->v_data)->i_number == ((struct dirent *)dp)->d_fileno) {
-				char *pch;
-				int len;
-
-				pch = ((struct dirent *)dp)->d_name;
-				len = strlen(pch);
-				
-				if (len >= *namelen) {
-					error = EOVERFLOW;
-					goto out;
-				}
-
-				strlcpy(name, ((struct dirent *)dp)->d_name, *namelen);
-				*namelen -= len + 1;
-				foundit = 1;
-				break;
-			}
-			dp = (struct dirent *)((char *)dp + dp->d_reclen);
-		} 
-		else {
-			error = EIO;
-			break;
-		}
-	}
+#define PARENTHINT 0x0001
+#define EXHAUSTSEARCH 0x0002
+#define WANTNAME 0x0004
 
-out:	
-	if (dirbuf != NULL) {
-		free(dirbuf, M_TEMP);
-	}
-	
-	if (foundit == 0 && error != 0) {
-		error = ENOENT;
-	}
-	
-	return error;
-}
-
 /*
  * vn_fullpath_nocache
  * 
@@ -157,11 +63,13 @@
  * - 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
  */
 static int
-vn_fullpath_nocache(struct vnode *vp, char **fullpath, char **freepath, ino_t directory_hint, char flags)
+vn_fullpath_nocache(struct vnode *vp, char **fullpath, char **freepath, uint64_t directory_hint, char flags)
 {	
 	struct vnode *dvp, *upper_dvp;
 	struct mount *mp;
@@ -192,68 +100,15 @@
 	
 	/*
 	 * - If our target is a directory, move on to the part where we traverse the '..' entries.
-	 * - If not, either use the directory_hint if it's available or do an exhaustive search on the fs (xD) so
-	 *   that we can connect the vp with 'a' parent directory.
+	 * - If not, try to find its' parent through VOP_GETPARENT
 	 */
 	if (vp->v_type != VDIR) {
-		/* grab the parent directory using the directory_hint */
-		if ((flags & PARENT_HINT) && vp->v_type != VDIR) {
-			error = VFS_VGET(vp->v_mount, directory_hint, LK_SHARED, &dvp);
-			/* in case of failure, proceed to exhaustive search */
-			if (error) {
-				uprintf("VFS_VGET failure %d\n", error);
-				dvp = NULL;
-			}
-			else {
-				/* grab the name that is being used to reference vp */
-				error = dir_ilookup(vp, dvp, fname, &fnamelen);
-				if (error) {
-					vput(dvp);
-					goto out;
-				}
-			}
-		}		
-		
-		/* 
-		 * if our target is not a directory and we haven't found 'a' parent directory, 
-		 * do an exhaustive search on the filesystem
-		 */
-		if ((flags & EXHAUSTIVE_SEARCH) && dvp == NULL) {
-			/*
-			 * XXXgpf: this actually does not work because when the thread will try to sleep,
-			 * e.g. in VOP_READDIR, the kernel will panic because we have ilocked mp >.<
-			 */
-			MNT_ILOCK(mp);
-			if (!TAILQ_EMPTY(&mp->mnt_nvnodelist)) {
-				struct vnode *tvp;
-
-				TAILQ_FOREACH(tvp, &mp->mnt_nvnodelist, v_nmntvnodes) {
-					if (tvp->v_type == VDIR) {
-						vn_lock(tvp, LK_SHARED);
-						/* grab the name that is being used to reference vp */
-						error = dir_ilookup(vp, tvp, fname, &fnamelen);
-						
-						/* found it */
-						if (error == 0) {
-							dvp = tvp;
-							vref(dvp);
-							break;
-						}
-						VOP_UNLOCK(tvp, 0);
-					}
-				}
-			}
-			MNT_IUNLOCK(mp);
-			
-			/* we failed to find a directory that contains the vnode, exit */
-			if (error != 0) {
-				error = ENOENT;
-				goto out;
-			}
-		}
-		/* we failed to find a directory that contains the vnode, exit */
-		else if (dvp == NULL) {
-			error = ENOENT;
+		/* 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;
 		}
 
@@ -268,7 +123,7 @@
 		strcpy(pch, fname);
 		buflen -= strlen(fname);
 		buf[--buflen] = '/';		
-	} /* if not VDIR */
+	}
 	/* if our target is a dir, do the initial preparation */
 	else {
 		dvp = vp;
@@ -355,11 +210,13 @@
 	struct nameidata nd;
 	struct vnode *vp, *dvp;
 	char *freepath, *fullpath;
-	char *path = "/usr/home/gpf/Desktop/gsoc/example";
-	//char *path = "/usr/home/gpf/Desktop/usb/abc/file";
+	//char *path = "/usr/home/gpf/Desktop/gsoc/example";
+	//char *path = "/usr/home/gpf/Desktop/";
+	char *path = "/example/test/test.sh";
 	ino_t directory_hint;
 	int vfslocked;
 	int error;
+	int flags;
 	
 	/* use the namei interface to get something that we can work on */
 	NDINIT(&nd, LOOKUP, FOLLOW | WANTPARENT, UIO_SYSSPACE, path, curthread);
@@ -372,11 +229,6 @@
 	
 	vp = nd.ni_vp;
 	dvp = nd.ni_dvp;
-	
-	#if defined DEBUG
-	uprintf("inode number of the file %u\n", ((struct inode *)vp->v_data)->i_number);
-	uprintf("inode number of the dir that contains the file %u\n", ((struct inode *)dvp->v_data)->i_number);
-	#endif
 
 	vrele(vp);
 	vrele(dvp);
@@ -384,14 +236,19 @@
 	
 	/* preping the call to vn_fullpath_nocache() */
 	freepath = NULL;
-	/* careful, should not reference the i_number like that when vp is the root of a fs */
-	if (dvp != NULL && dvp->v_data != NULL)
-		directory_hint = ((struct inode *)dvp->v_data)->i_number;
-	
-	error = vn_fullpath_nocache(vp, &fullpath, &freepath, directory_hint, PARENT_HINT);
+	if (!strcmp(vp->v_mount->mnt_stat.f_fstypename, "ufs")) {
+		flags = PARENTHINT | WANTNAME;
+		/* careful, should not reference the i_number like that when vp is the root of a fs */
+		if (dvp != NULL && dvp->v_data != NULL)
+			directory_hint = ((struct inode *)dvp->v_data)->i_number;
+	}
+	else if (!strcmp(vp->v_mount->mnt_stat.f_fstypename, "zfs")) {
+		flags = WANTNAME;
+	}
+	error = vn_fullpath_nocache(vp, &fullpath, &freepath, directory_hint, flags);
 
 	uprintf("vn_fullpath_nocache() returned %d\n", error);
-	if (freepath != NULL) {
+	if (freepath != NULL) {		
 		uprintf("path: %s\n", fullpath);
 		free(freepath, M_TEMP);
 	}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201005262106.o4QL6QvV019237>