summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/vfs_cache.c80
-rw-r--r--sys/nfs/nfs_node.c79
-rw-r--r--sys/nfsclient/nfs_node.c79
3 files changed, 238 insertions, 0 deletions
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index 3459917..bf792cd 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -137,6 +137,86 @@ static MALLOC_DEFINE(M_VFSCACHE, "vfscache", "VFS name cache entries");
* Flags in namecache.nc_flag
*/
#define NCF_WHITE 1
+
+/*
+ * Grab an atomic snapshot of the name cache hash chain lengths
+ */
+SYSCTL_NODE(_debug, OID_AUTO, hashstat, CTLFLAG_RW, NULL, "hash table stats");
+
+static int
+sysctl_debug_hashstat_rawnchash(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ struct nchashhead *ncpp;
+ struct namecache *ncp;
+ int n_nchash;
+ int count;
+
+ n_nchash = nchash + 1; /* nchash is max index, not count */
+ if (!req->oldptr)
+ return SYSCTL_OUT(req, 0, n_nchash * sizeof(int));
+
+ /* Scan hash tables for applicable entries */
+ for (ncpp = nchashtbl; n_nchash > 0; n_nchash--, ncpp++) {
+ count = 0;
+ LIST_FOREACH(ncp, ncpp, nc_hash) {
+ count++;
+ }
+ error = SYSCTL_OUT(req, (caddr_t)&count, sizeof(count));
+ if (error)
+ return (error);
+ }
+ return (0);
+}
+SYSCTL_PROC(_debug_hashstat, OID_AUTO, rawnchash, CTLTYPE_INT|CTLFLAG_RD,
+ 0, 0, sysctl_debug_hashstat_rawnchash, "S,int", "nchash chain lengths");
+
+static int
+sysctl_debug_hashstat_nchash(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ struct nchashhead *ncpp;
+ struct namecache *ncp;
+ int n_nchash;
+ int count, maxlength, used, pct;
+
+ if (!req->oldptr)
+ return SYSCTL_OUT(req, 0, 4 * sizeof(int));
+
+ n_nchash = nchash + 1; /* nchash is max index, not count */
+ used = 0;
+ maxlength = 0;
+
+ /* Scan hash tables for applicable entries */
+ for (ncpp = nchashtbl; n_nchash > 0; n_nchash--, ncpp++) {
+ count = 0;
+ LIST_FOREACH(ncp, ncpp, nc_hash) {
+ count++;
+ }
+ if (count)
+ used++;
+ if (maxlength < count)
+ maxlength = count;
+ }
+ n_nchash = nchash + 1;
+ pct = (used * 100 * 100) / n_nchash;
+ error = SYSCTL_OUT(req, (caddr_t)&n_nchash, sizeof(n_nchash));
+ if (error)
+ return (error);
+ error = SYSCTL_OUT(req, (caddr_t)&used, sizeof(used));
+ if (error)
+ return (error);
+ error = SYSCTL_OUT(req, (caddr_t)&maxlength, sizeof(maxlength));
+ if (error)
+ return (error);
+ error = SYSCTL_OUT(req, (caddr_t)&pct, sizeof(pct));
+ if (error)
+ return (error);
+ return (0);
+}
+SYSCTL_PROC(_debug_hashstat, OID_AUTO, nchash, CTLTYPE_INT|CTLFLAG_RD,
+ 0, 0, sysctl_debug_hashstat_nchash, "I", "nchash chain lengths");
+
/*
* Delete an entry from its hash list and move it to the front
* of the LRU list for immediate reuse.
diff --git a/sys/nfs/nfs_node.c b/sys/nfs/nfs_node.c
index a82ad11..0191b66 100644
--- a/sys/nfs/nfs_node.c
+++ b/sys/nfs/nfs_node.c
@@ -45,6 +45,7 @@
#include <sys/vnode.h>
#include <sys/malloc.h>
#include <sys/fnv_hash.h>
+#include <sys/sysctl.h>
#include <vm/vm_zone.h>
@@ -62,6 +63,84 @@ static u_long nfsnodehash;
#define FALSE 0
/*
+ * Grab an atomic snapshot of the nfsnode hash chain lengths
+ */
+SYSCTL_DECL(_debug_hashstat);
+static int
+sysctl_debug_hashstat_rawnfsnode(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ struct nfsnodehashhead *nnpp;
+ struct nfsnode *nnp;
+ int n_nfsnode;
+ int count;
+
+ n_nfsnode = nfsnodehash + 1; /* nfsnodehash = max index, not count */
+ if (!req->oldptr)
+ return SYSCTL_OUT(req, 0, n_nfsnode * sizeof(int));
+
+ /* Scan hash tables for applicable entries */
+ for (nnpp = nfsnodehashtbl; n_nfsnode > 0; n_nfsnode--, nnpp++) {
+ count = 0;
+ LIST_FOREACH(nnp, nnpp, n_hash) {
+ count++;
+ }
+ error = SYSCTL_OUT(req, (caddr_t)&count, sizeof(count));
+ if (error)
+ return (error);
+ }
+ return (0);
+}
+SYSCTL_PROC(_debug_hashstat, OID_AUTO, rawnfsnode, CTLTYPE_INT|CTLFLAG_RD,
+ 0, 0, sysctl_debug_hashstat_rawnfsnode, "S,int", "nfsnode chain lengths");
+
+static int
+sysctl_debug_hashstat_nfsnode(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ struct nfsnodehashhead *nnpp;
+ struct nfsnode *nnp;
+ int n_nfsnode;
+ int count, maxlength, used, pct;
+
+ if (!req->oldptr)
+ return SYSCTL_OUT(req, 0, 4 * sizeof(int));
+
+ n_nfsnode = nfsnodehash + 1; /* nfsnodehash = max index, not count */
+ used = 0;
+ maxlength = 0;
+
+ /* Scan hash tables for applicable entries */
+ for (nnpp = nfsnodehashtbl; n_nfsnode > 0; n_nfsnode--, nnpp++) {
+ count = 0;
+ LIST_FOREACH(nnp, nnpp, n_hash) {
+ count++;
+ }
+ if (count)
+ used++;
+ if (maxlength < count)
+ maxlength = count;
+ }
+ n_nfsnode = nfsnodehash + 1;
+ pct = (used * 100 * 100) / n_nfsnode;
+ error = SYSCTL_OUT(req, (caddr_t)&n_nfsnode, sizeof(n_nfsnode));
+ if (error)
+ return (error);
+ error = SYSCTL_OUT(req, (caddr_t)&used, sizeof(used));
+ if (error)
+ return (error);
+ error = SYSCTL_OUT(req, (caddr_t)&maxlength, sizeof(maxlength));
+ if (error)
+ return (error);
+ error = SYSCTL_OUT(req, (caddr_t)&pct, sizeof(pct));
+ if (error)
+ return (error);
+ return (0);
+}
+SYSCTL_PROC(_debug_hashstat, OID_AUTO, nfsnode, CTLTYPE_INT|CTLFLAG_RD,
+ 0, 0, sysctl_debug_hashstat_nfsnode, "I", "nfsnode chain lengths");
+
+/*
* Initialize hash links for nfsnodes
* and build nfsnode free list.
*/
diff --git a/sys/nfsclient/nfs_node.c b/sys/nfsclient/nfs_node.c
index a82ad11..0191b66 100644
--- a/sys/nfsclient/nfs_node.c
+++ b/sys/nfsclient/nfs_node.c
@@ -45,6 +45,7 @@
#include <sys/vnode.h>
#include <sys/malloc.h>
#include <sys/fnv_hash.h>
+#include <sys/sysctl.h>
#include <vm/vm_zone.h>
@@ -62,6 +63,84 @@ static u_long nfsnodehash;
#define FALSE 0
/*
+ * Grab an atomic snapshot of the nfsnode hash chain lengths
+ */
+SYSCTL_DECL(_debug_hashstat);
+static int
+sysctl_debug_hashstat_rawnfsnode(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ struct nfsnodehashhead *nnpp;
+ struct nfsnode *nnp;
+ int n_nfsnode;
+ int count;
+
+ n_nfsnode = nfsnodehash + 1; /* nfsnodehash = max index, not count */
+ if (!req->oldptr)
+ return SYSCTL_OUT(req, 0, n_nfsnode * sizeof(int));
+
+ /* Scan hash tables for applicable entries */
+ for (nnpp = nfsnodehashtbl; n_nfsnode > 0; n_nfsnode--, nnpp++) {
+ count = 0;
+ LIST_FOREACH(nnp, nnpp, n_hash) {
+ count++;
+ }
+ error = SYSCTL_OUT(req, (caddr_t)&count, sizeof(count));
+ if (error)
+ return (error);
+ }
+ return (0);
+}
+SYSCTL_PROC(_debug_hashstat, OID_AUTO, rawnfsnode, CTLTYPE_INT|CTLFLAG_RD,
+ 0, 0, sysctl_debug_hashstat_rawnfsnode, "S,int", "nfsnode chain lengths");
+
+static int
+sysctl_debug_hashstat_nfsnode(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ struct nfsnodehashhead *nnpp;
+ struct nfsnode *nnp;
+ int n_nfsnode;
+ int count, maxlength, used, pct;
+
+ if (!req->oldptr)
+ return SYSCTL_OUT(req, 0, 4 * sizeof(int));
+
+ n_nfsnode = nfsnodehash + 1; /* nfsnodehash = max index, not count */
+ used = 0;
+ maxlength = 0;
+
+ /* Scan hash tables for applicable entries */
+ for (nnpp = nfsnodehashtbl; n_nfsnode > 0; n_nfsnode--, nnpp++) {
+ count = 0;
+ LIST_FOREACH(nnp, nnpp, n_hash) {
+ count++;
+ }
+ if (count)
+ used++;
+ if (maxlength < count)
+ maxlength = count;
+ }
+ n_nfsnode = nfsnodehash + 1;
+ pct = (used * 100 * 100) / n_nfsnode;
+ error = SYSCTL_OUT(req, (caddr_t)&n_nfsnode, sizeof(n_nfsnode));
+ if (error)
+ return (error);
+ error = SYSCTL_OUT(req, (caddr_t)&used, sizeof(used));
+ if (error)
+ return (error);
+ error = SYSCTL_OUT(req, (caddr_t)&maxlength, sizeof(maxlength));
+ if (error)
+ return (error);
+ error = SYSCTL_OUT(req, (caddr_t)&pct, sizeof(pct));
+ if (error)
+ return (error);
+ return (0);
+}
+SYSCTL_PROC(_debug_hashstat, OID_AUTO, nfsnode, CTLTYPE_INT|CTLFLAG_RD,
+ 0, 0, sysctl_debug_hashstat_nfsnode, "I", "nfsnode chain lengths");
+
+/*
* Initialize hash links for nfsnodes
* and build nfsnode free list.
*/
OpenPOWER on IntegriCloud