svn commit: r193174 - in head/sys: kern sys

Konstantin Belousov kib at FreeBSD.org
Sun May 31 14:57:45 UTC 2009


Author: kib
Date: Sun May 31 14:57:43 2009
New Revision: 193174
URL: http://svn.freebsd.org/changeset/base/193174

Log:
  Eliminate code duplication in vn_fullpath1() around the cache lookups
  and calls to vn_vptocnp() by moving more of the common code to
  vn_vptocnp(). Rename vn_vptocnp() to vn_vptocnp_locked() to signify that
  cache is locked around the call.
  
  Do not track buffer position by both the pointer and offset, use only
  buflen to record the start of the free space.
  
  Export vn_vptocnp() for external consumers as a wrapper around
  vn_vptocnp_locked() that locks the cache and handles hold counts.
  
  Tested by:	pho

Modified:
  head/sys/kern/vfs_cache.c
  head/sys/sys/vnode.h

Modified: head/sys/kern/vfs_cache.c
==============================================================================
--- head/sys/kern/vfs_cache.c	Sun May 31 14:54:20 2009	(r193173)
+++ head/sys/kern/vfs_cache.c	Sun May 31 14:57:43 2009	(r193174)
@@ -206,7 +206,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_vptocnp_locked(struct vnode **vp, 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);
 
@@ -1036,12 +1036,55 @@ vn_fullpath_global(struct thread *td, st
 	return (error);
 }
 
+int
+vn_vptocnp(struct vnode **vp, char *buf, u_int *buflen)
+{
+	int error;
+
+	CACHE_RLOCK();
+	error = vn_vptocnp_locked(vp, buf, buflen);
+	if (error == 0) {
+		/*
+		 * vn_vptocnp_locked() dropped hold acquired by
+		 * VOP_VPTOCNP immediately after locking the
+		 * cache. Since we are going to drop the cache rlock,
+		 * re-hold the result.
+		 */
+		vhold(*vp);
+		CACHE_RUNLOCK();
+	}
+	return (error);
+}
+
 static int
-vn_vptocnp(struct vnode **vp, char **bp, char *buf, u_int *buflen)
+vn_vptocnp_locked(struct vnode **vp, char *buf, u_int *buflen)
 {
 	struct vnode *dvp;
+	struct namecache *ncp;
 	int error, vfslocked;
 
+	TAILQ_FOREACH(ncp, &((*vp)->v_cache_dst), nc_dst) {
+		if ((ncp->nc_flag & NCF_ISDOTDOT) == 0)
+			break;
+	}
+	if (ncp != NULL) {
+		if (*buflen < ncp->nc_nlen) {
+			CACHE_RUNLOCK();
+			numfullpathfail4++;
+			error = ENOMEM;
+			SDT_PROBE(vfs, namecache, fullpath, return, error,
+			    startvp, NULL, 0, 0);
+			return (error);
+		}
+		*buflen -= ncp->nc_nlen;
+		memcpy(buf + *buflen, ncp->nc_name, ncp->nc_nlen);
+		SDT_PROBE(vfs, namecache, fullpath, hit, ncp->nc_dvp,
+		    ncp->nc_name, vp, 0, 0);
+		*vp = ncp->nc_dvp;
+		return (0);
+	}
+	SDT_PROBE(vfs, namecache, fullpath, miss, vp, 0, 0, 0, 0);
+
 	vhold(*vp);
 	CACHE_RUNLOCK();
 	vfslocked = VFS_LOCK_GIANT((*vp)->v_mount);
@@ -1052,16 +1095,21 @@ vn_vptocnp(struct vnode **vp, char **bp,
 	VFS_UNLOCK_GIANT(vfslocked);
 	if (error) {
 		numfullpathfail2++;
+		SDT_PROBE(vfs, namecache, fullpath, return,  error, startvp,
+		    NULL, 0, 0);
 		return (error);
 	}
-	*bp = buf + *buflen;
+
 	*vp = dvp;
 	CACHE_RLOCK();
 	if ((*vp)->v_iflag & VI_DOOMED) {
 		/* forced unmount */
 		CACHE_RUNLOCK();
 		vdrop(*vp);
-		return (ENOENT);
+		error = ENOENT;
+		SDT_PROBE(vfs, namecache, fullpath, return, error, startvp,
+		    NULL, 0, 0);
+		return (error);
 	}
 	vdrop(*vp);
 
@@ -1075,59 +1123,26 @@ static int
 vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
     char *buf, char **retbuf, u_int buflen)
 {
-	char *bp;
-	int error, i, slash_prefixed;
-	struct namecache *ncp;
+	int error, slash_prefixed;
 #ifdef KDTRACE_HOOKS
 	struct vnode *startvp = vp;
 #endif
 
 	buflen--;
-	bp = buf + buflen;
-	*bp = '\0';
+	buf[buflen] = '\0';
 	error = 0;
 	slash_prefixed = 0;
 
 	SDT_PROBE(vfs, namecache, fullpath, entry, vp, 0, 0, 0, 0);
-	CACHE_RLOCK();
 	numfullpathcalls++;
+	CACHE_RLOCK();
 	if (vp->v_type != VDIR) {
-		ncp = TAILQ_FIRST(&vp->v_cache_dst);
-		if (ncp != NULL) {
-			buflen -= ncp->nc_nlen;
-			for (i = ncp->nc_nlen - 1; i >= 0 && bp != buf; i--)
-				*--bp = ncp->nc_name[i];
-			if (bp == buf) {
-				numfullpathfail4++;
-				CACHE_RUNLOCK();
-				error = ENOMEM;
-				SDT_PROBE(vfs, namecache, fullpath, return,
-				    error, startvp, NULL, 0, 0);
-				return (error);
-			}
-			SDT_PROBE(vfs, namecache, fullpath, hit, ncp->nc_dvp,
-			    ncp->nc_name, vp, 0, 0);
-			vp = ncp->nc_dvp;
-		} else {
-			SDT_PROBE(vfs, namecache, fullpath, miss, vp, 0, 0,
-			    0, 0);
-			error = vn_vptocnp(&vp, &bp, buf, &buflen);
-			if (error) {
-				SDT_PROBE(vfs, namecache, fullpath, return,
-				    error, startvp, NULL, 0, 0);
-				return (error);
-			}
-		}
-		if (buflen <= 0) {
-			numfullpathfail4++;
-			CACHE_RUNLOCK();
-			error = ENOMEM;
-			SDT_PROBE(vfs, namecache, fullpath, return, error,
-			    startvp, NULL, 0, 0);
+		error = vn_vptocnp_locked(&vp, buf, &buflen);
+		if (error)
 			return (error);
-		}
-		*--bp = '/';
-		buflen--;
+		if (buflen == 0)
+			return (ENOMEM);
+		buf[--buflen] = '/';
 		slash_prefixed = 1;
 	}
 	while (vp != rdir && vp != rootvnode) {
@@ -1141,64 +1156,39 @@ vn_fullpath1(struct thread *td, struct v
 			continue;
 		}
 		if (vp->v_type != VDIR) {
-			numfullpathfail1++;
 			CACHE_RUNLOCK();
+			numfullpathfail1++;
 			error = ENOTDIR;
 			break;
 		}
- 		TAILQ_FOREACH(ncp, &vp->v_cache_dst, nc_dst)
- 			if ((ncp->nc_flag & NCF_ISDOTDOT) == 0)
- 				break;
-		if (ncp != NULL) {
-			buflen -= ncp->nc_nlen;
-			for (i = ncp->nc_nlen - 1; i >= 0 && bp != buf; i--)
-				*--bp = ncp->nc_name[i];
-			if (bp == buf) {
-				numfullpathfail4++;
-				CACHE_RUNLOCK();
-				error = ENOMEM;
-				break;
-			}
-			SDT_PROBE(vfs, namecache, fullpath, hit, ncp->nc_dvp,
-			    ncp->nc_name, vp, 0, 0);
-			vp = ncp->nc_dvp;
-		} else {
-			SDT_PROBE(vfs, namecache, fullpath, miss, vp, 0, 0,
-			    0, 0);
-			error = vn_vptocnp(&vp, &bp, buf, &buflen);
-			if (error)
-				break;
-		}
-		if (buflen <= 0) {
-			numfullpathfail4++;
-			CACHE_RUNLOCK();
+		error = vn_vptocnp_locked(&vp, buf, &buflen);
+		if (error)
+			break;
+		if (buflen == 0) {
 			error = ENOMEM;
 			break;
 		}
-		*--bp = '/';
-		buflen--;
+		buf[--buflen] = '/';
 		slash_prefixed = 1;
 	}
-	if (error) {
-		SDT_PROBE(vfs, namecache, fullpath, return, error, startvp,
-		    NULL, 0, 0);
+	if (error)
 		return (error);
-	}
 	if (!slash_prefixed) {
-		if (bp == buf) {
-			numfullpathfail4++;
+		if (buflen == 0) {
 			CACHE_RUNLOCK();
+			numfullpathfail4++;
 			SDT_PROBE(vfs, namecache, fullpath, return, 0,
-			    startvp, bp, 0, 0);
+			    startvp, fullpath, 0, 0);
 			return (ENOMEM);
-		} else
-			*--bp = '/';
+		}
+		buf[--buflen] = '/';
 	}
 	numfullpathfound++;
 	CACHE_RUNLOCK();
 
-	SDT_PROBE(vfs, namecache, fullpath, return, 0, startvp, bp, 0, 0);
-	*retbuf = bp;
+	SDT_PROBE(vfs, namecache, fullpath, return, 0, startvp, buf + *buflen,
+	    0, 0);
+	*retbuf = buf + buflen;
 	return (0);
 }
 

Modified: head/sys/sys/vnode.h
==============================================================================
--- head/sys/sys/vnode.h	Sun May 31 14:54:20 2009	(r193173)
+++ head/sys/sys/vnode.h	Sun May 31 14:57:43 2009	(r193174)
@@ -598,6 +598,7 @@ int	insmntque1(struct vnode *vp, struct 
 int	insmntque(struct vnode *vp, struct mount *mp);
 u_quad_t init_va_filerev(void);
 int	speedup_syncer(void);
+int	vn_vptocnp(struct vnode **vp, char *buf, u_int *buflen);
 #define textvp_fullpath(p, rb, rfb) \
 	vn_fullpath(FIRST_THREAD_IN_PROC(p), (p)->p_textvp, rb, rfb)
 int	vn_fullpath(struct thread *td, struct vnode *vn,


More information about the svn-src-all mailing list