Module Name:    src
Committed By:   simonb
Date:           Thu Apr  1 06:23:15 UTC 2021

Modified Files:
        src/usr.bin/vmstat: vmstat.c

Log Message:
Use kernel sysctl hashstat collection instead of kmem grovelling
directly.  Also GC a few old hash nlist entries that no longer exist.


To generate a diff of this commit:
cvs rdiff -u -r1.244 -r1.245 src/usr.bin/vmstat/vmstat.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/vmstat/vmstat.c
diff -u src/usr.bin/vmstat/vmstat.c:1.244 src/usr.bin/vmstat/vmstat.c:1.245
--- src/usr.bin/vmstat/vmstat.c:1.244	Thu Apr  1 05:33:50 2021
+++ src/usr.bin/vmstat/vmstat.c	Thu Apr  1 06:23:14 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: vmstat.c,v 1.244 2021/04/01 05:33:50 simonb Exp $ */
+/* $NetBSD: vmstat.c,v 1.245 2021/04/01 06:23:14 simonb Exp $ */
 
 /*-
  * Copyright (c) 1998, 2000, 2001, 2007, 2019, 2020
@@ -71,7 +71,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 19
 #if 0
 static char sccsid[] = "@(#)vmstat.c	8.2 (Berkeley) 3/1/95";
 #else
-__RCSID("$NetBSD: vmstat.c,v 1.244 2021/04/01 05:33:50 simonb Exp $");
+__RCSID("$NetBSD: vmstat.c,v 1.245 2021/04/01 06:23:14 simonb Exp $");
 #endif
 #endif /* not lint */
 
@@ -113,6 +113,7 @@ __RCSID("$NetBSD: vmstat.c,v 1.244 2021/
 #include <nfs/nfsproto.h>
 #include <nfs/nfsnode.h>
 
+#include <assert.h>
 #include <ctype.h>
 #include <err.h>
 #include <errno.h>
@@ -207,31 +208,23 @@ struct nlist intrnl[] =
  */
 struct nlist hashnl[] =
 {
-#define	X_NFSNODE	0
-	{ .n_name = "_nfsnodehash" },
-#define	X_NFSNODETBL	1
-	{ .n_name = "_nfsnodehashtbl" },
-#define	X_IHASH		2
-	{ .n_name = "_ihash" },
-#define	X_IHASHTBL	3
-	{ .n_name = "_ihashtbl" },
-#define	X_BUFHASH	4
+#define	X_BUFHASH	0
 	{ .n_name = "_bufhash" },
-#define	X_BUFHASHTBL	5
+#define	X_BUFHASHTBL	1
 	{ .n_name = "_bufhashtbl" },
-#define	X_UIHASH	6
+#define	X_UIHASH	2
 	{ .n_name = "_uihash" },
-#define	X_UIHASHTBL	7
+#define	X_UIHASHTBL	3
 	{ .n_name = "_uihashtbl" },
-#define	X_IFADDRHASH	8
+#define	X_IFADDRHASH	4
 	{ .n_name = "_in_ifaddrhash" },
-#define	X_IFADDRHASHTBL	9
+#define	X_IFADDRHASHTBL	5
 	{ .n_name = "_in_ifaddrhashtbl" },
-#define	X_VCACHEHASH	10
+#define	X_VCACHEHASH	6
 	{ .n_name = "_vcache_hashmask" },
-#define	X_VCACHETBL	11
+#define	X_VCACHETBL	7
 	{ .n_name = "_vcache_hashtab" },
-#define X_HASHNL_SIZE	12	/* must be last */
+#define X_HASHNL_SIZE	8	/* must be last */
 	{ .n_name = NULL },
 };
 
@@ -300,6 +293,7 @@ void	deref_kptr(const void *, void *, si
 void	drvstats(int *);
 void	doevcnt(int verbose, int type);
 void	dohashstat(int, int, const char *);
+void	dohashstat_sysctl(int, int, const char *);
 void	dointr(int verbose);
 void	dopool(int, int);
 void	dopoolcache(int);
@@ -1925,6 +1919,9 @@ dohashstat(int verbose, int todo, const 
 	u_long	hashsize, i;
 	int	used, items, chain, maxchain;
 
+	if (memf == NULL)
+		return dohashstat_sysctl(verbose, todo, hashname);
+
 	hashbuf = NULL;
 	hashbufsize = 0;
 
@@ -2057,6 +2054,75 @@ dohashstat(int verbose, int todo, const 
 	}
 }
 
+void
+dohashstat_sysctl(int verbose, int todo, const char *hashname)
+{
+	struct hashstat_sysctl hash, *data, *hs;
+	int mib[3];
+	int error;
+	size_t i, len, miblen;
+
+
+	miblen = __arraycount(mib);
+	error = sysctlnametomib("kern.hashstat", mib, &miblen);
+	if (error)
+		err(EXIT_FAILURE, "nametomib kern.hashstat failed");
+	assert(miblen < 3);
+
+	if (todo & HASHLIST) {
+		mib[miblen] = CTL_DESCRIBE;
+		miblen++;
+	};
+
+	if (hashname) {
+		mib[miblen] = CTL_QUERY;
+		miblen++;
+		memset(&hash, 0, sizeof(hash));
+		strlcpy(hash.hash_name, hashname, sizeof(hash.hash_name));
+		len = sizeof(hash);
+		error = sysctl(mib, miblen, &hash, &len, &hash, len);
+		if (error == ENOENT) {
+			err(1, "hash '%s' not found", hashname);
+			return;
+		} else if (error) {
+			err(1, "sysctl kern.hashstat query failed");
+			return;
+		}
+
+		data = &hash;
+		len = 1;
+	} else {
+		data = asysctl(mib, miblen, &len);
+		if (data == NULL)
+			err(1, "failed to read kern.hashstat");
+		len /= sizeof(*data);
+	}
+
+	if (todo & HASHLIST) {
+		printf("Supported hashes:\n");
+		for (i = 0, hs = data; i < len; i++, hs++) {
+			printf("\t%-16s%s\n", hs->hash_name, hs->hash_desc);
+		}
+	} else {
+		printf("%-16s %8s %8s %8s %8s %8s %8s\n"
+		    "%-16s %8s %8s %8s %8s %8s %8s\n",
+		    "", "total", "used", "util", "num", "average", "maximum",
+		    "hash table", "buckets", "buckets", "%", "items", "chain",
+		    "chain");
+		for (i = 0, hs = data; i < len; i++, hs++) {
+			printf("%-16s %8"PRId64" %8"PRId64" %8.2f %8"PRId64
+			    " %8.2f %8"PRId64"\n",
+			    hs->hash_name, hs->hash_size, hs->hash_used,
+			    hs->hash_used * 100.0 / hs->hash_size, hs->hash_items,
+			    hs->hash_used ? (double)hs->hash_items / hs->hash_used : 0.0,
+			    hs->hash_maxchain);
+		}
+	}
+
+	if (!hashname && (data != NULL))
+		free(data);
+}
+
 /*
  * kreadc like kread but returns 1 if successful, 0 otherwise
  */
@@ -2254,7 +2320,7 @@ hist_traverse_sysctl(int todo, const cha
  			warnx("kernel history is not compiled into the kernel.");
 			return;
 		} else
-			err(EXIT_FAILURE, "nametomib failed");
+			err(EXIT_FAILURE, "nametomib kern.hist failed");
 	}
  
 	/* get the list of nodenames below kern.hist */

Reply via email to