clean up vmstat some more: - remove unused nfsnodehash and ihash hash tables - move cpu_infos fetching into its own namelist and only fetch it when necessary, leaving the main namelist with zero kvm-against-live-kernel requests - use bitops.h - use a separate type (now enum) for "done" parts of getnlist(), making it clear which parts are fetched or not - re-order the fetching getnlist() and skip fetching anything againste a live kernel that isn't needed - document explicitly what parts of getnlist() are still using kvm against a life kernel, and potential solutions - reduce weird if () do { .. no break or continue .. } while (0); back to a plain if () { ... }. Index: vmstat.c =================================================================== RCS file: /cvsroot/src/usr.bin/vmstat/vmstat.c,v retrieving revision 1.232 diff -p -u -u -r1.232 vmstat.c --- vmstat.c 4 Jan 2020 03:09:55 -0000 1.232 +++ vmstat.c 4 Jan 2020 05:52:45 -0000 @@ -98,6 +98,7 @@ __RCSID("$NetBSD: vmstat.c,v 1.232 2020/ #include #include #include +#include #include #include @@ -162,9 +163,18 @@ struct nlist namelist[] = { .n_name = "_pool_head" }, #define X_UVMEXP 5 { .n_name = "_uvmexp" }, -#define X_CPU_INFOS 6 +#define X_NL_SIZE 6 + { .n_name = NULL }, +}; + +/* + * Namelist for cpu_infos array. + */ +struct nlist cpunl[] = +{ +#define X_CPU_INFOS 0 { .n_name = "_cpu_infos" }, -#define X_NL_SIZE 7 +#define X_CPUNL_SIZE 1 { .n_name = NULL }, }; @@ -206,14 +216,6 @@ 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 { .n_name = "_bufhash" }, #define X_BUFHASHTBL 5 @@ -272,18 +274,18 @@ int winlines = 20; kvm_t *kd; -#define FORKSTAT 0x001 -#define INTRSTAT 0x002 -#define MEMSTAT 0x004 -#define SUMSTAT 0x008 -#define EVCNTSTAT 0x010 -#define VMSTAT 0x020 -#define HISTLIST 0x040 -#define HISTDUMP 0x080 -#define HASHSTAT 0x100 -#define HASHLIST 0x200 -#define VMTOTAL 0x400 -#define POOLCACHESTAT 0x800 +#define FORKSTAT __BIT(1) +#define INTRSTAT __BIT(2) +#define MEMSTAT __BIT(3) +#define SUMSTAT __BIT(4) +#define EVCNTSTAT __BIT(5) +#define VMSTAT __BIT(6) +#define HISTLIST __BIT(7) +#define HISTDUMP __BIT(8) +#define HASHSTAT __BIT(9) +#define HASHLIST __BIT(10) +#define VMTOTAL __BIT(11) +#define POOLCACHESTAT __BIT(12) /* * Print single word. `ovflow' is number of characters didn't fit @@ -552,16 +554,65 @@ main(int argc, char *argv[]) void getnlist(int todo) { - static int namelist_done = 0; - static int done = 0; + static enum { + INTRNL = __BIT(1), + HASHNL = __BIT(2), + CPUNL = __BIT(3), + NAMELIST = __BIT(4), + TIMENL = __BIT(4), + HISTNL = __BIT(4), + } done = 0; int c; size_t i; if (kd == NULL) errx(1, "kvm_openfiles: %s", kvm_errbuf); - if (!namelist_done) { - namelist_done = 1; + /* + * The intrnl[] is only used by platforms not converted to use + * interrypt-style event counters, and failure is handled. + * + * This should be retained until the final port switches from + * intrnames/eintrnames and intrcnt/eintrcnt. + */ + if ((todo & (SUMSTAT|INTRSTAT)) && !(done & INTRNL)) { + done |= INTRNL; + (void) kvm_nlist(kd, intrnl); + } + + /* + * The hash statistics will require some design to push into a + * sysctl-only method for live kernels. + */ + if ((todo & (HASHLIST|HASHSTAT)) && !(done & HASHNL)) { + done |= HASHNL; + if ((c = kvm_nlist(kd, hashnl)) == -1 || c == X_HASHNL_SIZE) + errx(1, "kvm_nlist: %s %s", "hashnl", kvm_geterr(kd)); + } + + /* + * The CPU statistics will require exposing these members of ci_data + * for each CPU into some sysctl-able method: + * sysctl-only method for live kernels. + * cpu_nintr + * cpu_nsyscall + * cpu_nswtch + * cpu_nfault + * cpu_ntrap + * cpu_nsoft + */ + if ((todo & (VMSTAT|SUMSTAT)) && !(done & CPUNL)) { + done |= CPUNL; + if ((c = kvm_nlist(kd, cpunl)) == -1 || c == X_CPUNL_SIZE) + errx(1, "kvm_nlist: %s %s", "cpunl", kvm_geterr(kd)); + } + + /* The rest don't need to be fetched from the live kernel. */ + if (memf == NULL) + return; + + if (!(done & NAMELIST)) { + done |= NAMELIST; if ((c = kvm_nlist(kd, namelist)) != 0) { int doexit = 0; if (c == -1) @@ -582,22 +633,13 @@ getnlist(int todo) } } } - if ((todo & (VMSTAT|INTRSTAT)) && !(done & (VMSTAT))) { - done |= VMSTAT; + if ((todo & (VMSTAT|INTRSTAT)) && !(done & TIMENL)) { + done |= TIMENL; if ((c = kvm_nlist(kd, timenl)) == -1 || c == X_TIMENL_SIZE) errx(1, "kvm_nlist: %s %s", "timenl", kvm_geterr(kd)); } - if ((todo & (SUMSTAT|INTRSTAT)) && !(done & (SUMSTAT|INTRSTAT))) { - done |= SUMSTAT|INTRSTAT; - (void) kvm_nlist(kd, intrnl); - } - if ((todo & (HASHLIST|HASHSTAT)) && !(done & (HASHLIST|HASHSTAT))) { - done |= HASHLIST|HASHSTAT; - if ((c = kvm_nlist(kd, hashnl)) == -1 || c == X_HASHNL_SIZE) - errx(1, "kvm_nlist: %s %s", "hashnl", kvm_geterr(kd)); - } - if ((todo & (HISTLIST|HISTDUMP)) && !(done & (HISTLIST|HISTDUMP))) { - done |= HISTLIST|HISTDUMP; + if ((todo & (HISTLIST|HISTDUMP)) && !(done & HISTNL)) { + done |= HISTNL; if (kvm_nlist(kd, histnl) == -1) errx(1, "kvm_nlist: %s %s", "histnl", kvm_geterr(kd)); } @@ -1198,7 +1240,7 @@ cpucounters(struct cpu_counter *cc) } if (!initialised) { - kread(namelist, X_CPU_INFOS, &cpu_infos, sizeof(cpu_infos)); + kread(cpunl, X_CPU_INFOS, &cpu_infos, sizeof(cpu_infos)); initialised = 1; } @@ -1306,7 +1348,7 @@ doevcnt(int verbose, int type) counttotal = 0; uptime = getuptime(); - if (memf == NULL) do { + if (memf == NULL) { const int mib[4] = { CTL_KERN, KERN_EVCNT, type, verbose ? KERN_EVCNT_COUNT_ANY : KERN_EVCNT_COUNT_NONZERO }; size_t buflen0, buflen = 0; @@ -1401,7 +1443,7 @@ doevcnt(int verbose, int type) (int)total_max, counttotal, (int)rate_max, counttotal / uptime); return; - } while (/*CONSTCOND*/ 0); + } if (type == EVCNT_TYPE_ANY) (void)printf("%-34s %16s %8s %s\n", "event", "total", "rate",