diff options
-rw-r--r-- | sys/kern/vfs_cache.c | 80 | ||||
-rw-r--r-- | sys/nfs/nfs_node.c | 79 | ||||
-rw-r--r-- | sys/nfsclient/nfs_node.c | 79 |
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. */ |