Re2: file weirdness / vnlru process issues

Matthew Dillon dillon at apollo.backplane.com
Mon Oct 18 15:15:52 PDT 2004


    Here is a new patch set.  I missed a case in cache_nlookup().  The other
    patch will work but might still result in unnecessary vnlru process
    wakeups.

    The hysteresis is designed such that in a heavily loaded system only 1
    out of 10 calls to the namecache will eat cpu cycles cleaning up negative
    cache entries.

						-Matt

Index: sys/namecache.h
===================================================================
RCS file: /cvs/src/sys/sys/namecache.h,v
retrieving revision 1.13
diff -u -r1.13 namecache.h
--- sys/namecache.h	12 Oct 2004 19:20:48 -0000	1.13
+++ sys/namecache.h	18 Oct 2004 20:35:08 -0000
@@ -164,6 +164,7 @@
 void	cache_purge(struct vnode *vp);
 void	cache_purgevfs (struct mount *mp);
 int	cache_get_nonblock(struct namecache *ncp);
+void	cache_cleanneg(int count);
 struct namecache *cache_get(struct namecache *ncp);
 struct namecache *cache_hold(struct namecache *ncp);
 void	cache_put(struct namecache *ncp);
Index: kern/vfs_cache.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_cache.c,v
retrieving revision 1.38
diff -u -r1.38 vfs_cache.c
--- kern/vfs_cache.c	12 Oct 2004 19:20:46 -0000	1.38
+++ kern/vfs_cache.c	18 Oct 2004 21:58:16 -0000
@@ -777,6 +777,38 @@
 	--ncp->nc_refs;
 }
 
+static enum { CHI_LOW, CHI_HIGH } cache_hysteresis_state = CHI_LOW;
+
+static __inline
+void
+cache_hysteresis(void)
+{
+	/*
+	 * Don't cache too many negative hits.  We use hysteresis to reduce
+	 * the impact on the critical path.
+	 */
+	switch(cache_hysteresis_state) {
+	case CHI_LOW:
+		if (numneg > MINNEG && numneg * ncnegfactor > numcache) {
+			cache_cleanneg(10);
+			if (cache_hysteresis_state == CHI_LOW)
+				printf("H");
+			cache_hysteresis_state = CHI_HIGH;
+		}
+		break;
+	case CHI_HIGH:
+		if (numneg > MINNEG * 9 / 10 && 
+		    numneg * ncnegfactor * 9 / 10 > numcache
+		) {
+			cache_cleanneg(10);
+		} else {
+			cache_hysteresis_state = CHI_LOW;
+			printf("L");
+		}
+		break;
+	}
+}
+
 /*
  * NEW NAMECACHE LOOKUP API
  *
@@ -883,6 +915,7 @@
 	ncp->nc_flag |= NCF_HASHED;
 	cache_link_parent(ncp, par);
 found:
+	cache_hysteresis();
 	return(ncp);
 }
 
@@ -1388,15 +1421,35 @@
 			ncp->nc_flag |= NCF_WHITEOUT;
 	}
 	cache_put(ncp);
+	cache_hysteresis();
+}
+
+void
+cache_cleanneg(int count)
+{
+	struct namecache *ncp;
+
+	/*
+	 * Automode from the vnlru proc - clean out 10% of the negative cache
+	 * entries.
+	 */
+	if (count == 0) {
+		count = numneg / 10 + 1;
+		printf("X");
+	}
 
 	/*
-	 * Don't cache too many negative hits
+	 * Attempt to clean out the specified number of negative cache
+	 * entries.
 	 */
-	if (numneg > MINNEG && numneg * ncnegfactor > numcache) {
+	while (count) {
 		ncp = TAILQ_FIRST(&ncneglist);
 		KKASSERT(ncp != NULL);
+		TAILQ_REMOVE(&ncneglist, ncp, nc_vnode);
+		TAILQ_INSERT_TAIL(&ncneglist, ncp, nc_vnode);
 		if (cache_get_nonblock(ncp) == 0)
 			cache_zap(ncp);
+		--count;
 	}
 }
 
Index: kern/vfs_mount.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_mount.c,v
retrieving revision 1.1
diff -u -r1.1 vfs_mount.c
--- kern/vfs_mount.c	12 Oct 2004 19:20:46 -0000	1.1
+++ kern/vfs_mount.c	18 Oct 2004 20:34:52 -0000
@@ -470,6 +470,7 @@
 			continue;
 		}
 		done = 0;
+		cache_cleanneg(0);
 		lwkt_gettoken(&ilock, &mountlist_token);
 		for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
 			if (vfs_busy(mp, LK_NOWAIT, &ilock, td)) {





More information about the Bugs mailing list