Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 16 Apr 2021 22:12:00 GMT
From:      Richard Scheffenegger <rscheff@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: d20563819b92 - stable/11 - tcp: Make hostcache.cache_count MPSAFE by using a counter_u64_t
Message-ID:  <202104162212.13GMC0oD087210@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/11 has been updated by rscheff:

URL: https://cgit.FreeBSD.org/src/commit/?id=d20563819b9292ddcd42caf3449636b84825b1d6

commit d20563819b9292ddcd42caf3449636b84825b1d6
Author:     Richard Scheffenegger <rscheff@FreeBSD.org>
AuthorDate: 2021-03-31 17:30:20 +0000
Commit:     Richard Scheffenegger <rscheff@FreeBSD.org>
CommitDate: 2021-04-16 21:33:31 +0000

    tcp: Make hostcache.cache_count MPSAFE  by using a counter_u64_t
    
    Addressing the underlying root cause for cache_count to
    show unexpectedly high  values, by protecting all arithmetic on
    that global variable by using counter(9).
    
    PR:             254333
    Reviewed By: tuexen, #transport
    MFC after: 2 weeks
    Sponsored by: NetApp, Inc.
    Differential Revision: https://reviews.freebsd.org/D29510
    
    (cherry picked from commit 95e56d31e348594973affd0ea81d8f8383bc3031)
---
 sys/netinet/tcp_hostcache.c | 20 ++++++++++++--------
 sys/netinet/tcp_hostcache.h | 20 ++++++++++----------
 2 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/sys/netinet/tcp_hostcache.c b/sys/netinet/tcp_hostcache.c
index c4d51dd0bd59..0b5a212c4897 100644
--- a/sys/netinet/tcp_hostcache.c
+++ b/sys/netinet/tcp_hostcache.c
@@ -144,8 +144,8 @@ SYSCTL_UINT(_net_inet_tcp_hostcache, OID_AUTO, bucketlimit,
     CTLFLAG_VNET | CTLFLAG_RDTUN, &VNET_NAME(tcp_hostcache.bucket_limit), 0,
     "Per-bucket hash limit for hostcache");
 
-SYSCTL_UINT(_net_inet_tcp_hostcache, OID_AUTO, count, CTLFLAG_VNET | CTLFLAG_RD,
-     &VNET_NAME(tcp_hostcache.cache_count), 0,
+SYSCTL_COUNTER_U64(_net_inet_tcp_hostcache, OID_AUTO, count, CTLFLAG_VNET | CTLFLAG_RD,
+     &VNET_NAME(tcp_hostcache.cache_count),
     "Current number of entries in hostcache");
 
 SYSCTL_INT(_net_inet_tcp_hostcache, OID_AUTO, expire, CTLFLAG_VNET | CTLFLAG_RW,
@@ -194,7 +194,8 @@ tcp_hc_init(void)
 	/*
 	 * Initialize hostcache structures.
 	 */
-	V_tcp_hostcache.cache_count = 0;
+	V_tcp_hostcache.cache_count = counter_u64_alloc(M_WAITOK);
+	counter_u64_zero(V_tcp_hostcache.cache_count);
 	V_tcp_hostcache.hashsize = TCP_HOSTCACHE_HASHSIZE;
 	V_tcp_hostcache.bucket_limit = TCP_HOSTCACHE_BUCKETLIMIT;
 	V_tcp_hostcache.expire = TCP_HOSTCACHE_EXPIRE;
@@ -262,6 +263,9 @@ tcp_hc_destroy(void)
 	/* Purge all hc entries. */
 	tcp_hc_purge_internal(1);
 
+	/* Release the counter */
+	counter_u64_free(V_tcp_hostcache.cache_count);
+
 	/* Free the uma zone and the allocated hash table. */
 	uma_zdestroy(V_tcp_hostcache.zone);
 
@@ -369,7 +373,7 @@ tcp_hc_insert(struct in_conninfo *inc)
 	 * If the bucket limit is reached, reuse the least-used element.
 	 */
 	if (hc_head->hch_length >= V_tcp_hostcache.bucket_limit ||
-	    V_tcp_hostcache.cache_count >= V_tcp_hostcache.cache_limit) {
+	    counter_u64_fetch(V_tcp_hostcache.cache_count) >= V_tcp_hostcache.cache_limit) {
 		hc_entry = TAILQ_LAST(&hc_head->hch_bucket, hc_qhead);
 		/*
 		 * At first we were dropping the last element, just to
@@ -386,7 +390,7 @@ tcp_hc_insert(struct in_conninfo *inc)
 		}
 		TAILQ_REMOVE(&hc_head->hch_bucket, hc_entry, rmx_q);
 		V_tcp_hostcache.hashbase[hash].hch_length--;
-		V_tcp_hostcache.cache_count--;
+		counter_u64_add(V_tcp_hostcache.cache_count, -1);
 		TCPSTAT_INC(tcps_hc_bucketoverflow);
 #if 0
 		uma_zfree(V_tcp_hostcache.zone, hc_entry);
@@ -419,7 +423,7 @@ tcp_hc_insert(struct in_conninfo *inc)
 	 */
 	TAILQ_INSERT_HEAD(&hc_head->hch_bucket, hc_entry, rmx_q);
 	V_tcp_hostcache.hashbase[hash].hch_length++;
-	V_tcp_hostcache.cache_count++;
+	counter_u64_add(V_tcp_hostcache.cache_count, 1);
 	TCPSTAT_INC(tcps_hc_added);
 
 	return hc_entry;
@@ -633,7 +637,7 @@ sysctl_tcp_hc_list(SYSCTL_HANDLER_ARGS)
 
 	/* Optimize Buffer length query by sbin/sysctl */
 	if (req->oldptr == NULL) {
-		len = (V_tcp_hostcache.cache_count + 1) * linesize;
+		len = (counter_u64_fetch(V_tcp_hostcache.cache_count) + 1) * linesize;
 		return (SYSCTL_OUT(req, NULL, len));
 	}
 
@@ -705,7 +709,7 @@ tcp_hc_purge_internal(int all)
 					      hc_entry, rmx_q);
 				uma_zfree(V_tcp_hostcache.zone, hc_entry);
 				V_tcp_hostcache.hashbase[i].hch_length--;
-				V_tcp_hostcache.cache_count--;
+				counter_u64_add(V_tcp_hostcache.cache_count, -1);
 			} else
 				hc_entry->rmx_expire -= V_tcp_hostcache.prune;
 		}
diff --git a/sys/netinet/tcp_hostcache.h b/sys/netinet/tcp_hostcache.h
index 44875ff68f6e..4eddfaa806c5 100644
--- a/sys/netinet/tcp_hostcache.h
+++ b/sys/netinet/tcp_hostcache.h
@@ -67,16 +67,16 @@ struct hc_metrics {
 };
 
 struct tcp_hostcache {
-	struct	hc_head *hashbase;
-	uma_zone_t zone;
-	u_int	hashsize;
-	u_int	hashmask;
-	u_int	bucket_limit;
-	u_int	cache_count;
-	u_int	cache_limit;
-	int	expire;
-	int	prune;
-	int	purgeall;
+	struct hc_head	*hashbase;
+	uma_zone_t	zone;
+	u_int		hashsize;
+	u_int		hashmask;
+	u_int		bucket_limit;
+	counter_u64_t	cache_count;
+	u_int		cache_limit;
+	int		expire;
+	int		prune;
+	int		purgeall;
 };
 
 #endif /* !_NETINET_TCP_HOSTCACHE_H_*/



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