Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 12 Dec 2008 00:57:39 +0000 (UTC)
From:      Joe Marcus Clarke <marcus@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r185956 - head/sys/kern
Message-ID:  <200812120057.mBC0vdX7081650@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: marcus (doc,ports committer)
Date: Fri Dec 12 00:57:38 2008
New Revision: 185956
URL: http://svn.freebsd.org/changeset/base/185956

Log:
  Add a new VOP, VOP_VPTOCNP, which translates a vnode to its component name
  on a best-effort basis.  Teach vn_fullpath to use this new VOP if a
  regular VFS cache lookup fails.  This VOP is designed to supplement the
  VFS cache to provide a better chance that a vnode-to-name lookup will
  succeed.
  
  Currently, an implementation for devfs is being committed.  The default
  implementation is to return ENOENT.
  
  A big thanks to kib for the mentorship on this, and to pho for running it
  through his stress test suite.
  
  Reviewed by:	arch
  Approved by:	kib

Modified:
  head/sys/kern/vfs_cache.c
  head/sys/kern/vfs_default.c
  head/sys/kern/vnode_if.src

Modified: head/sys/kern/vfs_cache.c
==============================================================================
--- head/sys/kern/vfs_cache.c	Fri Dec 12 00:56:00 2008	(r185955)
+++ head/sys/kern/vfs_cache.c	Fri Dec 12 00:57:38 2008	(r185956)
@@ -169,6 +169,7 @@ SYSCTL_OPAQUE(_vfs_cache, OID_AUTO, nchs
 
 
 static void cache_zap(struct namecache *ncp);
+static int vn_vptocnp(struct vnode **vp, char **bp, char *buf, u_int *buflen);
 static int vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
     char *buf, char **retbuf, u_int buflen);
 
@@ -840,6 +841,38 @@ vn_fullpath_global(struct thread *td, st
 	return (error);
 }
 
+static int
+vn_vptocnp(struct vnode **vp, char **bp, char *buf, u_int *buflen)
+{
+	struct vnode *dvp;
+	int error, vfslocked;
+
+	vhold(*vp);
+	CACHE_UNLOCK();
+	vfslocked = VFS_LOCK_GIANT((*vp)->v_mount);
+	vn_lock(*vp, LK_SHARED | LK_RETRY);
+	vdrop(*vp);
+	error = VOP_VPTOCNP(*vp, &dvp, buf, buflen);
+	VOP_UNLOCK(*vp, 0);
+	VFS_UNLOCK_GIANT(vfslocked);
+	if (error) {
+		numfullpathfail2++;
+		return (error);
+	}
+	*bp = buf + *buflen;
+	*vp = dvp;
+	CACHE_LOCK();
+	if ((*vp)->v_iflag & VI_DOOMED) {
+		/* forced unmount */
+		CACHE_UNLOCK();
+		vdrop(*vp);
+		return (ENOENT);
+	}
+	vdrop(*vp);
+
+	return (0);
+}
+
 /*
  * The magic behind kern___getcwd() and vn_fullpath().
  */
@@ -851,7 +884,8 @@ vn_fullpath1(struct thread *td, struct v
 	int error, i, slash_prefixed;
 	struct namecache *ncp;
 
-	bp = buf + buflen - 1;
+	buflen--;
+	bp = buf + buflen;
 	*bp = '\0';
 	error = 0;
 	slash_prefixed = 0;
@@ -860,58 +894,77 @@ vn_fullpath1(struct thread *td, struct v
 	numfullpathcalls++;
 	if (vp->v_type != VDIR) {
 		ncp = TAILQ_FIRST(&vp->v_cache_dst);
-		if (!ncp) {
-			numfullpathfail2++;
-			CACHE_UNLOCK();
-			return (ENOENT);
+		if (ncp != NULL) {
+			for (i = ncp->nc_nlen - 1; i >= 0 && bp > buf; i--)
+				*--bp = ncp->nc_name[i];
+			if (bp == buf) {
+				numfullpathfail4++;
+				CACHE_UNLOCK();
+				return (ENOMEM);
+			}
+			vp = ncp->nc_dvp;
+		} else {
+			error = vn_vptocnp(&vp, &bp, buf, &buflen);
+			if (error) {
+				return (error);
+			}
 		}
-		for (i = ncp->nc_nlen - 1; i >= 0 && bp > buf; i--)
-			*--bp = ncp->nc_name[i];
-		if (bp == buf) {
+		*--bp = '/';
+		buflen--;
+		if (buflen < 0) {
 			numfullpathfail4++;
 			CACHE_UNLOCK();
 			return (ENOMEM);
 		}
-		*--bp = '/';
 		slash_prefixed = 1;
-		vp = ncp->nc_dvp;
 	}
 	while (vp != rdir && vp != rootvnode) {
 		if (vp->v_vflag & VV_ROOT) {
 			if (vp->v_iflag & VI_DOOMED) {	/* forced unmount */
+				CACHE_UNLOCK();
 				error = EBADF;
 				break;
 			}
 			vp = vp->v_mount->mnt_vnodecovered;
 			continue;
 		}
-		if (vp->v_dd == NULL) {
+		if (vp->v_type != VDIR) {
 			numfullpathfail1++;
+			CACHE_UNLOCK();
 			error = ENOTDIR;
 			break;
 		}
 		ncp = TAILQ_FIRST(&vp->v_cache_dst);
-		if (!ncp) {
-			numfullpathfail2++;
-			error = ENOENT;
-			break;
+		if (ncp != NULL) {
+			MPASS(ncp->nc_dvp == vp->v_dd);
+			buflen -= ncp->nc_nlen - 1;
+			for (i = ncp->nc_nlen - 1; i >= 0 && bp != buf; i--)
+				*--bp = ncp->nc_name[i];
+			if (bp == buf) {
+				numfullpathfail4++;
+				CACHE_UNLOCK();
+				error = ENOMEM;
+				break;
+			}
+			vp = ncp->nc_dvp;
+		} else {
+			error = vn_vptocnp(&vp, &bp, buf, &buflen);
+			if (error) {
+				break;
+			}
 		}
-		MPASS(ncp->nc_dvp == vp->v_dd);
-		for (i = ncp->nc_nlen - 1; i >= 0 && bp != buf; i--)
-			*--bp = ncp->nc_name[i];
-		if (bp == buf) {
+		*--bp = '/';
+		buflen--;
+		if (buflen < 0) {
 			numfullpathfail4++;
+			CACHE_UNLOCK();
 			error = ENOMEM;
 			break;
 		}
-		*--bp = '/';
 		slash_prefixed = 1;
-		vp = ncp->nc_dvp;
 	}
-	if (error) {
-		CACHE_UNLOCK();
+	if (error)
 		return (error);
-	}
 	if (!slash_prefixed) {
 		if (bp == buf) {
 			numfullpathfail4++;

Modified: head/sys/kern/vfs_default.c
==============================================================================
--- head/sys/kern/vfs_default.c	Fri Dec 12 00:56:00 2008	(r185955)
+++ head/sys/kern/vfs_default.c	Fri Dec 12 00:57:38 2008	(r185956)
@@ -98,6 +98,7 @@ struct vop_vector default_vnodeops = {
 	.vop_revoke =		VOP_PANIC,
 	.vop_strategy =		vop_nostrategy,
 	.vop_unlock =		vop_stdunlock,
+	.vop_vptocnp =		VOP_ENOENT,
 	.vop_vptofh =		vop_stdvptofh,
 };
 
@@ -138,6 +139,13 @@ vop_einval(struct vop_generic_args *ap)
 }
 
 int
+vop_enoent(struct vop_generic_args *ap)
+{
+
+	return (ENOENT);
+}
+
+int
 vop_null(struct vop_generic_args *ap)
 {
 

Modified: head/sys/kern/vnode_if.src
==============================================================================
--- head/sys/kern/vnode_if.src	Fri Dec 12 00:56:00 2008	(r185955)
+++ head/sys/kern/vnode_if.src	Fri Dec 12 00:57:38 2008	(r185956)
@@ -595,3 +595,13 @@ vop_vptofh {
 	IN struct vnode *vp;
 	IN struct fid *fhp;
 };
+
+%% vptocnp		vp	L L L
+%% vptocnp		vpp	- U -
+
+vop_vptocnp {
+	IN struct vnode *vp;
+	OUT struct vnode **vpp;
+	INOUT char *buf;
+	INOUT int *buflen;
+};



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