Tue Jun 3 21:16:15 2014 UTC ()
Provide sysctl for namecache statistics.


(joerg)
diff -r1.96 -r1.97 src/sys/kern/vfs_cache.c
diff -r1.32 -r1.33 src/sys/sys/namei.src
diff -r1.77 -r1.78 src/usr.bin/systat/vmstat.c
diff -r1.193 -r1.194 src/usr.bin/vmstat/vmstat.c

cvs diff -r1.96 -r1.97 src/sys/kern/vfs_cache.c (expand / switch to context diff)
--- src/sys/kern/vfs_cache.c 2014/06/03 19:42:17 1.96
+++ src/sys/kern/vfs_cache.c 2014/06/03 21:16:15 1.97
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_cache.c,v 1.96 2014/06/03 19:42:17 joerg Exp $	*/
+/*	$NetBSD: vfs_cache.c,v 1.97 2014/06/03 21:16:15 joerg Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -58,13 +58,14 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.96 2014/06/03 19:42:17 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.97 2014/06/03 21:16:15 joerg Exp $");
 
 #include "opt_ddb.h"
 #include "opt_revcache.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/sysctl.h>
 #include <sys/time.h>
 #include <sys/mount.h>
 #include <sys/vnode.h>
@@ -1097,4 +1098,50 @@
 	mutex_enter(&cpup->cpu_lock);
 	COUNT(cpup->cpu_stats, ncs_2passes);
 	mutex_exit(&cpup->cpu_lock);
+}
+
+static int
+cache_stat_sysctl(SYSCTLFN_ARGS)
+{
+	struct nchstats_sysctl stats;
+
+	if (oldp == NULL) {
+		*oldlenp = sizeof(stats);
+		return 0;
+	}
+
+	if (*oldlenp < sizeof(stats)) {
+		*oldlenp = 0;
+		return 0;
+	}
+
+	memset(&stats, 0, sizeof(stats));
+
+	sysctl_unlock();
+	cache_lock_cpus();
+	stats.ncs_goodhits = nchstats.ncs_goodhits;
+	stats.ncs_neghits = nchstats.ncs_neghits;
+	stats.ncs_badhits = nchstats.ncs_badhits;
+	stats.ncs_falsehits = nchstats.ncs_falsehits;
+	stats.ncs_miss = nchstats.ncs_miss;
+	stats.ncs_long = nchstats.ncs_long;
+	stats.ncs_pass2 = nchstats.ncs_pass2;
+	stats.ncs_2passes = nchstats.ncs_2passes;
+	stats.ncs_revhits = nchstats.ncs_revhits;
+	stats.ncs_revmiss = nchstats.ncs_revmiss;
+	cache_unlock_cpus();
+	sysctl_relock();
+
+	*oldlenp = sizeof(stats);
+	return sysctl_copyout(l, &stats, oldp, sizeof(stats));
+}
+
+SYSCTL_SETUP(sysctl_cache_stat_setup, "vfs.namecache_stats subtree setup")
+{
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_STRUCT, "namecache_stats",
+		       SYSCTL_DESCR("namecache statistics"),
+		       cache_stat_sysctl, 0, NULL, 0,
+		       CTL_VFS, CTL_CREATE, CTL_EOL);
 }

cvs diff -r1.32 -r1.33 src/sys/sys/namei.src (expand / switch to context diff)
--- src/sys/sys/namei.src 2014/06/03 19:30:29 1.32
+++ src/sys/sys/namei.src 2014/06/03 21:16:15 1.33
@@ -1,4 +1,4 @@
-/*	$NetBSD: namei.src,v 1.32 2014/06/03 19:30:29 joerg Exp $	*/
+/*	$NetBSD: namei.src,v 1.33 2014/06/03 21:16:15 joerg Exp $	*/
 
 /*
  * Copyright (c) 1985, 1989, 1991, 1993
@@ -302,6 +302,19 @@
 	long	ncs_2passes;		/* number of times we attempt it */
 	long	ncs_revhits;		/* reverse-cache hits */
 	long	ncs_revmiss;		/* reverse-cache misses */
+};
+
+struct	nchstats_sysctl {
+	uint64_t ncs_goodhits;		/* hits that we can really use */
+	uint64_t ncs_neghits;		/* negative hits that we can use */
+	uint64_t ncs_badhits;		/* hits we must drop */
+	uint64_t ncs_falsehits;		/* hits with id mismatch */
+	uint64_t ncs_miss;		/* misses */
+	uint64_t ncs_long;		/* long names that ignore cache */
+	uint64_t ncs_pass2;		/* names found with passes == 2 */
+	uint64_t ncs_2passes;		/* number of times we attempt it */
+	uint64_t ncs_revhits;		/* reverse-cache hits */
+	uint64_t ncs_revmiss;		/* reverse-cache misses */
 };
 
 #ifdef _KERNEL

cvs diff -r1.77 -r1.78 src/usr.bin/systat/vmstat.c (expand / switch to context diff)
--- src/usr.bin/systat/vmstat.c 2010/04/30 16:21:05 1.77
+++ src/usr.bin/systat/vmstat.c 2014/06/03 21:16:15 1.78
@@ -1,4 +1,4 @@
-/*	$NetBSD: vmstat.c,v 1.77 2010/04/30 16:21:05 njoly Exp $	*/
+/*	$NetBSD: vmstat.c,v 1.78 2014/06/03 21:16:15 joerg Exp $	*/
 
 /*-
  * Copyright (c) 1983, 1989, 1992, 1993
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)vmstat.c	8.2 (Berkeley) 1/12/94";
 #endif
-__RCSID("$NetBSD: vmstat.c,v 1.77 2010/04/30 16:21:05 njoly Exp $");
+__RCSID("$NetBSD: vmstat.c,v 1.78 2014/06/03 21:16:15 joerg Exp $");
 #endif /* not lint */
 
 /*
@@ -63,7 +63,7 @@
 static struct Info {
 	struct	uvmexp_sysctl uvmexp;
 	struct	vmtotal Total;
-	struct	nchstats nchstats;
+	struct	nchstats_sysctl nchstats;
 	long	nchcount;
 	long	*intrcnt;
 	u_int64_t	*evcnt;
@@ -776,7 +776,12 @@
 
 	cpureadstats();
 	drvreadstats();
-	NREAD(X_NCHSTATS, &stats->nchstats, sizeof stats->nchstats);
+	size = sizeof(stats->nchstats);
+	if (sysctlbyname("vfs.namecache_stats", &stats->nchstats, &size,
+	    NULL, 0) < 0) {
+		error("can't get namecache statistics: %s\n", strerror(errno));
+		memset(&stats->nchstats, 0, sizeof(stats->nchstats));
+	}
 	if (nintr)
 		NREAD(X_INTRCNT, stats->intrcnt, nintr * LONG);
 	for (i = 0; i < nevcnt; i++)

cvs diff -r1.193 -r1.194 src/usr.bin/vmstat/vmstat.c (expand / switch to context diff)
--- src/usr.bin/vmstat/vmstat.c 2014/06/02 19:16:10 1.193
+++ src/usr.bin/vmstat/vmstat.c 2014/06/03 21:16:15 1.194
@@ -1,4 +1,4 @@
-/* $NetBSD: vmstat.c,v 1.193 2014/06/02 19:16:10 joerg Exp $ */
+/* $NetBSD: vmstat.c,v 1.194 2014/06/03 21:16:15 joerg Exp $ */
 
 /*-
  * Copyright (c) 1998, 2000, 2001, 2007 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
 #if 0
 static char sccsid[] = "@(#)vmstat.c	8.2 (Berkeley) 3/1/95";
 #else
-__RCSID("$NetBSD: vmstat.c,v 1.193 2014/06/02 19:16:10 joerg Exp $");
+__RCSID("$NetBSD: vmstat.c,v 1.194 2014/06/03 21:16:15 joerg Exp $");
 #endif
 #endif /* not lint */
 
@@ -848,8 +848,8 @@
 void
 dosum(void)
 {
-	struct nchstats nchstats;
-	u_long nchtotal;
+	struct nchstats_sysctl nch_stats;
+	uint64_t nchtotal;
 	struct uvmexp_sysctl uvmexp2;
 	size_t ssize;
 	int active_kernel;
@@ -965,28 +965,51 @@
 	(void)printf("%9u total pending pageouts\n", uvmexp.pdpending);
 	(void)printf("%9u pages deactivated\n", uvmexp.pddeact);
 
-	kread(namelist, X_NCHSTATS, &nchstats, sizeof(nchstats));
-	nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
-	    nchstats.ncs_badhits + nchstats.ncs_falsehits +
-	    nchstats.ncs_miss + nchstats.ncs_long;
-	(void)printf("%9lu total name lookups\n", nchtotal);
-	(void)printf("%9lu good hits\n", nchstats.ncs_goodhits);
-	(void)printf("%9lu negative hits\n", nchstats.ncs_neghits);
-	(void)printf("%9lu bad hits\n", nchstats.ncs_badhits);
-	(void)printf("%9lu false hits\n", nchstats.ncs_falsehits);
-	(void)printf("%9lu miss\n", nchstats.ncs_miss);
-	(void)printf("%9lu too long\n", nchstats.ncs_long);
-	(void)printf("%9lu pass2 hits\n", nchstats.ncs_pass2);
-	(void)printf("%9lu 2passes\n", nchstats.ncs_2passes);
+	if (active_kernel) {
+		ssize = sizeof(nch_stats);
+		if (sysctlbyname("vfs.namecache_stats", &nch_stats, &ssize,
+		    NULL, 0)) {
+			warn("vfs.namecache_stats failed");
+			memset(&nch_stats, 0, sizeof(nch_stats));
+		}
+	} else {
+		struct nchstats nch_stats_kvm;
+
+		kread(namelist, X_NCHSTATS, &nch_stats_kvm,
+		    sizeof(nch_stats_kvm));
+		nch_stats.ncs_goodhits = nch_stats_kvm.ncs_goodhits;
+		nch_stats.ncs_neghits = nch_stats_kvm.ncs_neghits;
+		nch_stats.ncs_badhits = nch_stats_kvm.ncs_badhits;
+		nch_stats.ncs_falsehits = nch_stats_kvm.ncs_falsehits;
+		nch_stats.ncs_miss = nch_stats_kvm.ncs_miss;
+		nch_stats.ncs_long = nch_stats_kvm.ncs_long;
+		nch_stats.ncs_pass2 = nch_stats_kvm.ncs_pass2;
+		nch_stats.ncs_2passes = nch_stats_kvm.ncs_2passes;
+		nch_stats.ncs_revhits = nch_stats_kvm.ncs_revhits;
+		nch_stats.ncs_revmiss = nch_stats_kvm.ncs_revmiss;
+	}
+
+	nchtotal = nch_stats.ncs_goodhits + nch_stats.ncs_neghits +
+	    nch_stats.ncs_badhits + nch_stats.ncs_falsehits +
+	    nch_stats.ncs_miss + nch_stats.ncs_long;
+	(void)printf("%9" PRIu64 " total name lookups\n", nchtotal);
+	(void)printf("%9" PRIu64 " good hits\n", nch_stats.ncs_goodhits);
+	(void)printf("%9" PRIu64 " negative hits\n", nch_stats.ncs_neghits);
+	(void)printf("%9" PRIu64 " bad hits\n", nch_stats.ncs_badhits);
+	(void)printf("%9" PRIu64 " false hits\n", nch_stats.ncs_falsehits);
+	(void)printf("%9" PRIu64 " miss\n", nch_stats.ncs_miss);
+	(void)printf("%9" PRIu64 " too long\n", nch_stats.ncs_long);
+	(void)printf("%9" PRIu64 " pass2 hits\n", nch_stats.ncs_pass2);
+	(void)printf("%9" PRIu64 " 2passes\n", nch_stats.ncs_2passes);
 	(void)printf(
 	    "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n",
-	    "", PCT(nchstats.ncs_goodhits, nchtotal),
-	    PCT(nchstats.ncs_neghits, nchtotal),
-	    PCT(nchstats.ncs_pass2, nchtotal));
+	    "", PCT(nch_stats.ncs_goodhits, nchtotal),
+	    PCT(nch_stats.ncs_neghits, nchtotal),
+	    PCT(nch_stats.ncs_pass2, nchtotal));
 	(void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
-	    PCT(nchstats.ncs_badhits, nchtotal),
-	    PCT(nchstats.ncs_falsehits, nchtotal),
-	    PCT(nchstats.ncs_long, nchtotal));
+	    PCT(nch_stats.ncs_badhits, nchtotal),
+	    PCT(nch_stats.ncs_falsehits, nchtotal),
+	    PCT(nch_stats.ncs_long, nchtotal));
 }
 
 void