aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Scheffenegger <rscheff@FreeBSD.org>2021-03-31 17:30:20 +0000
committerRichard Scheffenegger <rscheff@FreeBSD.org>2021-04-16 20:52:21 +0000
commitc0f8ed6ff81260fb4a26da354d3f06aaa83e74de (patch)
treef6d6b9c85b1e4154f2290173249c48d58a31aae4
parent12ce9e4868d1454b263a2330ce95e91b145c1c8f (diff)
downloadsrc-c0f8ed6ff81260fb4a26da354d3f06aaa83e74de.tar.gz
src-c0f8ed6ff81260fb4a26da354d3f06aaa83e74de.zip
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)
-rw-r--r--sys/netinet/tcp_hostcache.c20
-rw-r--r--sys/netinet/tcp_hostcache.h20
2 files changed, 22 insertions, 18 deletions
diff --git a/sys/netinet/tcp_hostcache.c b/sys/netinet/tcp_hostcache.c
index db68fd5de90d..5a7e3fb63c7e 100644
--- a/sys/netinet/tcp_hostcache.c
+++ b/sys/netinet/tcp_hostcache.c
@@ -146,8 +146,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,
@@ -196,7 +196,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;
@@ -264,6 +265,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);
@@ -371,7 +375,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
@@ -388,7 +392,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);
@@ -421,7 +425,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;
@@ -637,7 +641,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));
}
@@ -709,7 +713,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 f4e1013aac60..b5237392acc2 100644
--- a/sys/netinet/tcp_hostcache.h
+++ b/sys/netinet/tcp_hostcache.h
@@ -69,16 +69,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_*/