PERFORCE change 179289 for review
Efstratios Karatzas
gpf at FreeBSD.org
Mon Jun 7 15:33:02 UTC 2010
http://p4web.freebsd.org/@@179289?ac=10
Change 179289 by gpf at gpf_desktop on 2010/06/07 15:32:53
- make vn_fullpath_nocache() friendly to non-mp safe fs
- removed some useless locks or references
- some code refactoring, edited comments etc
- fixed a tiny bug in vn_fullpath_nocache()
Affected files ...
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/kern/vfs_cache.c#3 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/ufs/ffs/ffs_vnops.c#7 edit
Differences ...
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/kern/vfs_cache.c#3 (text+ko) ====
@@ -1227,43 +1227,53 @@
return (0);
}
+/*
+ * XXXgpf: should relocate them someplace else
+ * I just dont know where:S
+ */
+#define PARENTHINT 0x0001
+#define EXHAUSTSEARCH 0x0002
+#define WANTNAME 0x0004
+
/*
- * vn_fullpath_nocache
+ * vn_fullpath_nocache(9)
*
* 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.
+ * and to EXHAUSTIVE_SEARCH, if we are willing to search the entire filesystem to acquire a path.
*
* Locks: no locks required.
*
- * Author's note: This only works for UFS filesystems (for now).
- * Oh, also EXHAUSTIVE_SEARCH will kernel panic :-D
+ * Authors Note: freepath should be set to NULL before calling this KPI. Upon returning from the KPI,
+ * the caller should check if freepath is non-NULL, and if so, invoke free(9) with a pool type of M_TEMP.
*/
int
vn_fullpath_nocache(struct vnode *vp, char **fullpath, char **freepath, uint64_t directory_hint, char flags)
{
+ char fname[MNAMELEN];
struct vnode *dvp, *upper_dvp;
struct mount *mp;
struct thread * td;
- char *buf, *pch;
- char fname[MNAMELEN];
+ char *buf, *pch;
int error, buflen, vfslocked, fnamelen;
KASSERT(vp != NULL, ("vn_fullpath_nocache: null vp"));
dvp = NULL;
buf = NULL;
- *freepath = NULL;
+ *freepath = NULL;
+ VREF(vp);
+ /* doesn't really make sense to continue without this flag set */
+ flags |= WANTNAME;
+ /* XXXgpf: do we really need this? */
if (vp->v_type == VBAD) {
error = ENOENT;
goto out;
- }
-
- vref(vp);
+ }
error = 0;
td = curthread;
mp = vp->v_mount;
@@ -1286,12 +1296,18 @@
goto out;
}
- /* we have found a parent directory and a name for our vnode, save the name */
+ /*
+ * we have found a parent directory and a name for our vnode,
+ * save the name at the end of buf
+ */
pch = buf + buflen - strlen(fname);
if (pch < buf) {
error = EOVERFLOW;
- if (dvp != NULL)
+ if (dvp != NULL) {
+ vfslocked = VFS_LOCK_GIANT(dvp->v_mount);
vput(dvp);
+ VFS_UNLOCK_GIANT(vfslocked);
+ }
goto out;
}
strcpy(pch, fname);
@@ -1301,7 +1317,7 @@
/* if our target is a dir, do the initial preparation */
else {
dvp = vp;
- vref(dvp);
+ VREF(dvp);
vn_lock(dvp, LK_SHARED);
}
@@ -1313,54 +1329,58 @@
/*
* 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);
+ MNT_REF(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) {
+ vfslocked = VFS_LOCK_GIANT(dvp->v_mount);
vput(dvp);
+ VFS_UNLOCK_GIANT(vfslocked);
error = EOVERFLOW;
- VFS_UNLOCK_GIANT(vfslocked);
+ MNT_REL(dvp->v_mount);
goto out;
}
-
+
pch = buf + buflen - fs_path_len;
memcpy(pch, fs_path, fs_path_len);
buflen -= fs_path_len;
-
- VFS_UNLOCK_GIANT(vfslocked);
-
+
+ MNT_REL(dvp->v_mount);
break;
}
-
+
+ vfslocked = VFS_LOCK_GIANT(dvp->v_mount);
error = VOP_VPTOCNP(dvp, &upper_dvp, td->td_ucred, buf, &buflen);
- if (error) {
- uprintf("VOP_VPTOCNP failure %d\n", error);
+ VFS_UNLOCK_GIANT(vfslocked);
+ if (error)
+ break;
+ if (buflen <= 0) {
+ error = EOVERFLOW;
break;
}
-
- buf[--buflen] = '/';
- if (dvp != NULL)
+
+ buf[--buflen] = '/';
+ if (dvp != NULL) {
+ vfslocked = VFS_LOCK_GIANT(dvp->v_mount);
vput(dvp);
-
+ VFS_UNLOCK_GIANT(vfslocked);
+ }
vdrop(upper_dvp);
dvp = upper_dvp;
vn_lock(dvp, LK_SHARED);
- vref(dvp);
+ VREF(dvp);
} /* while */
- vput(dvp);
+ vfslocked = VFS_LOCK_GIANT(dvp->v_mount);
+ vput(dvp);
+ VFS_UNLOCK_GIANT(vfslocked);
*fullpath = buf + buflen;
*freepath = buf;
@@ -1369,8 +1389,10 @@
*freepath = NULL;
if (buf != NULL)
free(buf, M_TEMP);
- }
+ }
+ vfslocked = VFS_LOCK_GIANT(vp->v_mount);
vrele(vp);
-
+ VFS_UNLOCK_GIANT(vfslocked);
+
return error;
}
==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/ufs/ffs/ffs_vnops.c#7 (text+ko) ====
@@ -1806,7 +1806,7 @@
*
* find 'a' name that is used to reference vp inside some parent directory.
* flags should be set to WANTNAME if the filename should be copied to
- * the supplied buffer.
+ * the supplied buffer, in which case the supplied buffer should be != NULL.
*
* flags should be set to EXHAUSTSEARCH if want to perform a depth first search
* on the filesystem that contains vp. In this case, tmpdvp should be the root vnode
@@ -1951,7 +1951,9 @@
* 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.
+ * facilitate the search. On success, the name used to reference the child -vp-
+ * will be copied to buf. buflen should contain the lenght of buf on entry. On
+ * success, it will contain the remaining length of the buffer.
*
* Flags should be set to:
* - PARENTHIT: if a hint ino_t of a directory is supplied to facilitate the search
@@ -1989,8 +1991,6 @@
if (flags & WANTNAME)
KASSERT(ap->a_buf != NULL, ("VOP_GEPARENT: null buffer"));
- MNT_REF(mp);
-
/* XXXgpf:is this check necessary? */
if (vp->v_type == VBAD) {
error = ENOENT;
@@ -2040,14 +2040,10 @@
}
out:
- if (error == 0 && dvp != NULL) {
+ if (error == 0 && dvp != NULL)
*(ap->a_vpp) = dvp;
- }
- else {
+ else
*(ap->a_vpp) = NULL;
- }
-
- MNT_REL(mp);
return error;
}
More information about the p4-projects
mailing list