Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/ad-namecache]: src/sys/kern Resurrect the counter stuff from HEAD, which...
details: https://anonhg.NetBSD.org/src/rev/eac344ef4100
branches: ad-namecache
changeset: 746115:eac344ef4100
user: ad <ad%NetBSD.org@localhost>
date: Sun Mar 22 14:16:50 2020 +0000
description:
Resurrect the counter stuff from HEAD, which tries to deal with 32-bit
counter rollover. Drive it by sysctl and/or callout every 5 minutes,
since there's no garbage collection kthread any more.
diffstat:
sys/kern/vfs_cache.c | 99 +++++++++++++++++++++++++++++++++++----------------
1 files changed, 67 insertions(+), 32 deletions(-)
diffs (191 lines):
diff -r e70ceff4577d -r eac344ef4100 sys/kern/vfs_cache.c
--- a/sys/kern/vfs_cache.c Sun Mar 22 01:58:22 2020 +0000
+++ b/sys/kern/vfs_cache.c Sun Mar 22 14:16:50 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_cache.c,v 1.126.2.16 2020/03/22 01:58:22 ad Exp $ */
+/* $NetBSD: vfs_cache.c,v 1.126.2.17 2020/03/22 14:16:50 ad Exp $ */
/*-
* Copyright (c) 2008, 2019, 2020 The NetBSD Foundation, Inc.
@@ -153,9 +153,10 @@
* and the definition of "struct vnode" for the particulars.
*
* Per-CPU statistics, and LRU list totals are read unlocked, since
- * an approximate value is OK. We maintain uintptr_t sized per-CPU
- * counters and 64-bit global counters under the theory that uintptr_t
- * sized counters are less likely to be hosed by nonatomic increment.
+ * an approximate value is OK. We maintain 32-bit sized per-CPU
+ * counters and 64-bit global counters under the theory that 32-bit
+ * sized counters are less likely to be hosed by nonatomic increment
+ * (on 32-bit platforms).
*
* The lock order is:
*
@@ -171,7 +172,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.126.2.16 2020/03/22 01:58:22 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.126.2.17 2020/03/22 14:16:50 ad Exp $");
#define __NAMECACHE_PRIVATE
#ifdef _KERNEL_OPT
@@ -180,6 +181,8 @@
#endif
#include <sys/types.h>
+#include <sys/atomic.h>
+#include <sys/callout.h>
#include <sys/cpu.h>
#include <sys/errno.h>
#include <sys/evcnt.h>
@@ -199,15 +202,13 @@
#include <miscfs/genfs/genfs.h>
static void cache_activate(struct namecache *);
+static void cache_update_stats(void *);
static int cache_compare_key(void *, const void *, const void *);
static int cache_compare_nodes(void *, const void *, const void *);
static void cache_deactivate(void);
static void cache_reclaim(void);
static int cache_stat_sysctl(SYSCTLFN_ARGS);
-/* Per-CPU counters. */
-struct nchstats_percpu _NAMEI_CACHE_STATS(uintptr_t);
-
/* Global pool cache. */
static pool_cache_t cache_pool __read_mostly;
@@ -225,8 +226,15 @@
static kmutex_t cache_lru_lock __cacheline_aligned;
-/* Cache effectiveness statistics. This holds total from per-cpu stats */
-struct nchstats nchstats __cacheline_aligned;
+/* Cache effectiveness statistics. nchstats holds system-wide total. */
+struct nchstats nchstats;
+struct nchstats_percpu _NAMEI_CACHE_STATS(uint32_t);
+struct nchcpu {
+ struct nchstats_percpu cur;
+ struct nchstats_percpu last;
+};
+static callout_t cache_stat_callout;
+static kmutex_t cache_stat_lock __cacheline_aligned;
#define COUNT(f) do { \
lwp_t *l = curlwp; \
@@ -235,6 +243,12 @@
KPREEMPT_ENABLE(l); \
} while (/* CONSTCOND */ 0);
+#define UPDATE(nchcpu, f) do { \
+ uint32_t cur = atomic_load_relaxed(&nchcpu->cur.f); \
+ nchstats.f += cur - nchcpu->last.f; \
+ nchcpu->last.f = cur; \
+} while (/* CONSTCOND */ 0)
+
/*
* Tunables. cache_maxlen replaces the historical doingcache:
* set it zero to disable caching for debugging purposes.
@@ -242,6 +256,7 @@
int cache_lru_maxdeact __read_mostly = 2; /* max # to deactivate */
int cache_lru_maxscan __read_mostly = 64; /* max # to scan/reclaim */
int cache_maxlen __read_mostly = USHRT_MAX; /* max name length to cache */
+int cache_stat_interval __read_mostly = 300; /* in seconds */
/* sysctl */
static struct sysctllog *cache_sysctllog;
@@ -1000,6 +1015,11 @@
TAILQ_INIT(&cache_lru.list[LRU_ACTIVE]);
TAILQ_INIT(&cache_lru.list[LRU_INACTIVE]);
+ mutex_init(&cache_stat_lock, MUTEX_DEFAULT, IPL_NONE);
+ callout_init(&cache_stat_callout, CALLOUT_MPSAFE);
+ callout_setfunc(&cache_stat_callout, cache_update_stats, NULL);
+ callout_schedule(&cache_stat_callout, cache_stat_interval * hz);
+
KASSERT(cache_sysctllog == NULL);
sysctl_createv(&cache_sysctllog, 0, NULL, NULL,
CTLFLAG_PERMANENT,
@@ -1362,6 +1382,41 @@
}
/*
+ * Sum the stats from all CPUs into nchstats. This needs to run at least
+ * once within every window where a 32-bit counter could roll over. It's
+ * called regularly by timer to ensure this.
+ */
+static void
+cache_update_stats(void *cookie)
+{
+ CPU_INFO_ITERATOR cii;
+ struct cpu_info *ci;
+
+ mutex_enter(&cache_stat_lock);
+ for (CPU_INFO_FOREACH(cii, ci)) {
+ struct nchcpu *nchcpu = ci->ci_data.cpu_nch;
+ UPDATE(nchcpu, ncs_goodhits);
+ UPDATE(nchcpu, ncs_neghits);
+ UPDATE(nchcpu, ncs_badhits);
+ UPDATE(nchcpu, ncs_falsehits);
+ UPDATE(nchcpu, ncs_miss);
+ UPDATE(nchcpu, ncs_long);
+ UPDATE(nchcpu, ncs_pass2);
+ UPDATE(nchcpu, ncs_2passes);
+ UPDATE(nchcpu, ncs_revhits);
+ UPDATE(nchcpu, ncs_revmiss);
+ UPDATE(nchcpu, ncs_collisions);
+ UPDATE(nchcpu, ncs_denied);
+ }
+ if (cookie != NULL) {
+ memcpy(cookie, &nchstats, sizeof(nchstats));
+ }
+ /* Reset the timer; arrive back here in N minutes at latest. */
+ callout_schedule(&cache_stat_callout, cache_stat_interval * hz);
+ mutex_exit(&cache_stat_lock);
+}
+
+/*
* Fetch the current values of the stats. We return the most
* recent values harvested into nchstats by cache_reclaim(), which
* will be less than a second old.
@@ -1369,9 +1424,7 @@
static int
cache_stat_sysctl(SYSCTLFN_ARGS)
{
- CPU_INFO_ITERATOR cii;
struct nchstats stats;
- struct cpu_info *ci;
if (oldp == NULL) {
*oldlenp = sizeof(nchstats);
@@ -1383,27 +1436,9 @@
return 0;
}
+ /* Refresh the global stats. */
sysctl_unlock();
- memset(&stats, 0, sizeof(nchstats));
- for (CPU_INFO_FOREACH(cii, ci)) {
- struct nchstats_percpu *np = ci->ci_data.cpu_nch;
-
- stats.ncs_goodhits += np->ncs_goodhits;
- stats.ncs_neghits += np->ncs_neghits;
- stats.ncs_badhits += np->ncs_badhits;
- stats.ncs_falsehits += np->ncs_falsehits;
- stats.ncs_miss += np->ncs_miss;
- stats.ncs_long += np->ncs_long;
- stats.ncs_pass2 += np->ncs_pass2;
- stats.ncs_2passes += np->ncs_2passes;
- stats.ncs_revhits += np->ncs_revhits;
- stats.ncs_revmiss += np->ncs_revmiss;
- stats.ncs_collisions += np->ncs_collisions;
- stats.ncs_denied += np->ncs_denied;
- }
- mutex_enter(&cache_lru_lock);
- memcpy(&nchstats, &stats, sizeof(nchstats));
- mutex_exit(&cache_lru_lock);
+ cache_update_stats(&stats);
sysctl_relock();
*oldlenp = MIN(sizeof(stats), *oldlenp);
Home |
Main Index |
Thread Index |
Old Index