Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 19 Oct 2020 18:51:51 +0000 (UTC)
From:      Mateusz Guzik <mjg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r366846 - head/sys/kern
Message-ID:  <202010191851.09JIpp1G016435@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mjg
Date: Mon Oct 19 18:51:51 2020
New Revision: 366846
URL: https://svnweb.freebsd.org/changeset/base/366846

Log:
  cache: promote negative entries based on more than one hit
  
  During tinderbox and similar workloads negative entries get at least one
  hit before they get evicted. In the current scheme this avoidably promotes
  them.
  
  Be conservative and stick to 2 hits for now.

Modified:
  head/sys/kern/vfs_cache.c

Modified: head/sys/kern/vfs_cache.c
==============================================================================
--- head/sys/kern/vfs_cache.c	Mon Oct 19 18:24:06 2020	(r366845)
+++ head/sys/kern/vfs_cache.c	Mon Oct 19 18:51:51 2020	(r366846)
@@ -129,6 +129,7 @@ SDT_PROBE_DECLARE(vfs, namei, lookup, return);
  */
 struct negstate {
 	u_char neg_flag;
+	u_char neg_hit;
 };
 _Static_assert(sizeof(struct negstate) <= sizeof(struct vnode *),
     "the state must fit in a union with a pointer without growing it");
@@ -905,18 +906,27 @@ cache_neg_init(struct namecache *ncp)
 	ncp->nc_flag |= NCF_NEGATIVE;
 	ns = NCP2NEGSTATE(ncp);
 	ns->neg_flag = 0;
+	ns->neg_hit = 0;
 	counter_u64_add(neg_created, 1);
 }
 
+#define CACHE_NEG_PROMOTION_THRESH 2
+
 static bool
 cache_neg_hit_prep(struct namecache *ncp)
 {
 	struct negstate *ns;
+	u_char n;
 
 	ns = NCP2NEGSTATE(ncp);
-	if ((ns->neg_flag & NEG_HOT) != 0)
-		return (true);
-	return (false);
+	n = atomic_load_char(&ns->neg_hit);
+	for (;;) {
+		if (n >= CACHE_NEG_PROMOTION_THRESH)
+			return (false);
+		if (atomic_fcmpset_8(&ns->neg_hit, &n, n + 1))
+			break;
+	}
+	return (n + 1 == CACHE_NEG_PROMOTION_THRESH);
 }
 
 /*
@@ -971,6 +981,7 @@ cache_neg_demote_locked(struct namecache *ncp)
 	TAILQ_INSERT_TAIL(&nl->nl_list, ncp, nc_dst);
 	nl->nl_hotnum--;
 	ns->neg_flag &= ~NEG_HOT;
+	atomic_store_char(&ns->neg_hit, 0);
 }
 
 /*
@@ -1098,7 +1109,7 @@ cache_neg_remove(struct namecache *ncp)
 }
 
 static struct neglist *
-cache_neg_evict_select(void)
+cache_neg_evict_select_list(void)
 {
 	struct neglist *nl;
 	u_int c;
@@ -1112,6 +1123,33 @@ cache_neg_evict_select(void)
 	return (nl);
 }
 
+static struct namecache *
+cache_neg_evict_select_entry(struct neglist *nl)
+{
+	struct namecache *ncp, *lncp;
+	struct negstate *ns, *lns;
+	int i;
+
+	mtx_assert(&nl->nl_evict_lock, MA_OWNED);
+	mtx_assert(&nl->nl_lock, MA_OWNED);
+	ncp = TAILQ_FIRST(&nl->nl_list);
+	if (ncp == NULL)
+		return (NULL);
+	lncp = ncp;
+	lns = NCP2NEGSTATE(lncp);
+	for (i = 1; i < 4; i++) {
+		ncp = TAILQ_NEXT(ncp, nc_dst);
+		if (ncp == NULL)
+			break;
+		ns = NCP2NEGSTATE(ncp);
+		if (ns->neg_hit < lns->neg_hit) {
+			lncp = ncp;
+			lns = ns;
+		}
+	}
+	return (lncp);
+}
+
 static bool
 cache_neg_evict(void)
 {
@@ -1125,7 +1163,7 @@ cache_neg_evict(void)
 	u_char nlen;
 	bool evicted;
 
-	nl = cache_neg_evict_select();
+	nl = cache_neg_evict_select_list();
 	if (nl == NULL) {
 		return (false);
 	}
@@ -1135,7 +1173,7 @@ cache_neg_evict(void)
 	if (ncp != NULL) {
 		cache_neg_demote_locked(ncp);
 	}
-	ncp = TAILQ_FIRST(&nl->nl_list);
+	ncp = cache_neg_evict_select_entry(nl);
 	if (ncp == NULL) {
 		counter_u64_add(neg_evict_skipped_empty, 1);
 		mtx_unlock(&nl->nl_lock);



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