- Separate hashstat namelist into separate hashnl[], and don't barf if

some of the symbols can't be found
- Only kvm_nlist() hashnl[] and histnl[] once
- Add a description to struct kernel_hash, and print with -L
- Sort entries in khashes[]
- Don't exit on unknown hashes; just display a warning and move on
This commit is contained in:
lukem 2001-11-26 14:06:31 +00:00
parent 3dfc0ff3ab
commit 31c1ed8952

View File

@ -1,4 +1,4 @@
/* $NetBSD: vmstat.c,v 1.89 2001/11/26 10:38:59 lukem Exp $ */ /* $NetBSD: vmstat.c,v 1.90 2001/11/26 14:06:31 lukem Exp $ */
/*- /*-
* Copyright (c) 1998, 2000, 2001 The NetBSD Foundation, Inc. * Copyright (c) 1998, 2000, 2001 The NetBSD Foundation, Inc.
@ -81,7 +81,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 1986, 1991, 1993\n\
#if 0 #if 0
static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 3/1/95"; static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 3/1/95";
#else #else
__RCSID("$NetBSD: vmstat.c,v 1.89 2001/11/26 10:38:59 lukem Exp $"); __RCSID("$NetBSD: vmstat.c,v 1.90 2001/11/26 14:06:31 lukem Exp $");
#endif #endif
#endif /* not lint */ #endif /* not lint */
@ -137,6 +137,9 @@ __RCSID("$NetBSD: vmstat.c,v 1.89 2001/11/26 10:38:59 lukem Exp $");
#include "dkstats.h" #include "dkstats.h"
/*
* General namelist
*/
struct nlist namelist[] = struct nlist namelist[] =
{ {
#define X_BOOTTIME 0 #define X_BOOTTIME 0
@ -165,51 +168,71 @@ struct nlist namelist[] =
{ "_pool_head" }, { "_pool_head" },
#define X_UVMEXP 12 #define X_UVMEXP 12
{ "_uvmexp" }, { "_uvmexp" },
#define X_NFSNODE 13 #define X_END 13
{ "_nfsnodehash" },
#define X_NFSNODETBL 14
{ "_nfsnodehashtbl" },
#define X_IHASH 15
{ "_ihash" },
#define X_IHASHTBL 16
{ "_ihashtbl" },
#define X_BUFHASH 17
{ "_bufhash" },
#define X_BUFHASHTBL 18
{ "_bufhashtbl" },
#define X_PIDHASH 19
{ "_pidhash" },
#define X_PIDHASHTBL 20
{ "_pidhashtbl" },
#define X_PGRPHASH 21
{ "_pgrphash" },
#define X_PGRPHASHTBL 22
{ "_pgrphashtbl" },
#define X_UIHASH 23
{ "_uihash" },
#define X_UIHASHTBL 24
{ "_uihashtbl" },
#define X_IFADDRHASH 25
{ "_in_ifaddrhash" },
#define X_IFADDRHASHTBL 26
{ "_in_ifaddrhashtbl" },
#define X_NCHASH 27
{ "_nchash" },
#define X_NCHASHTBL 28
{ "_nchashtbl" },
#define X_NCVHASH 29
{ "_ncvhash" },
#define X_NCVHASHTBL 30
{ "_ncvhashtbl" },
#define X_END 31
#if defined(pc532) #if defined(pc532)
#define X_IVT (X_END) #define X_IVT (X_END)
{ "_ivt" }, { "_ivt" },
#endif #endif
{ "" }, { NULL },
}; };
/*
* Namelist for hash statistics
*/
struct nlist hashnl[] =
{
#define X_NFSNODE 0
{ "_nfsnodehash" },
#define X_NFSNODETBL 1
{ "_nfsnodehashtbl" },
#define X_IHASH 2
{ "_ihash" },
#define X_IHASHTBL 3
{ "_ihashtbl" },
#define X_BUFHASH 4
{ "_bufhash" },
#define X_BUFHASHTBL 5
{ "_bufhashtbl" },
#define X_PIDHASH 6
{ "_pidhash" },
#define X_PIDHASHTBL 7
{ "_pidhashtbl" },
#define X_PGRPHASH 8
{ "_pgrphash" },
#define X_PGRPHASHTBL 9
{ "_pgrphashtbl" },
#define X_UIHASH 10
{ "_uihash" },
#define X_UIHASHTBL 11
{ "_uihashtbl" },
#define X_IFADDRHASH 12
{ "_in_ifaddrhash" },
#define X_IFADDRHASHTBL 13
{ "_in_ifaddrhashtbl" },
#define X_NCHASH 14
{ "_nchash" },
#define X_NCHASHTBL 15
{ "_nchashtbl" },
#define X_NCVHASH 16
{ "_ncvhash" },
#define X_NCVHASHTBL 17
{ "_ncvhashtbl" },
#define X_HASHNL_SIZE 18 /* must be last */
{ NULL },
};
/*
* Namelist for UVM histories
*/
struct nlist histnl[] =
{
{ "_uvm_histories" },
#define X_UVM_HISTORIES 0
{ NULL },
};
struct uvmexp uvmexp, ouvmexp; struct uvmexp uvmexp, ouvmexp;
int ndrives; int ndrives;
@ -357,19 +380,19 @@ main(int argc, char *argv[])
} }
if ((c = kvm_nlist(kd, namelist)) != 0) { if ((c = kvm_nlist(kd, namelist)) != 0) {
if (c > 0) { if (c == -1)
(void)fprintf(stderr, errx(1, "kvm_nlist: %s %s", "namelist", kvm_geterr(kd));
"vmstat: undefined symbols:"); (void)fprintf(stderr, "vmstat: undefined symbols:");
for (c = 0; for (c = 0; c < sizeof(namelist) / sizeof(namelist[0]); c++)
c < sizeof(namelist) / sizeof(namelist[0]); c++) if (namelist[c].n_type == 0)
if (namelist[c].n_type == 0) fprintf(stderr, " %s", namelist[c].n_name);
fprintf(stderr, " %s", (void)fputc('\n', stderr);
namelist[c].n_name);
(void)fputc('\n', stderr);
} else
warnx("kvm_nlist: %s", kvm_geterr(kd));
exit(1); exit(1);
} }
if ((c = kvm_nlist(kd, hashnl)) == -1 || c == X_HASHNL_SIZE)
errx(1, "kvm_nlist: %s %s", "hashnl", kvm_geterr(kd));
if (kvm_nlist(kd, histnl) == -1)
errx(1, "kvm_nlist: %s %s", "histnl", kvm_geterr(kd));
if (todo & VMSTAT) { if (todo & VMSTAT) {
struct winsize winsize; struct winsize winsize;
@ -1129,6 +1152,7 @@ dopool(void)
inuse, total, (double)(100 * inuse) / total); inuse, total, (double)(100 * inuse) / total);
} }
enum hashtype { /* from <sys/systm.h> */ enum hashtype { /* from <sys/systm.h> */
HASH_LIST, HASH_LIST,
HASH_TAILQ HASH_TAILQ
@ -1141,41 +1165,51 @@ struct uidinfo { /* XXX: no kernel header file */
}; };
struct kernel_hash { struct kernel_hash {
int hashsize; const char * description; /* description */
int hashtbl; int hashsize; /* nlist index for hash size */
enum hashtype type; int hashtbl; /* nlist index for hash table */
size_t offset; enum hashtype type; /* type of hash table */
size_t offset; /* offset of {LIST,TAILQ}_NEXT */
} khashes[] = } khashes[] =
{ {
{ {
X_NFSNODE, X_NFSNODETBL, "buffer hash",
HASH_LIST, offsetof(struct nfsnode, n_hash)
} , {
X_IHASH, X_IHASHTBL,
HASH_LIST, offsetof(struct inode, i_hash)
} , {
X_BUFHASH, X_BUFHASHTBL, X_BUFHASH, X_BUFHASHTBL,
HASH_LIST, offsetof(struct buf, b_hash) HASH_LIST, offsetof(struct buf, b_hash)
} , { }, {
X_PIDHASH, X_PIDHASHTBL, "inode cache (ihash)",
HASH_LIST, offsetof(struct proc, p_hash) X_IHASH, X_IHASHTBL,
} , { HASH_LIST, offsetof(struct inode, i_hash)
X_PGRPHASH, X_PGRPHASHTBL, }, {
HASH_LIST, offsetof(struct pgrp, pg_hash), "ipv4 address -> interface hash",
} , {
X_UIHASH, X_UIHASHTBL,
HASH_LIST, offsetof(struct uidinfo, ui_hash),
} , {
X_IFADDRHASH, X_IFADDRHASHTBL, X_IFADDRHASH, X_IFADDRHASHTBL,
HASH_LIST, offsetof(struct in_ifaddr, ia_hash), HASH_LIST, offsetof(struct in_ifaddr, ia_hash),
} , { }, {
"name cache hash",
X_NCHASH, X_NCHASHTBL, X_NCHASH, X_NCHASHTBL,
HASH_LIST, offsetof(struct namecache, nc_hash), HASH_LIST, offsetof(struct namecache, nc_hash),
} , { }, {
"name cache directory hash",
X_NCVHASH, X_NCVHASHTBL, X_NCVHASH, X_NCVHASHTBL,
HASH_LIST, offsetof(struct namecache, nc_vhash), HASH_LIST, offsetof(struct namecache, nc_vhash),
} , { }, {
-1, -1, 0, 0 "nfs client node cache",
X_NFSNODE, X_NFSNODETBL,
HASH_LIST, offsetof(struct nfsnode, n_hash)
}, {
"process group (pgrp) hash",
X_PGRPHASH, X_PGRPHASHTBL,
HASH_LIST, offsetof(struct pgrp, pg_hash),
}, {
"process id (pid) hash",
X_PIDHASH, X_PIDHASHTBL,
HASH_LIST, offsetof(struct proc, p_hash)
}, {
"user info (uid -> used processes) hash",
X_UIHASH, X_UIHASHTBL,
HASH_LIST, offsetof(struct uidinfo, ui_hash),
}, {
NULL, -1, -1, 0, 0,
} }
}; };
@ -1194,25 +1228,30 @@ dohashstat(int verbose, int todo, const char *hashname)
hashbufsize = 0; hashbufsize = 0;
if (todo & HASHLIST) { if (todo & HASHLIST) {
const char *prefix = ""; printf("Supported hashes:\n");
for (curhash = khashes; curhash->description; curhash++) {
printf("Supported hashes:\n\t"); if (hashnl[curhash->hashsize].n_value == 0 ||
for (curhash = khashes; curhash->hashsize != -1; curhash++) { hashnl[curhash->hashtbl].n_value == 0)
printf("%s%s", continue;
prefix, namelist[curhash->hashsize].n_name + 1); printf("\t%-16s%s\n",
prefix = ", "; hashnl[curhash->hashsize].n_name + 1,
curhash->description);
} }
return; return;
} }
if (hashname != NULL) { if (hashname != NULL) {
for (curhash = khashes; curhash->hashsize != -1; curhash++) { for (curhash = khashes; curhash->description; curhash++) {
if (strcmp(namelist[curhash->hashsize].n_name + 1, if (strcmp(hashnl[curhash->hashsize].n_name + 1,
hashname) == 0) hashname) == 0 &&
hashnl[curhash->hashsize].n_value != 0 &&
hashnl[curhash->hashtbl].n_value != 0)
break; break;
} }
if (curhash->hashsize == -1) if (curhash->description == NULL) {
errx(1, "%s: no such hash", hashname); warnx("%s: no such hash", hashname);
return;
}
} }
printf( printf(
@ -1222,28 +1261,35 @@ dohashstat(int verbose, int todo, const char *hashname)
"hash table", "buckets", "buckets", "%", "items", "chain", "hash table", "buckets", "buckets", "%", "items", "chain",
"chain"); "chain");
for (curhash = khashes; curhash->hashsize != -1; curhash++) { for (curhash = khashes; curhash->description; curhash++) {
if (hashnl[curhash->hashsize].n_value == 0 ||
hashnl[curhash->hashtbl].n_value == 0)
continue;
if (hashname != NULL && if (hashname != NULL &&
strcmp(namelist[curhash->hashsize].n_name + 1, hashname)) strcmp(hashnl[curhash->hashsize].n_name + 1, hashname))
continue; continue;
elemsize = curhash->type == HASH_LIST ? elemsize = curhash->type == HASH_LIST ?
sizeof(*hashtbl_list) : sizeof(*hashtbl_tailq); sizeof(*hashtbl_list) : sizeof(*hashtbl_tailq);
kread(curhash->hashsize, &hashsize, sizeof(hashsize)); deref_kptr((void *)hashnl[curhash->hashsize].n_value,
&hashsize, sizeof(hashsize),
hashnl[curhash->hashsize].n_name);
hashsize++; hashsize++;
kread(curhash->hashtbl, &hashaddr, sizeof(hashaddr)); deref_kptr((void *)hashnl[curhash->hashtbl].n_value,
&hashaddr, sizeof(hashaddr),
hashnl[curhash->hashtbl].n_name);
if (verbose) if (verbose)
printf("%s %lu, %s %p, offset %ld, elemsize %d\n", printf("%s %lu, %s %p, offset %ld, elemsize %d\n",
namelist[curhash->hashsize].n_name + 1, hashsize, hashnl[curhash->hashsize].n_name + 1, hashsize,
namelist[curhash->hashtbl].n_name + 1, hashaddr, hashnl[curhash->hashtbl].n_name + 1, hashaddr,
(long)curhash->offset, elemsize); (long)curhash->offset, elemsize);
thissize = hashsize * elemsize; thissize = hashsize * elemsize;
if (thissize > hashbufsize) { if (thissize > hashbufsize) {
hashbufsize = thissize; hashbufsize = thissize;
if ((hashbuf = realloc(hashbuf, hashbufsize)) == NULL) if ((hashbuf = realloc(hashbuf, hashbufsize)) == NULL)
errx(1, "malloc %d", hashbufsize); errx(1, "malloc hashbuf %d", hashbufsize);
} }
deref_kptr(hashaddr, hashbuf, thissize, deref_kptr(hashaddr, hashbuf, thissize,
namelist[curhash->hashtbl].n_name); hashnl[curhash->hashtbl].n_name);
used = 0; used = 0;
items = maxchain = 0; items = maxchain = 0;
if (curhash->type == HASH_LIST) if (curhash->type == HASH_LIST)
@ -1282,14 +1328,14 @@ dohashstat(int verbose, int todo, const char *hashname)
maxchain = chain; maxchain = chain;
} }
printf("%-16s %8ld %8d %8.2f %8d %8d %8d\n", printf("%-16s %8ld %8d %8.2f %8d %8d %8d\n",
namelist[curhash->hashsize].n_name + 1, hashnl[curhash->hashsize].n_name + 1,
hashsize, used, used * 100.0 / hashsize, hashsize, used, used * 100.0 / hashsize,
items, used ? items / used : 0, maxchain); items, used ? items / used : 0, maxchain);
} }
} }
/* /*
* kread reads something from the kernel, given its nlist index. * kread reads something from the kernel, given its nlist index in namelist[].
*/ */
void void
kread(int nlx, void *addr, size_t size) kread(int nlx, void *addr, size_t size)
@ -1319,14 +1365,6 @@ deref_kptr(const void *kptr, void *ptr, size_t len, const char *msg)
errx(1, "kptr %lx: %s: %s", (u_long)kptr, msg, kvm_geterr(kd)); errx(1, "kptr %lx: %s: %s", (u_long)kptr, msg, kvm_geterr(kd));
} }
struct nlist histnl[] =
{
{ "_uvm_histories" },
#define X_UVM_HISTORIES 0
{ NULL },
};
/* /*
* Traverse the UVM history buffers, performing the requested action. * Traverse the UVM history buffers, performing the requested action.
* *
@ -1340,7 +1378,7 @@ hist_traverse(int todo, const char *histname)
char *name = NULL; char *name = NULL;
size_t namelen = 0; size_t namelen = 0;
if (kvm_nlist(kd, histnl) != 0) { if (histnl[0].n_value == 0) {
warnx("UVM history is not compiled into the kernel."); warnx("UVM history is not compiled into the kernel.");
return; return;
} }