Create debug.hashstat.[raw]nchash and debug.hashstat.[raw]nfsnode to

enable easy access to the hash chain stats.  The raw prefixed versions
dump an integer array to userland with the chain lengths.  This cheats
and calls it an array of 'struct int' rather than 'int' or sysctl -a
faithfully dumps out the 128K array on an average machine.  The non-raw
versions return 4 integers: count, number of chains used, maximum chain
length, and percentage utilization (fixed point, multiplied by 100).
The raw forms are more useful for analyzing the hash distribution, while
the other form can be read easily by humans and stats loggers.
This commit is contained in:
Peter Wemm 2001-04-11 00:39:20 +00:00
parent ba33efd92c
commit 9d10eb0c0c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=75402
3 changed files with 238 additions and 0 deletions

View File

@ -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.

View File

@ -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>
@ -61,6 +62,84 @@ static u_long nfsnodehash;
#define TRUE 1
#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.

View File

@ -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>
@ -61,6 +62,84 @@ static u_long nfsnodehash;
#define TRUE 1
#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.