Annotation of src/usr.bin/vmstat/vmstat.c, Revision 1.65
1.11 deraadt 1: /* $NetBSD: vmstat.c,v 1.29.4.1 1996/06/05 00:21:05 cgd Exp $ */
1.65 ! art 2: /* $OpenBSD: vmstat.c,v 1.64 2002/01/21 17:30:38 deraadt Exp $ */
1.1 deraadt 3:
4: /*
5: * Copyright (c) 1980, 1986, 1991, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #ifndef lint
38: static char copyright[] =
39: "@(#) Copyright (c) 1980, 1986, 1991, 1993\n\
40: The Regents of the University of California. All rights reserved.\n";
41: #endif /* not lint */
42:
43: #ifndef lint
44: #if 0
45: static char sccsid[] = "@(#)vmstat.c 8.1 (Berkeley) 6/6/93";
46: #else
1.11 deraadt 47: static char rcsid[] = "$NetBSD: vmstat.c,v 1.29.4.1 1996/06/05 00:21:05 cgd Exp $";
1.1 deraadt 48: #endif
49: #endif /* not lint */
50:
1.48 art 51: #define __POOL_EXPOSE
52:
1.1 deraadt 53: #include <sys/param.h>
54: #include <sys/time.h>
55: #include <sys/proc.h>
56: #include <sys/user.h>
57: #include <sys/dkstat.h>
58: #include <sys/buf.h>
59: #include <sys/namei.h>
60: #include <sys/malloc.h>
61: #include <sys/fcntl.h>
62: #include <sys/ioctl.h>
63: #include <sys/sysctl.h>
64: #include <sys/device.h>
1.48 art 65: #include <sys/pool.h>
1.1 deraadt 66: #include <time.h>
67: #include <nlist.h>
68: #include <kvm.h>
1.21 millert 69: #include <err.h>
1.1 deraadt 70: #include <errno.h>
71: #include <unistd.h>
72: #include <signal.h>
73: #include <stdio.h>
74: #include <ctype.h>
75: #include <stdlib.h>
76: #include <string.h>
77: #include <paths.h>
78: #include <limits.h>
1.6 tholo 79: #include "dkstats.h"
1.1 deraadt 80:
1.56 angelos 81: #include <uvm/uvm_object.h>
1.29 art 82: #include <uvm/uvm_extern.h>
83:
1.1 deraadt 84: struct nlist namelist[] = {
1.53 deraadt 85: #define X_UVMEXP 0
1.29 art 86: { "_uvmexp" },
1.53 deraadt 87: #define X_BOOTTIME 1
1.1 deraadt 88: { "_boottime" },
1.53 deraadt 89: #define X_NCHSTATS 2
1.1 deraadt 90: { "_nchstats" },
1.53 deraadt 91: #define X_INTRNAMES 3
1.1 deraadt 92: { "_intrnames" },
1.53 deraadt 93: #define X_EINTRNAMES 4
1.1 deraadt 94: { "_eintrnames" },
1.53 deraadt 95: #define X_INTRCNT 5
1.1 deraadt 96: { "_intrcnt" },
1.53 deraadt 97: #define X_EINTRCNT 6
1.1 deraadt 98: { "_eintrcnt" },
1.53 deraadt 99: #define X_KMEMSTAT 7
1.1 deraadt 100: { "_kmemstats" },
1.53 deraadt 101: #define X_KMEMBUCKETS 8
1.1 deraadt 102: { "_bucket" },
1.53 deraadt 103: #define X_ALLEVENTS 9
1.1 deraadt 104: { "_allevents" },
1.53 deraadt 105: #define X_FORKSTAT 10
1.12 tholo 106: { "_forkstat" },
1.53 deraadt 107: #define X_POOLHEAD 11
1.48 art 108: { "_pool_head" },
1.53 deraadt 109: #define X_NSELCOLL 12
1.50 art 110: { "_nselcoll" },
1.53 deraadt 111: #define X_END 13
1.28 espie 112: #if defined(__i386__)
1.12 tholo 113: #define X_INTRHAND (X_END)
114: { "_intrhand" },
115: #define X_INTRSTRAY (X_END+1)
116: { "_intrstray" },
117: #endif
1.1 deraadt 118: { "" },
119: };
120:
1.6 tholo 121: /* Objects defined in dkstats.c */
122: extern struct _disk cur;
1.10 deraadt 123: extern char **dr_name;
124: extern int *dk_select, dk_ndrive;
1.1 deraadt 125:
1.29 art 126: struct uvmexp uvmexp, ouvmexp;
1.6 tholo 127: int ndrives;
1.1 deraadt 128:
129: int winlines = 20;
130:
131: kvm_t *kd;
132:
133: #define FORKSTAT 0x01
134: #define INTRSTAT 0x02
135: #define MEMSTAT 0x04
136: #define SUMSTAT 0x08
137: #define TIMESTAT 0x10
138: #define VMSTAT 0x20
139:
1.10 deraadt 140: void cpustats __P((void));
141: void dkstats __P((void));
142: void dointr __P((void));
143: void domem __P((void));
1.48 art 144: void dopool __P((void));
1.10 deraadt 145: void dosum __P((void));
146: void dovmstat __P((u_int, int));
147: void kread __P((int, void *, size_t));
148: void usage __P((void));
149: void dotimes __P((void));
150: void doforkst __P((void));
1.21 millert 151: void printhdr __P((void));
1.1 deraadt 152:
1.10 deraadt 153: char **choosedrives __P((char **));
154:
155: /* Namelist and memory file names. */
156: char *nlistf, *memf;
1.6 tholo 157:
1.50 art 158: extern char *__progname;
159:
1.65 ! art 160: int verbose = 0;
! 161:
1.21 millert 162: int
1.1 deraadt 163: main(argc, argv)
1.62 mpech 164: int argc;
165: char **argv;
1.1 deraadt 166: {
167: extern int optind;
168: extern char *optarg;
1.62 mpech 169: int c, todo;
1.1 deraadt 170: u_int interval;
171: int reps;
1.25 deraadt 172: char errbuf[_POSIX2_LINE_MAX];
1.1 deraadt 173:
174: interval = reps = todo = 0;
1.65 ! art 175: while ((c = getopt(argc, argv, "c:fiM:mN:stw:v")) != -1) {
1.1 deraadt 176: switch (c) {
177: case 'c':
178: reps = atoi(optarg);
179: break;
180: case 'f':
181: todo |= FORKSTAT;
182: break;
183: case 'i':
184: todo |= INTRSTAT;
185: break;
186: case 'M':
187: memf = optarg;
188: break;
189: case 'm':
190: todo |= MEMSTAT;
191: break;
192: case 'N':
193: nlistf = optarg;
194: break;
195: case 's':
196: todo |= SUMSTAT;
197: break;
198: case 't':
199: todo |= TIMESTAT;
200: break;
201: case 'w':
202: interval = atoi(optarg);
203: break;
1.65 ! art 204: case 'v':
! 205: verbose = 1;
! 206: break;
1.1 deraadt 207: case '?':
208: default:
209: usage();
210: }
211: }
212: argc -= optind;
213: argv += optind;
214:
215: if (todo == 0)
216: todo = VMSTAT;
217:
1.56 angelos 218: if (nlistf != NULL || memf != NULL) {
219: setegid(getgid());
220: setgid(getgid());
221: }
222:
1.1 deraadt 223: /*
224: * Discard setgid privileges if not the running kernel so that bad
225: * guys can't print interesting stuff from kernel memory.
226: */
1.56 angelos 227: #if notyet
1.15 tholo 228: if (nlistf != NULL || memf != NULL) {
1.56 angelos 229: #endif
230: kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
231: if (kd == 0)
232: errx(1, "kvm_openfiles: %s", errbuf);
233:
234: if ((c = kvm_nlist(kd, namelist)) != 0) {
235: setgid(getgid());
236: setegid(getegid());
237:
238: if (c > 0) {
239: (void)fprintf(stderr,
240: "%s: undefined symbols:", __progname);
241: for (c = 0;
242: c < sizeof(namelist)/sizeof(namelist[0]);
243: c++)
244: if (namelist[c].n_type == 0)
245: fprintf(stderr, " %s",
246: namelist[c].n_name);
247: (void)fputc('\n', stderr);
248: exit(1);
249: } else
250: errx(1, "kvm_nlist: %s", kvm_geterr(kd));
251: }
252: #ifdef notyet
1.15 tholo 253: }
1.59 heko 254: #endif /* notyet */
1.1 deraadt 255:
1.56 angelos 256: setegid(getegid());
257: setgid(getgid());
1.1 deraadt 258:
259: if (todo & VMSTAT) {
260: struct winsize winsize;
261:
1.6 tholo 262: dkinit(0); /* Initialize disk stats, no disks selected. */
263: argv = choosedrives(argv); /* Select disks. */
1.1 deraadt 264: winsize.ws_row = 0;
265: (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize);
266: if (winsize.ws_row > 0)
267: winlines = winsize.ws_row;
268:
269: }
1.25 deraadt 270:
1.1 deraadt 271: #define BACKWARD_COMPATIBILITY
272: #ifdef BACKWARD_COMPATIBILITY
273: if (*argv) {
274: interval = atoi(*argv);
275: if (*++argv)
276: reps = atoi(*argv);
277: }
278: #endif
279:
280: if (interval) {
281: if (!reps)
282: reps = -1;
283: } else if (reps)
284: interval = 1;
285:
286: if (todo & FORKSTAT)
287: doforkst();
1.48 art 288: if (todo & MEMSTAT) {
1.1 deraadt 289: domem();
1.48 art 290: dopool();
291: }
1.1 deraadt 292: if (todo & SUMSTAT)
293: dosum();
294: if (todo & TIMESTAT)
295: dotimes();
296: if (todo & INTRSTAT)
297: dointr();
298: if (todo & VMSTAT)
299: dovmstat(interval, reps);
300: exit(0);
301: }
302:
303: char **
1.6 tholo 304: choosedrives(argv)
1.1 deraadt 305: char **argv;
306: {
1.62 mpech 307: int i;
1.1 deraadt 308:
309: /*
310: * Choose drives to be displayed. Priority goes to (in order) drives
311: * supplied as arguments, default drives. If everything isn't filled
312: * in and there are drives not taken care of, display the first few
313: * that fit.
314: */
315: #define BACKWARD_COMPATIBILITY
316: for (ndrives = 0; *argv; ++argv) {
317: #ifdef BACKWARD_COMPATIBILITY
318: if (isdigit(**argv))
319: break;
320: #endif
321: for (i = 0; i < dk_ndrive; i++) {
322: if (strcmp(dr_name[i], *argv))
323: continue;
1.6 tholo 324: dk_select[i] = 1;
1.1 deraadt 325: ++ndrives;
326: break;
327: }
328: }
1.64 deraadt 329: for (i = 0; i < dk_ndrive && ndrives < 2; i++) {
1.6 tholo 330: if (dk_select[i])
1.1 deraadt 331: continue;
1.6 tholo 332: dk_select[i] = 1;
1.1 deraadt 333: ++ndrives;
334: }
335: return(argv);
336: }
337:
1.19 deraadt 338: time_t
1.1 deraadt 339: getuptime()
340: {
1.11 deraadt 341: static time_t now;
342: static struct timeval boottime;
1.1 deraadt 343: time_t uptime;
1.50 art 344: int mib[2];
345: size_t size;
1.1 deraadt 346:
1.50 art 347: if (boottime.tv_sec == 0) {
1.56 angelos 348: if (nlistf == NULL && memf == NULL) {
1.50 art 349: size = sizeof(boottime);
350: mib[0] = CTL_KERN;
351: mib[1] = KERN_BOOTTIME;
352: if (sysctl(mib, 2, &boottime, &size, NULL, 0) < 0) {
1.56 angelos 353: warn("could not get kern.boottime");
1.50 art 354: bzero(&boottime, sizeof(boottime));
355: }
1.56 angelos 356: } else {
357: kread(X_BOOTTIME, &boottime, sizeof(boottime));
1.50 art 358: }
359: }
1.1 deraadt 360: (void)time(&now);
1.11 deraadt 361: uptime = now - boottime.tv_sec;
1.50 art 362: if (uptime <= 0 || uptime > 60*60*24*365*10)
363: errx(1, "time makes no sense; namelist must be wrong");
364:
1.1 deraadt 365: return(uptime);
366: }
367:
368: int hz, hdrcnt;
369:
370: void
371: dovmstat(interval, reps)
372: u_int interval;
373: int reps;
374: {
375: struct vmtotal total;
376: time_t uptime, halfuptime;
377: void needhdr();
378: int mib[2];
1.50 art 379: struct clockinfo clkinfo;
1.1 deraadt 380: size_t size;
381:
382: uptime = getuptime();
383: halfuptime = uptime / 2;
384: (void)signal(SIGCONT, needhdr);
385:
1.50 art 386: mib[0] = CTL_KERN;
387: mib[1] = KERN_CLOCKRATE;
388: size = sizeof(clkinfo);
389: if (sysctl(mib, 2, &clkinfo, &size, NULL, 0) < 0) {
1.56 angelos 390: warn("could not read kern.clockrate");
1.50 art 391: return;
392: }
393: hz = clkinfo.stathz;
1.1 deraadt 394:
395: for (hdrcnt = 1;;) {
396: if (!--hdrcnt)
397: printhdr();
1.6 tholo 398: /* Read new disk statistics */
399: dkreadstats();
1.56 angelos 400: if (nlistf == NULL && memf == NULL) {
401: size = sizeof(struct uvmexp);
1.52 angelos 402: mib[0] = CTL_VM;
403: mib[1] = VM_UVMEXP;
404: if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0) {
1.56 angelos 405: warn("could not get vm.uvmexp");
406: bzero(&uvmexp, sizeof(struct uvmexp));
1.52 angelos 407: }
1.56 angelos 408: } else {
409: kread(X_UVMEXP, &uvmexp, sizeof(struct uvmexp));
1.52 angelos 410: }
1.1 deraadt 411: size = sizeof(total);
412: mib[0] = CTL_VM;
413: mib[1] = VM_METER;
414: if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) {
1.56 angelos 415: warn("could not read vm.vmmeter");
1.1 deraadt 416: bzero(&total, sizeof(total));
417: }
1.22 millert 418: (void)printf("%2u%2u%2u",
1.1 deraadt 419: total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw);
1.29 art 420: #define rate(x) (((x) + halfuptime) / uptime) /* round */
421: #define pgtok(a) ((a) * ((int)uvmexp.pagesize >> 10))
1.35 hugh 422: (void)printf("%7u%7u ",
1.1 deraadt 423: pgtok(total.t_avm), pgtok(total.t_free));
1.64 deraadt 424: (void)printf("%5u ", rate(uvmexp.faults - ouvmexp.faults));
1.29 art 425: (void)printf("%3u ", rate(uvmexp.pdreact - ouvmexp.pdreact));
426: (void)printf("%3u ", rate(uvmexp.pageins - ouvmexp.pageins));
427: (void)printf("%3u %3u ",
428: rate(uvmexp.pdpageouts - ouvmexp.pdpageouts), 0);
429: (void)printf("%3u ", rate(uvmexp.pdscans - ouvmexp.pdscans));
430: dkstats();
1.64 deraadt 431: (void)printf("%4u %5u %4u ",
1.29 art 432: rate(uvmexp.intrs - ouvmexp.intrs),
433: rate(uvmexp.syscalls - ouvmexp.syscalls),
434: rate(uvmexp.swtch - ouvmexp.swtch));
1.1 deraadt 435: cpustats();
436: (void)printf("\n");
437: (void)fflush(stdout);
438: if (reps >= 0 && --reps <= 0)
439: break;
1.29 art 440: ouvmexp = uvmexp;
1.1 deraadt 441: uptime = interval;
442: /*
443: * We round upward to avoid losing low-frequency events
444: * (i.e., >= 1 per interval but < 1 per second).
445: */
1.14 deraadt 446: halfuptime = uptime == 1 ? 0 : (uptime + 1) / 2;
1.1 deraadt 447: (void)sleep(interval);
448: }
449: }
450:
1.21 millert 451: void
1.1 deraadt 452: printhdr()
453: {
1.62 mpech 454: int i;
1.1 deraadt 455:
1.35 hugh 456: (void)printf(" procs memory page%*s", 20, "");
1.6 tholo 457: if (ndrives > 0)
1.64 deraadt 458: (void)printf("%s %*sfaults cpu\n",
1.6 tholo 459: ((ndrives > 1) ? "disks" : "disk"),
1.64 deraadt 460: ((ndrives > 1) ? ndrives * 4 - 4 : 0), "");
1.1 deraadt 461: else
1.64 deraadt 462: (void)printf("%*s faults cpu\n",
1.6 tholo 463: ndrives * 3, "");
464:
1.64 deraadt 465: (void)printf(" r b w avm fre flt re pi po fr sr ");
1.1 deraadt 466: for (i = 0; i < dk_ndrive; i++)
1.6 tholo 467: if (dk_select[i])
1.64 deraadt 468: (void)printf("%c%c%c", dr_name[i][0],
469: dr_name[i][1],
1.1 deraadt 470: dr_name[i][strlen(dr_name[i]) - 1]);
1.64 deraadt 471: (void)printf(" in sy cs us sy id\n");
1.1 deraadt 472: hdrcnt = winlines - 2;
473: }
474:
475: /*
476: * Force a header to be prepended to the next output.
477: */
478: void
479: needhdr()
480: {
481:
482: hdrcnt = 1;
483: }
484:
485: void
486: dotimes()
487: {
488: u_int pgintime, rectime;
1.52 angelos 489: int mib[2];
490: size_t size;
1.1 deraadt 491:
1.56 angelos 492: /* XXX Why are these set to 0 ? This doesn't look right. */
1.12 tholo 493: pgintime = 0;
494: rectime = 0;
1.56 angelos 495:
496: if (nlistf == NULL && memf == NULL) {
497: size = sizeof(struct uvmexp);
1.52 angelos 498: mib[0] = CTL_VM;
499: mib[1] = VM_UVMEXP;
500: if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0) {
1.56 angelos 501: warn("could not read vm.uvmexp");
502: bzero(&uvmexp, sizeof(struct uvmexp));
1.52 angelos 503: }
1.56 angelos 504: } else {
505: kread(X_UVMEXP, &uvmexp, sizeof(struct uvmexp));
1.52 angelos 506: }
507:
1.29 art 508: (void)printf("%u reactivates, %u total time (usec)\n",
509: uvmexp.pdreact, rectime);
510: (void)printf("average: %u usec / reclaim\n", rectime / uvmexp.pdreact);
511: (void)printf("\n");
512: (void)printf("%u page ins, %u total time (msec)\n",
513: uvmexp.pageins, pgintime / 10);
514: (void)printf("average: %8.1f msec / page in\n",
515: pgintime / (uvmexp.pageins * 10.0));
1.1 deraadt 516: }
517:
1.21 millert 518: int
1.1 deraadt 519: pct(top, bot)
520: long top, bot;
521: {
522: long ans;
523:
524: if (bot == 0)
525: return(0);
526: ans = (quad_t)top * 100 / bot;
527: return (ans);
528: }
529:
530: #define PCT(top, bot) pct((long)(top), (long)(bot))
531:
532: void
533: dosum()
534: {
535: struct nchstats nchstats;
536: long nchtotal;
1.52 angelos 537: size_t size;
538: int mib[2], nselcoll;
1.1 deraadt 539:
1.56 angelos 540: if (nlistf == NULL && memf == NULL) {
541: size = sizeof(struct uvmexp);
1.52 angelos 542: mib[0] = CTL_VM;
543: mib[1] = VM_UVMEXP;
544: if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0) {
1.56 angelos 545: warn("could not read vm.uvmexp");
546: bzero(&uvmexp, sizeof(struct uvmexp));
1.52 angelos 547: }
1.56 angelos 548: } else {
549: kread(X_UVMEXP, &uvmexp, sizeof(struct uvmexp));
1.52 angelos 550: }
551:
1.32 art 552: /* vm_page constants */
1.35 hugh 553: (void)printf("%11u bytes per page\n", uvmexp.pagesize);
1.32 art 554:
555: /* vm_page counters */
1.35 hugh 556: (void)printf("%11u pages managed\n", uvmexp.npages);
557: (void)printf("%11u pages free\n", uvmexp.free);
558: (void)printf("%11u pages active\n", uvmexp.active);
559: (void)printf("%11u pages inactive\n", uvmexp.inactive);
560: (void)printf("%11u pages being paged out\n", uvmexp.paging);
561: (void)printf("%11u pages wired\n", uvmexp.wired);
562: (void)printf("%11u pages reserved for pagedaemon\n",
1.48 art 563: uvmexp.reserve_pagedaemon);
1.35 hugh 564: (void)printf("%11u pages reserved for kernel\n",
1.48 art 565: uvmexp.reserve_kernel);
1.32 art 566:
567: /* swap */
1.35 hugh 568: (void)printf("%11u swap pages\n", uvmexp.swpages);
569: (void)printf("%11u swap pages in use\n", uvmexp.swpginuse);
570: (void)printf("%11u total anon's in system\n", uvmexp.nanon);
571: (void)printf("%11u free anon's\n", uvmexp.nfreeanon);
1.32 art 572:
573: /* stat counters */
1.35 hugh 574: (void)printf("%11u page faults\n", uvmexp.faults);
575: (void)printf("%11u traps\n", uvmexp.traps);
576: (void)printf("%11u interrupts\n", uvmexp.intrs);
577: (void)printf("%11u cpu context switches\n", uvmexp.swtch);
578: (void)printf("%11u software interrupts\n", uvmexp.softs);
579: (void)printf("%11u syscalls\n", uvmexp.syscalls);
580: (void)printf("%11u pagein operations\n", uvmexp.pageins);
581: (void)printf("%11u swap ins\n", uvmexp.swapins);
582: (void)printf("%11u swap outs\n", uvmexp.swapouts);
583: (void)printf("%11u forks\n", uvmexp.forks);
584: (void)printf("%11u forks where vmspace is shared\n",
1.48 art 585: uvmexp.forks_sharevm);
1.32 art 586:
587: /* daemon counters */
1.64 deraadt 588: (void)printf("%11u number of times the pagedaemon woke up\n",
1.48 art 589: uvmexp.pdwoke);
1.35 hugh 590: (void)printf("%11u revolutions of the clock hand\n", uvmexp.pdrevs);
591: (void)printf("%11u pages freed by pagedaemon\n", uvmexp.pdfreed);
592: (void)printf("%11u pages scanned by pagedaemon\n", uvmexp.pdscans);
593: (void)printf("%11u pages reactivated by pagedaemon\n", uvmexp.pdreact);
594: (void)printf("%11u busy pages found by pagedaemon\n", uvmexp.pdbusy);
1.29 art 595:
1.56 angelos 596: if (nlistf == NULL && memf == NULL) {
1.52 angelos 597: size = sizeof(nchstats);
598: mib[0] = CTL_KERN;
599: mib[1] = KERN_NCHSTATS;
600: if (sysctl(mib, 2, &nchstats, &size, NULL, 0) < 0) {
1.56 angelos 601: warn("could not read kern.nchstats");
1.52 angelos 602: bzero(&nchstats, sizeof(nchstats));
603: }
1.56 angelos 604: } else {
605: kread(X_NCHSTATS, &nchstats, sizeof(nchstats));
1.52 angelos 606: }
607:
1.1 deraadt 608: nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
609: nchstats.ncs_badhits + nchstats.ncs_falsehits +
610: nchstats.ncs_miss + nchstats.ncs_long;
1.35 hugh 611: (void)printf("%11ld total name lookups\n", nchtotal);
1.52 angelos 612: (void)printf("%11s cache hits (%d%% pos + %d%% neg) system %d%% "
613: "per-directory\n",
1.1 deraadt 614: "", PCT(nchstats.ncs_goodhits, nchtotal),
615: PCT(nchstats.ncs_neghits, nchtotal),
616: PCT(nchstats.ncs_pass2, nchtotal));
1.35 hugh 617: (void)printf("%11s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
1.1 deraadt 618: PCT(nchstats.ncs_badhits, nchtotal),
619: PCT(nchstats.ncs_falsehits, nchtotal),
620: PCT(nchstats.ncs_long, nchtotal));
1.52 angelos 621:
1.56 angelos 622: if (nlistf == NULL && memf == NULL) {
1.52 angelos 623: size = sizeof(nselcoll);
624: mib[0] = CTL_KERN;
625: mib[1] = KERN_NSELCOLL;
626: if (sysctl(mib, 2, &nselcoll, &size, NULL, 0) < 0) {
1.56 angelos 627: warn("could not read kern.nselcoll");
1.52 angelos 628: nselcoll = 0;
629: }
1.56 angelos 630: } else {
631: kread(X_NSELCOLL, &nselcoll, sizeof(nselcoll));
1.52 angelos 632: }
1.50 art 633: (void)printf("%11d select collisions\n", nselcoll);
1.1 deraadt 634: }
635:
636: void
637: doforkst()
638: {
639: struct forkstat fks;
1.52 angelos 640: size_t size;
641: int mib[2];
642:
1.56 angelos 643: if (nlistf == NULL && memf == NULL) {
1.52 angelos 644: size = sizeof(struct forkstat);
645: mib[0] = CTL_KERN;
646: mib[1] = KERN_FORKSTAT;
647: if (sysctl(mib, 2, &fks, &size, NULL, 0) < 0) {
1.56 angelos 648: warn("could not read kern.forkstat");
1.52 angelos 649: bzero(&fks, sizeof(struct forkstat));
650: }
1.56 angelos 651: } else {
652: kread(X_FORKSTAT, &fks, sizeof(struct forkstat));
1.52 angelos 653: }
1.1 deraadt 654:
655: (void)printf("%d forks, %d pages, average %.2f\n",
656: fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork);
657: (void)printf("%d vforks, %d pages, average %.2f\n",
1.12 tholo 658: fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / (fks.cntvfork ? fks.cntvfork : 1));
659: (void)printf("%d rforks, %d pages, average %.2f\n",
660: fks.cntrfork, fks.sizrfork, (double)fks.sizrfork / (fks.cntrfork ? fks.cntrfork : 1));
1.36 niklas 661: (void)printf("%d kthread creations, %d pages, average %.2f\n",
662: fks.cntkthread, fks.sizkthread, (double)fks.sizkthread / (fks.cntkthread ? fks.cntkthread : 1));
1.1 deraadt 663: }
664:
665: void
666: dkstats()
667: {
1.62 mpech 668: int dn, state;
1.1 deraadt 669: double etime;
670:
1.6 tholo 671: /* Calculate disk stat deltas. */
672: dkswap();
1.1 deraadt 673: etime = 0;
674: for (state = 0; state < CPUSTATES; ++state) {
1.6 tholo 675: etime += cur.cp_time[state];
1.1 deraadt 676: }
677: if (etime == 0)
678: etime = 1;
679: etime /= hz;
680: for (dn = 0; dn < dk_ndrive; ++dn) {
1.6 tholo 681: if (!dk_select[dn])
1.1 deraadt 682: continue;
1.64 deraadt 683: (void)printf("%3.0f ", cur.dk_xfer[dn] / etime);
1.1 deraadt 684: }
685: }
686:
687: void
688: cpustats()
689: {
1.62 mpech 690: int state;
1.1 deraadt 691: double pct, total;
692:
693: total = 0;
694: for (state = 0; state < CPUSTATES; ++state)
1.6 tholo 695: total += cur.cp_time[state];
1.1 deraadt 696: if (total)
697: pct = 100 / total;
698: else
699: pct = 0;
1.6 tholo 700: (void)printf("%2.0f ", (cur.cp_time[CP_USER] + cur.cp_time[CP_NICE]) * pct);
701: (void)printf("%2.0f ", (cur.cp_time[CP_SYS] + cur.cp_time[CP_INTR]) * pct);
702: (void)printf("%2.0f", cur.cp_time[CP_IDLE] * pct);
1.1 deraadt 703: }
704:
1.53 deraadt 705: #if defined(__i386__)
1.12 tholo 706: /* To get struct intrhand */
1.13 tholo 707: #define _KERNEL
1.12 tholo 708: #include <machine/psl.h>
1.56 angelos 709: #include <machine/cpu.h>
1.13 tholo 710: #undef _KERNEL
1.12 tholo 711: void
712: dointr()
713: {
714: struct intrhand *intrhand[16], *ihp, ih;
1.56 angelos 715: u_long inttotal = 0;
1.19 deraadt 716: time_t uptime;
1.50 art 717: u_long intrstray[16];
1.34 deraadt 718: char iname[17], fname[31];
1.58 pvalchev 719: int i;
720: #if 0
721: int mib[2], l, incflag;
1.56 angelos 722: size_t size;
723: char *intrnames, *intrcount, *intrn, *intrc, *buf1, *buf2;
1.58 pvalchev 724: #endif
1.12 tholo 725:
726: iname[16] = '\0';
727: uptime = getuptime();
728:
1.27 alex 729: (void)printf("interrupt total rate\n");
1.56 angelos 730:
731: #if 0 /* XXX Something else is needed here....get on with it Theo! */
732: if (nlistf == NULL && memf == NULL) {
733: mib[0] = CTL_MACHDEP;
734: mib[1] = CPU_INTRNAMES;
735: size = 0;
736: if (sysctl(mib, 2, NULL, &size, NULL, 0) < 0)
737: err(1, "could not get machdep.intrnames");
738: intrnames = calloc(size, sizeof(char));
739: if (intrnames == NULL)
740: err(1,
741: "could not allocate memory for interrupt names");
742: if (sysctl(mib, 2, intrnames, &size, NULL, 0) < 0)
743: err(1, "could not get machdep.intrnames");
744:
745: mib[1] = CPU_INTRCOUNT;
746: size = 0;
747: if (sysctl(mib, 2, NULL, &size, NULL, 0) < 0)
748: err(1, "could not get machdep.intrcount");
749: intrcount = calloc(size, sizeof(char));
750: if (intrcount == NULL)
751: err(1,
752: "could not allocate memory for interrupt count");
753: if (sysctl(mib, 2, intrcount, &size, NULL, 0) < 0)
754: err(1, "could not get machdep.intrcount");
755:
756: mib[1] = CPU_INTRSTRAY;
757: size = sizeof(intrstray);
758: if (sysctl(mib, 2, intrstray, &size, NULL, 0) < 0) {
759: warn("could not get machdep.intrstray");
760: bzero(intrstray, sizeof(intrstray));
761: }
762:
763: buf1 = intrnames;
764: buf2 = intrcount;
765: i = 0;
766: while ((intrn = strsep(&buf1, ",/")) != NULL) {
767: /* Find what the next delimiter is */
768: for (l = 0; buf2[l] != '\0'; l++) {
769: if (buf2[l] == '/') {
770: /* Don't increase the irq count */
771: incflag = 0;
772: break;
773: } else if (buf2[l] == ',') {
774: incflag = 1;
775: break;
776: }
777: }
778:
779: if ((intrc = strsep(&buf2, ",/")) == NULL)
780: errx(1, "unexpected failure matching interrupts with usage counters");
781:
782: /* Unused interrupt ? If so, skip this entry */
783: if (intrn[0] == '\0') {
784: if (incflag)
785: i++;
786: continue;
787: }
788:
789: snprintf(fname, sizeof fname, "irq%d/%s", i, intrn);
790: printf("%-16.16s %10lu %8lu\n", fname,
791: strtoul(intrc, NULL, 10),
792: strtoul(intrc, NULL, 10) / uptime);
793: inttotal += strtoul(intrc, NULL, 10);
794:
795: if (incflag)
796: i++;
797: }
798:
799: free(intrnames);
800: free(intrcount);
801: } else
802: #endif /* 0 */
803: {
804: kread(X_INTRHAND, intrhand, sizeof(intrhand));
805: kread(X_INTRSTRAY, intrstray, sizeof(intrstray));
806:
807: for (i = 0; i < 16; i++) {
808: ihp = intrhand[i];
809: while (ihp) {
810: if (kvm_read(kd, (u_long)ihp, &ih,
811: sizeof(ih)) != sizeof(ih))
812: errx(1, "vmstat: ih: %s",
813: kvm_geterr(kd));
814: if (kvm_read(kd, (u_long)ih.ih_what, iname,
815: 16) != 16)
816: errx(1, "vmstat: ih_what: %s",
817: kvm_geterr(kd));
818: snprintf(fname, sizeof fname, "irq%d/%s", i,
819: iname);
820: printf("%-16.16s %10lu %8lu\n", fname,
821: ih.ih_count, ih.ih_count / uptime);
822: inttotal += ih.ih_count;
823: ihp = ih.ih_next;
824: }
1.12 tholo 825: }
826: }
1.56 angelos 827:
1.12 tholo 828: for (i = 0; i < 16; i++)
829: if (intrstray[i]) {
1.50 art 830: printf("Stray irq %-2d %10lu %8lu\n",
1.53 deraadt 831: i, intrstray[i], intrstray[i] / uptime);
1.12 tholo 832: inttotal += intrstray[i];
833: }
1.50 art 834: printf("Total %10lu %8lu\n", inttotal, inttotal / uptime);
1.1 deraadt 835: }
836: #else
837: void
838: dointr()
839: {
1.62 mpech 840: long *intrcnt, inttotal;
1.19 deraadt 841: time_t uptime;
1.62 mpech 842: int nintr, inamlen;
843: char *intrname;
1.9 deraadt 844: struct evcntlist allevents;
845: struct evcnt evcnt, *evptr;
1.1 deraadt 846: struct device dev;
847:
848: uptime = getuptime();
849: nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value;
850: inamlen =
851: namelist[X_EINTRNAMES].n_value - namelist[X_INTRNAMES].n_value;
852: intrcnt = malloc((size_t)nintr);
853: intrname = malloc((size_t)inamlen);
1.50 art 854: if (intrcnt == NULL || intrname == NULL)
855: err(1, "malloc");
1.1 deraadt 856: kread(X_INTRCNT, intrcnt, (size_t)nintr);
857: kread(X_INTRNAMES, intrname, (size_t)inamlen);
1.27 alex 858: (void)printf("interrupt total rate\n");
1.1 deraadt 859: inttotal = 0;
860: nintr /= sizeof(long);
861: while (--nintr >= 0) {
862: if (*intrcnt)
1.27 alex 863: (void)printf("%-14s %12ld %8ld\n", intrname,
1.1 deraadt 864: *intrcnt, *intrcnt / uptime);
865: intrname += strlen(intrname) + 1;
866: inttotal += *intrcnt++;
867: }
868: kread(X_ALLEVENTS, &allevents, sizeof allevents);
1.9 deraadt 869: evptr = allevents.tqh_first;
870: while (evptr) {
871: if (kvm_read(kd, (long)evptr, (void *)&evcnt,
1.50 art 872: sizeof evcnt) != sizeof evcnt)
873: errx(1, "event chain trashed: %s", kvm_geterr(kd));
1.1 deraadt 874: if (strcmp(evcnt.ev_name, "intr") == 0) {
875: if (kvm_read(kd, (long)evcnt.ev_dev, (void *)&dev,
1.50 art 876: sizeof dev) != sizeof dev)
877: errx(1, "event chain trashed: %s", kvm_geterr(kd));
1.1 deraadt 878: if (evcnt.ev_count)
1.33 art 879: (void)printf("%-14s %12d %8ld\n", dev.dv_xname,
880: evcnt.ev_count, (long)(evcnt.ev_count / uptime));
1.1 deraadt 881: inttotal += evcnt.ev_count++;
882: }
1.9 deraadt 883: evptr = evcnt.ev_list.tqe_next;
1.1 deraadt 884: }
1.27 alex 885: (void)printf("Total %12ld %8ld\n", inttotal, inttotal / uptime);
1.1 deraadt 886: }
887: #endif
888:
889: /*
890: * These names are defined in <sys/malloc.h>.
891: */
892: char *kmemnames[] = INITKMEMNAMES;
893:
894: void
895: domem()
896: {
1.62 mpech 897: struct kmembuckets *kp;
898: struct kmemstats *ks;
899: int i, j;
1.1 deraadt 900: int len, size, first;
1.50 art 901: u_long totuse = 0, totfree = 0;
902: quad_t totreq = 0;
1.1 deraadt 903: char *name;
904: struct kmemstats kmemstats[M_LAST];
905: struct kmembuckets buckets[MINBUCKET + 16];
1.50 art 906: int mib[4];
907: size_t siz;
908: char buf[BUFSIZ], *bufp, *ap;
909:
910: if (memf == NULL && nlistf == NULL) {
1.53 deraadt 911: mib[0] = CTL_KERN;
1.50 art 912: mib[1] = KERN_MALLOCSTATS;
913: mib[2] = KERN_MALLOC_BUCKETS;
914: siz = sizeof(buf);
915: if (sysctl(mib, 3, buf, &siz, NULL, 0) < 0) {
1.56 angelos 916: warnx("could not read kern.malloc.buckets");
1.50 art 917: return;
918: }
919:
920: bufp = buf;
921: mib[2] = KERN_MALLOC_BUCKET;
922: siz = sizeof(struct kmembuckets);
923: i = 0;
924: while ((ap = strsep(&bufp, ",")) != NULL) {
1.53 deraadt 925: mib[3] = atoi(ap);
1.50 art 926:
927: if (sysctl(mib, 4, &buckets[MINBUCKET + i], &siz,
1.53 deraadt 928: NULL, 0) < 0) {
1.56 angelos 929: warn("could not read kern.malloc.bucket.%d", mib[3]);
1.50 art 930: return;
931: }
932: i++;
933: }
934: } else {
1.53 deraadt 935: kread(X_KMEMBUCKETS, buckets, sizeof(buckets));
1.50 art 936: }
1.1 deraadt 937:
1.18 kstailey 938: for (first = 1, i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16;
939: i++, kp++) {
1.65 ! art 940: if (kp->kb_calls == 0 && !verbose)
1.1 deraadt 941: continue;
1.18 kstailey 942: if (first) {
943: (void)printf("Memory statistics by bucket size\n");
944: (void)printf(
1.50 art 945: " Size In Use Free Requests HighWater Couldfree\n");
1.18 kstailey 946: first = 0;
947: }
1.1 deraadt 948: size = 1 << i;
1.60 art 949: (void)printf("%8d %8llu %6llu %18llu %7llu %10llu\n", size,
950: (unsigned long long)(kp->kb_total - kp->kb_totalfree),
951: (unsigned long long)kp->kb_totalfree,
952: (unsigned long long)kp->kb_calls,
953: (unsigned long long)kp->kb_highwat,
954: (unsigned long long)kp->kb_couldfree);
1.1 deraadt 955: totfree += size * kp->kb_totalfree;
1.18 kstailey 956: }
957:
958: /*
959: * If kmem statistics are not being gathered by the kernel,
960: * first will still be 1.
961: */
962: if (first) {
963: printf(
964: "Kmem statistics are not being gathered by the kernel.\n");
965: return;
1.1 deraadt 966: }
967:
1.52 angelos 968: if (memf == NULL && nlistf == NULL) {
969: bzero(kmemstats, sizeof(kmemstats));
970: for (i = 0; i < M_LAST; i++) {
1.53 deraadt 971: mib[0] = CTL_KERN;
1.52 angelos 972: mib[1] = KERN_MALLOCSTATS;
973: mib[2] = KERN_MALLOC_KMEMSTATS;
974: mib[3] = i;
975: siz = sizeof(struct kmemstats);
976:
977: /*
978: * Skip errors -- these are presumed to be unallocated
979: * entries.
980: */
981: if (sysctl(mib, 4, &kmemstats[i], &siz, NULL, 0) < 0)
982: continue;
983: }
984: } else {
985: kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats));
986: }
987:
1.1 deraadt 988: (void)printf("\nMemory usage type by bucket size\n");
989: (void)printf(" Size Type(s)\n");
990: kp = &buckets[MINBUCKET];
991: for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) {
992: if (kp->kb_calls == 0)
993: continue;
994: first = 1;
995: len = 8;
996: for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
997: if (ks->ks_calls == 0)
998: continue;
999: if ((ks->ks_size & j) == 0)
1000: continue;
1001: name = kmemnames[i] ? kmemnames[i] : "undefined";
1002: len += 2 + strlen(name);
1003: if (first)
1004: printf("%8d %s", j, name);
1005: else
1006: printf(",");
1007: if (len >= 80) {
1008: printf("\n\t ");
1009: len = 10 + strlen(name);
1010: }
1011: if (!first)
1012: printf(" %s", name);
1013: first = 0;
1014: }
1015: printf("\n");
1016: }
1017:
1018: (void)printf(
1.26 deraadt 1019: "\nMemory statistics by type Type Kern\n");
1.1 deraadt 1020: (void)printf(
1.26 deraadt 1021: " Type InUse MemUse HighUse Limit Requests Limit Limit Size(s)\n");
1.1 deraadt 1022: for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
1023: if (ks->ks_calls == 0)
1024: continue;
1.24 mickey 1025: (void)printf("%14s%6ld%6ldK%7ldK%6ldK%9ld%5u%6u",
1.1 deraadt 1026: kmemnames[i] ? kmemnames[i] : "undefined",
1027: ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
1028: (ks->ks_maxused + 1023) / 1024,
1029: (ks->ks_limit + 1023) / 1024, ks->ks_calls,
1030: ks->ks_limblocks, ks->ks_mapblocks);
1031: first = 1;
1032: for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
1033: if ((ks->ks_size & j) == 0)
1034: continue;
1035: if (first)
1036: printf(" %d", j);
1037: else
1038: printf(",%d", j);
1039: first = 0;
1040: }
1041: printf("\n");
1042: totuse += ks->ks_memuse;
1043: totreq += ks->ks_calls;
1044: }
1045: (void)printf("\nMemory Totals: In Use Free Requests\n");
1.50 art 1046: (void)printf(" %7luK %6luK %8qu\n",
1.1 deraadt 1047: (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq);
1048: }
1049:
1.54 art 1050: static void
1051: print_pool(struct pool *pp, char *name)
1052: {
1053: static int first = 1;
1054: int ovflw;
1055: char maxp[32];
1056:
1057: if (first) {
1058: (void)printf("Memory resource pool statistics\n");
1059: (void)printf(
1060: "%-11s%5s%9s%5s%9s%6s%6s%6s%6s%6s%6s%5s\n",
1061: "Name",
1062: "Size",
1063: "Requests",
1064: "Fail",
1065: "Releases",
1066: "Pgreq",
1067: "Pgrel",
1068: "Npage",
1069: "Hiwat",
1070: "Minpg",
1071: "Maxpg",
1072: "Idle");
1073: first = 0;
1074: }
1.65 ! art 1075:
! 1076: /* Skip unused pools unless verbose output. */
! 1077: if (pp->pr_nget == 0 && !verbose)
! 1078: return;
! 1079:
1.54 art 1080: if (pp->pr_maxpages == UINT_MAX)
1081: sprintf(maxp, "inf");
1082: else
1083: sprintf(maxp, "%u", pp->pr_maxpages);
1084: /*
1085: * Print single word. `ovflow' is number of characters didn't fit
1086: * on the last word. `fmt' is a format string to print this word.
1087: * It must contain asterisk for field width. `width' is a width
1088: * occupied by this word. `fixed' is a number of constant chars in
1089: * `fmt'. `val' is a value to be printed using format string `fmt'.
1090: */
1091: #define PRWORD(ovflw, fmt, width, fixed, val) do { \
1092: (ovflw) += printf((fmt), \
1093: (width) - (fixed) - (ovflw) > 0 ? \
1094: (width) - (fixed) - (ovflw) : 0, \
1095: (val)) - (width); \
1096: if ((ovflw) < 0) \
1097: (ovflw) = 0; \
1098: } while (/* CONSTCOND */0)
1099:
1100: ovflw = 0;
1101: PRWORD(ovflw, "%-*s", 11, 0, name);
1102: PRWORD(ovflw, " %*u", 5, 1, pp->pr_size);
1103: PRWORD(ovflw, " %*lu", 9, 1, pp->pr_nget);
1104: PRWORD(ovflw, " %*lu", 5, 1, pp->pr_nfail);
1105: PRWORD(ovflw, " %*lu", 9, 1, pp->pr_nput);
1106: PRWORD(ovflw, " %*lu", 6, 1, pp->pr_npagealloc);
1107: PRWORD(ovflw, " %*lu", 6, 1, pp->pr_npagefree);
1108: PRWORD(ovflw, " %*d", 6, 1, pp->pr_npages);
1109: PRWORD(ovflw, " %*d", 6, 1, pp->pr_hiwat);
1110: PRWORD(ovflw, " %*d", 6, 1, pp->pr_minpages);
1111: PRWORD(ovflw, " %*s", 6, 1, maxp);
1112: PRWORD(ovflw, " %*lu\n", 5, 1, pp->pr_nidle);
1113: }
1114:
1.55 art 1115: static void dopool_kvm(void);
1116: static void dopool_sysctl(void);
1117:
1.48 art 1118: void
1119: dopool(void)
1120: {
1.55 art 1121: if (nlistf == NULL && memf == NULL)
1122: dopool_sysctl();
1123: else
1124: dopool_kvm();
1125: }
1126:
1127: void
1128: dopool_sysctl(void)
1129: {
1.63 art 1130: long total = 0, inuse = 0;
1.55 art 1131: struct pool pool;
1132: size_t size;
1133: int mib[4];
1134: int npools, i;
1135:
1136: mib[0] = CTL_KERN;
1137: mib[1] = KERN_POOL;
1138: mib[2] = KERN_POOL_NPOOLS;
1139: size = sizeof(npools);
1140: if (sysctl(mib, 3, &npools, &size, NULL, 0) < 0) {
1141: printf("Can't figure out number of pools in kernel: %s\n",
1142: strerror(errno));
1143: return;
1144: }
1145:
1146: for (i = 1; npools; i++) {
1147: char name[32];
1148:
1149: mib[0] = CTL_KERN;
1150: mib[1] = KERN_POOL;
1151: mib[2] = KERN_POOL_POOL;
1152: mib[3] = i;
1153: size = sizeof(struct pool);
1154: if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) {
1155: if (errno == ENOENT)
1156: continue;
1157: printf("error getting pool: %s\n", strerror(errno));
1158: return;
1159: }
1160: npools--;
1161: mib[2] = KERN_POOL_NAME;
1162: size = sizeof(name);
1163: if (sysctl(mib, 4, &name, &size, NULL, 0) < 0) {
1164: printf("error getting pool name: %s\n",
1165: strerror(errno));
1166: return;
1167: }
1168: print_pool(&pool, name);
1.63 art 1169:
1170: inuse += (pool.pr_nget - pool.pr_nput) * pool.pr_size;
1171: total += pool.pr_npages * getpagesize(); /* XXX */
1.55 art 1172: }
1.63 art 1173:
1174: inuse /= 1024;
1175: total /= 1024;
1176: printf("\nIn use %ldK, total allocated %ldK; utilization %.1f%%\n",
1177: inuse, total, (double)(100 * inuse) / total);
1.55 art 1178: }
1179:
1180: void
1181: dopool_kvm(void)
1182: {
1.48 art 1183: long addr;
1184: long total = 0, inuse = 0;
1185: TAILQ_HEAD(,pool) pool_head;
1186: struct pool pool, *pp = &pool;
1187:
1188: kread(X_POOLHEAD, &pool_head, sizeof(pool_head));
1189: addr = (long)TAILQ_FIRST(&pool_head);
1190:
1.55 art 1191: while (addr != 0) {
1.54 art 1192: char name[32];
1.56 angelos 1193:
1.48 art 1194: if (kvm_read(kd, addr, (void *)pp, sizeof *pp) != sizeof *pp) {
1195: (void)fprintf(stderr,
1196: "vmstat: pool chain trashed: %s\n",
1197: kvm_geterr(kd));
1198: exit(1);
1199: }
1200: if (kvm_read(kd, (long)pp->pr_wchan, name, sizeof name) < 0) {
1201: (void)fprintf(stderr,
1202: "vmstat: pool name trashed: %s\n",
1203: kvm_geterr(kd));
1204: exit(1);
1205: }
1.56 angelos 1206:
1.48 art 1207: name[31] = '\0';
1208:
1.54 art 1209: print_pool(pp, name);
1.48 art 1210:
1211: inuse += (pp->pr_nget - pp->pr_nput) * pp->pr_size;
1.63 art 1212: total += pp->pr_npages * getpagesize(); /* XXX */
1.56 angelos 1213:
1.48 art 1214: addr = (long)TAILQ_NEXT(pp, pr_poollist);
1215: }
1216:
1217: inuse /= 1024;
1218: total /= 1024;
1219: printf("\nIn use %ldK, total allocated %ldK; utilization %.1f%%\n",
1220: inuse, total, (double)(100 * inuse) / total);
1221: }
1222:
1.1 deraadt 1223: /*
1224: * kread reads something from the kernel, given its nlist index.
1225: */
1226: void
1227: kread(nlx, addr, size)
1228: int nlx;
1229: void *addr;
1230: size_t size;
1231: {
1232: char *sym;
1233:
1234: if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) {
1235: sym = namelist[nlx].n_name;
1236: if (*sym == '_')
1237: ++sym;
1.50 art 1238: errx(1, "symbol %s not defined", sym);
1.1 deraadt 1239: }
1240: if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) {
1241: sym = namelist[nlx].n_name;
1242: if (*sym == '_')
1243: ++sym;
1.50 art 1244: errx(1, "%s: %s", sym, kvm_geterr(kd));
1.1 deraadt 1245: }
1246: }
1247:
1248: void
1249: usage()
1250: {
1.50 art 1251: (void)fprintf(stderr, "usage: %s [-fimst] [-c count] [-M core] "
1252: "[-N system] [-w wait] [disks]\n", __progname);
1.1 deraadt 1253: exit(1);
1254: }