svn commit: r190829 - head/sys/kern

Robert Watson rwatson at FreeBSD.org
Tue Apr 7 13:58:58 PDT 2009


Author: rwatson
Date: Tue Apr  7 20:58:56 2009
New Revision: 190829
URL: http://svn.freebsd.org/changeset/base/190829

Log:
  Nul-terminate strings in the VFS name cache, which negligibly change
  the size and cost of name cache entries, but make adding debugging
  and tracing easier.
  
  Add SDT DTrace probes for various namecache events:
  
    vfs:namecache:enter:done - new entry in the name cache, passed parent
      directory vnode pointer, name added to the cache, and child vnode
      pointer.
  
    vfs:namecache:enter_negative:done - new negative entry in the name cache,
      passed parent vnode pointer, name added to the cache.
  
    vfs:namecache:fullpath:enter - call to vn_fullpath1() is made, passed
      the vnode to resolve to a name.
  
    vfs:namecache:fullpath:hit - vn_fullpath1() successfully resolved a
      search for the parent of an object using the namecache, passed the
      discovered parent directory vnode pointer, name, and child vnode
      pointer.
  
    vfs:namecache:fullpath:miss - vn_fullpath1() failed to resolve a search
      for the parent of an object using the namecache, passed the child
      vnode pointer.
  
    vfs:namecache:fullpath:return - vn_fullpath1() has completed, passed the
      error number, and if that is zero, the vnode to resolve, and the
      returned path.
  
    vfs:namecache:lookup:hit - postive name cache entry hit, passed the
      parent directory vnode pointer, name, and child vnode pointer.
  
    vfs:namecache:lookup:hit_negative - negative name cache entry hit,
      passed the parent directory vnode pointer and name.
  
    vfs:namecache:lookup:miss - name cache miss, passed the parent directory
      pointer and the full remaining component name (not terminated after the
      cache miss component).
  
    vfs:namecache:purge:done - name cache purge for a vnode, passed the vnode
      pointer to purge.
  
    vfs:namecache:purge_negative:done - name cache purge of negative entries
      for children of a vnode, passed the vnode pointer to purge.
  
    vfs:namecache:purgevfs - name cache purge for a mountpoint, passed the
      mount pointer.  Separate probes will also be invoked for each cache
      entry zapped.
  
    vfs:namecache:zap:done - name cache entry zapped, passed the parent
      directory vnode pointer, name, and child vnode pointer.
  
    vfs:namecache:zap_negative:done - negative name cache entry zapped,
      passed the parent directory vnode pointer and name.
  
  For any probes involving an extant name cache entry (enter, hit, zapp),
  we use the nul-terminated string for the name component.  For misses,
  the remainder of the path, including later components, is provided as
  an argument instead since there is no handy nul-terminated version of
  the string around.  This is arguably a bug.
  
  MFC after:      1 month
  Sponsored by:   Google, Inc.
  Reviewed by:	jhb, kan, kib (earlier version)

Modified:
  head/sys/kern/vfs_cache.c

Modified: head/sys/kern/vfs_cache.c
==============================================================================
--- head/sys/kern/vfs_cache.c	Tue Apr  7 20:34:34 2009	(r190828)
+++ head/sys/kern/vfs_cache.c	Tue Apr  7 20:58:56 2009	(r190829)
@@ -35,6 +35,7 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_kdtrace.h"
 #include "opt_ktrace.h"
 
 #include <sys/param.h>
@@ -47,6 +48,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/namei.h>
 #include <sys/proc.h>
 #include <sys/rwlock.h>
+#include <sys/sdt.h>
 #include <sys/syscallsubr.h>
 #include <sys/sysctl.h>
 #include <sys/sysproto.h>
@@ -58,6 +60,31 @@ __FBSDID("$FreeBSD$");
 
 #include <vm/uma.h>
 
+SDT_PROVIDER_DECLARE(vfs);
+SDT_PROBE_DEFINE3(vfs, namecache, enter, done, "struct vnode *", "char *",
+    "struct vnode *");
+SDT_PROBE_DEFINE2(vfs, namecache, enter_negative, done, "struct vnode *",
+    "char *");
+SDT_PROBE_DEFINE1(vfs, namecache, fullpath, entry, "struct vnode *");
+SDT_PROBE_DEFINE3(vfs, namecache, fullpath, hit, "struct vnode *",
+    "struct char *", "struct vnode *");
+SDT_PROBE_DEFINE1(vfs, namecache, fullpath, miss, "struct vnode *");
+SDT_PROBE_DEFINE3(vfs, namecache, fullpath, return, "int", "struct vnode *",
+    "struct char *");
+SDT_PROBE_DEFINE3(vfs, namecache, lookup, hit, "struct vnode *", "char *",
+    "struct vnode *");
+SDT_PROBE_DEFINE2(vfs, namecache, lookup, hit_negative, "struct vnode *",
+    "char *");
+SDT_PROBE_DEFINE2(vfs, namecache, lookup, miss, "struct vnode *",
+    "char *");
+SDT_PROBE_DEFINE1(vfs, namecache, purge, done, "struct vnode *");
+SDT_PROBE_DEFINE1(vfs, namecache, purge_negative, done, "struct vnode *");
+SDT_PROBE_DEFINE1(vfs, namecache, purgevfs, done, "struct mount *");
+SDT_PROBE_DEFINE3(vfs, namecache, zap, done, "struct vnode *", "char *",
+    "struct vnode *");
+SDT_PROBE_DEFINE2(vfs, namecache, zap_negative, done, "struct vnode *",
+    "char *");
+
 /*
  * This structure describes the elements in the cache of recent
  * names looked up by namei.
@@ -71,7 +98,7 @@ struct	namecache {
 	struct	vnode *nc_vp;		/* vnode the name refers to */
 	u_char	nc_flag;		/* flag bits */
 	u_char	nc_nlen;		/* length of name */
-	char	nc_name[0];		/* segment name */
+	char	nc_name[0];		/* segment name + nul */
 };
 
 /*
@@ -133,9 +160,10 @@ RW_SYSINIT(vfscache, &cache_lock, "Name 
 static uma_zone_t cache_zone_small;
 static uma_zone_t cache_zone_large;
 
-#define	CACHE_PATH_CUTOFF	32
-#define	CACHE_ZONE_SMALL	(sizeof(struct namecache) + CACHE_PATH_CUTOFF)
-#define	CACHE_ZONE_LARGE	(sizeof(struct namecache) + NAME_MAX)
+#define	CACHE_PATH_CUTOFF	35
+#define	CACHE_ZONE_SMALL	(sizeof(struct namecache) + CACHE_PATH_CUTOFF \
+				    + 1)
+#define	CACHE_ZONE_LARGE	(sizeof(struct namecache) + NAME_MAX + 1)
 
 #define cache_alloc(len)	uma_zalloc(((len) <= CACHE_PATH_CUTOFF) ? \
 	cache_zone_small : cache_zone_large, M_WAITOK)
@@ -291,6 +319,15 @@ cache_zap(ncp)
 
 	rw_assert(&cache_lock, RA_WLOCKED);
 	CTR2(KTR_VFS, "cache_zap(%p) vp %p", ncp, ncp->nc_vp);
+#ifdef KDTRACE_HOOKS
+	if (ncp->nc_vp != NULL) {
+		SDT_PROBE(vfs, namecache, zap, done, ncp->nc_dvp,
+		    ncp->nc_name, ncp->nc_vp, 0, 0);
+	} else {
+		SDT_PROBE(vfs, namecache, zap_negative, done, ncp->nc_dvp,
+		    ncp->nc_name, 0, 0, 0);
+	}
+#endif
 	vp = NULL;
 	LIST_REMOVE(ncp, nc_hash);
 	if (ncp->nc_flag & NCF_ISDOTDOT) {
@@ -361,12 +398,17 @@ retry_wlocked:
 			CTR2(KTR_VFS, "cache_lookup(%p, %s) found via .",
 			    dvp, cnp->cn_nameptr);
 			dothits++;
+			SDT_PROBE(vfs, namecache, lookup, hit, dvp, ".",
+			    *vpp, 0, 0);
 			goto success;
 		}
 		if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.') {
 			dotdothits++;
-			if (dvp->v_cache_dd == NULL)
+			if (dvp->v_cache_dd == NULL) {
+				SDT_PROBE(vfs, namecache, lookup, miss, dvp,
+				    "..", NULL, 0, 0);
 				goto unlock;
+			}
 			if ((cnp->cn_flags & MAKEENTRY) == 0) {
 				if (dvp->v_cache_dd->nc_flag & NCF_ISDOTDOT)
 					cache_zap(dvp->v_cache_dd);
@@ -379,6 +421,8 @@ retry_wlocked:
 				*vpp = dvp->v_cache_dd->nc_dvp;
 			CTR3(KTR_VFS, "cache_lookup(%p, %s) found %p via ..",
 			    dvp, cnp->cn_nameptr, *vpp);
+			SDT_PROBE(vfs, namecache, lookup, hit, dvp, "..",
+			    *vpp, 0, 0);
 			goto success;
 		}
 	}
@@ -394,6 +438,8 @@ retry_wlocked:
 
 	/* We failed to find an entry */
 	if (ncp == NULL) {
+		SDT_PROBE(vfs, namecache, lookup, miss, dvp, cnp->cn_nameptr,
+		    NULL, 0, 0);
 		if ((cnp->cn_flags & MAKEENTRY) == 0) {
 			nummisszap++;
 		} else {
@@ -421,6 +467,8 @@ retry_wlocked:
 		*vpp = ncp->nc_vp;
 		CTR4(KTR_VFS, "cache_lookup(%p, %s) found %p via ncp %p",
 		    dvp, cnp->cn_nameptr, *vpp, ncp);
+		SDT_PROBE(vfs, namecache, lookup, hit, dvp, ncp->nc_name,
+		    *vpp, 0, 0);
 		goto success;
 	}
 
@@ -449,6 +497,8 @@ retry_wlocked:
 	nchstats.ncs_neghits++;
 	if (ncp->nc_flag & NCF_WHITE)
 		cnp->cn_flags |= ISWHITEOUT;
+	SDT_PROBE(vfs, namecache, lookup, hit_negative, dvp, ncp->nc_name,
+	    0, 0, 0);
 	CACHE_WUNLOCK();
 	return (ENOENT);
 
@@ -579,6 +629,8 @@ cache_enter(dvp, vp, cnp)
 				}
 			}
 			dvp->v_cache_dd = NULL;
+			SDT_PROBE(vfs, namecache, enter, done, dvp, "..", vp,
+			    0, 0);
 			CACHE_WUNLOCK();
 			flag = NCF_ISDOTDOT;
 		}
@@ -597,7 +649,7 @@ cache_enter(dvp, vp, cnp)
 	ncp->nc_flag = flag;
 	len = ncp->nc_nlen = cnp->cn_namelen;
 	hash = fnv_32_buf(cnp->cn_nameptr, len, FNV1_32_INIT);
-	bcopy(cnp->cn_nameptr, ncp->nc_name, len);
+	strlcpy(ncp->nc_name, cnp->cn_nameptr, len + 1);
 	hash = fnv_32_buf(&dvp, sizeof(dvp), hash);
 	CACHE_WLOCK();
 
@@ -667,8 +719,12 @@ cache_enter(dvp, vp, cnp)
 	 */
 	if (vp) {
 		TAILQ_INSERT_HEAD(&vp->v_cache_dst, ncp, nc_dst);
+		SDT_PROBE(vfs, namecache, enter, done, dvp, ncp->nc_name, vp,
+		    0, 0);
 	} else {
 		TAILQ_INSERT_TAIL(&ncneg, ncp, nc_dst);
+		SDT_PROBE(vfs, namecache, enter_negative, done, dvp,
+		    ncp->nc_name, 0, 0, 0);
 	}
 	if (numneg * ncnegfactor > numcache) {
 		ncp = TAILQ_FIRST(&ncneg);
@@ -709,6 +765,7 @@ cache_purge(vp)
 {
 
 	CTR1(KTR_VFS, "cache_purge(%p)", vp);
+	SDT_PROBE(vfs, namecache, purge, done, vp, 0, 0, 0, 0);
 	CACHE_WLOCK();
 	while (!LIST_EMPTY(&vp->v_cache_src))
 		cache_zap(LIST_FIRST(&vp->v_cache_src));
@@ -733,6 +790,7 @@ cache_purge_negative(vp)
 	struct namecache *cp, *ncp;
 
 	CTR1(KTR_VFS, "cache_purge_negative(%p)", vp);
+	SDT_PROBE(vfs, namecache, purge_negative, done, vp, 0, 0, 0, 0);
 	CACHE_WLOCK();
 	LIST_FOREACH_SAFE(cp, &vp->v_cache_src, nc_src, ncp) {
 		if (cp->nc_vp == NULL)
@@ -752,6 +810,7 @@ cache_purgevfs(mp)
 	struct namecache *ncp, *nnp;
 
 	/* Scan hash tables for applicable entries */
+	SDT_PROBE(vfs, namecache, purgevfs, done, mp, 0, 0, 0, 0);
 	CACHE_WLOCK();
 	for (ncpp = &nchashtbl[nchash]; ncpp >= nchashtbl; ncpp--) {
 		LIST_FOREACH_SAFE(ncp, ncpp, nc_hash, nnp) {
@@ -998,6 +1057,9 @@ vn_fullpath1(struct thread *td, struct v
 	char *bp;
 	int error, i, slash_prefixed;
 	struct namecache *ncp;
+#ifdef KDTRACE_HOOKS
+	struct vnode *startvp = vp;
+#endif
 
 	buflen--;
 	bp = buf + buflen;
@@ -1005,6 +1067,7 @@ vn_fullpath1(struct thread *td, struct v
 	error = 0;
 	slash_prefixed = 0;
 
+	SDT_PROBE(vfs, namecache, fullpath, entry, vp, 0, 0, 0, 0);
 	CACHE_RLOCK();
 	numfullpathcalls++;
 	if (vp->v_type != VDIR) {
@@ -1016,18 +1079,31 @@ vn_fullpath1(struct thread *td, struct v
 			if (bp == buf) {
 				numfullpathfail4++;
 				CACHE_RUNLOCK();
-				return (ENOMEM);
+				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)
+			if (error) {
+				SDT_PROBE(vfs, namecache, fullpath, return,
+				    error, startvp, NULL, 0, 0);
 				return (error);
+			}
 		}
 		if (buflen <= 0) {
 			numfullpathfail4++;
 			CACHE_RUNLOCK();
-			return (ENOMEM);
+			error = ENOMEM;
+			SDT_PROBE(vfs, namecache, fullpath, return, error,
+			    startvp, NULL, 0, 0);
+			return (error);
 		}
 		*--bp = '/';
 		buflen--;
@@ -1062,8 +1138,12 @@ vn_fullpath1(struct thread *td, struct v
 				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;
@@ -1078,12 +1158,17 @@ vn_fullpath1(struct thread *td, struct v
 		buflen--;
 		slash_prefixed = 1;
 	}
-	if (error)
+	if (error) {
+		SDT_PROBE(vfs, namecache, fullpath, return, error, startvp,
+		    NULL, 0, 0);
 		return (error);
+	}
 	if (!slash_prefixed) {
 		if (bp == buf) {
 			numfullpathfail4++;
 			CACHE_RUNLOCK();
+			SDT_PROBE(vfs, namecache, fullpath, return, 0,
+			    startvp, bp, 0, 0);
 			return (ENOMEM);
 		} else
 			*--bp = '/';
@@ -1091,6 +1176,7 @@ vn_fullpath1(struct thread *td, struct v
 	numfullpathfound++;
 	CACHE_RUNLOCK();
 
+	SDT_PROBE(vfs, namecache, fullpath, return, 0, startvp, bp, 0, 0);
 	*retbuf = bp;
 	return (0);
 }


More information about the svn-src-all mailing list