pstat.c revision 181905
11553Srgrimes/*- 223687Speter * Copyright (c) 1980, 1991, 1993, 1994 31553Srgrimes * The Regents of the University of California. All rights reserved. 497378Sdes * Copyright (c) 2002 Networks Associates Technologies, Inc. 597378Sdes * All rights reserved. 61553Srgrimes * 797378Sdes * Portions of this software were developed for the FreeBSD Project by 897378Sdes * ThinkSec AS and NAI Labs, the Security Research Division of Network 997378Sdes * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 1097378Sdes * ("CBOSS"), as part of the DARPA CHATS research program. 1197378Sdes * 121553Srgrimes * Redistribution and use in source and binary forms, with or without 131553Srgrimes * modification, are permitted provided that the following conditions 141553Srgrimes * are met: 151553Srgrimes * 1. Redistributions of source code must retain the above copyright 161553Srgrimes * notice, this list of conditions and the following disclaimer. 171553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 181553Srgrimes * notice, this list of conditions and the following disclaimer in the 191553Srgrimes * documentation and/or other materials provided with the distribution. 201553Srgrimes * 4. Neither the name of the University nor the names of its contributors 211553Srgrimes * may be used to endorse or promote products derived from this software 221553Srgrimes * without specific prior written permission. 231553Srgrimes * 241553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341553Srgrimes * SUCH DAMAGE. 351553Srgrimes */ 361553Srgrimes 37114601Sobrien#if 0 381553Srgrimes#ifndef lint 3930243Scharnierstatic const char copyright[] = 4023687Speter"@(#) Copyright (c) 1980, 1991, 1993, 1994\n\ 411553Srgrimes The Regents of the University of California. All rights reserved.\n"; 421553Srgrimes#endif /* not lint */ 431553Srgrimes 441553Srgrimes#ifndef lint 4523687Speterstatic char sccsid[] = "@(#)pstat.c 8.16 (Berkeley) 5/9/95"; 46114601Sobrien#endif /* not lint */ 4730243Scharnier#endif 48114601Sobrien#include <sys/cdefs.h> 49114601Sobrien__FBSDID("$FreeBSD: head/usr.sbin/pstat/pstat.c 181905 2008-08-20 08:31:58Z ed $"); 501553Srgrimes 511553Srgrimes#include <sys/param.h> 521553Srgrimes#include <sys/time.h> 531553Srgrimes#include <sys/file.h> 541553Srgrimes#include <sys/stat.h> 5597176Sdes#include <sys/stdint.h> 561553Srgrimes#include <sys/ioctl.h> 571553Srgrimes#include <sys/tty.h> 5842955Sdillon#include <sys/blist.h> 591553Srgrimes 601553Srgrimes#include <sys/sysctl.h> 61138129Sdas#include <vm/vm_param.h> 621553Srgrimes 631553Srgrimes#include <err.h> 64138129Sdas#include <errno.h> 6518570Sbde#include <fcntl.h> 661553Srgrimes#include <kvm.h> 67143929Skeramida#include <libutil.h> 681553Srgrimes#include <limits.h> 691553Srgrimes#include <nlist.h> 701553Srgrimes#include <stdio.h> 711553Srgrimes#include <stdlib.h> 721553Srgrimes#include <string.h> 731553Srgrimes#include <unistd.h> 741553Srgrimes 7597375Sdesenum { 7697375Sdes NL_CONSTTY, 7797375Sdes NL_MAXFILES, 7897375Sdes NL_NFILES, 7997375Sdes NL_TTY_LIST 8097375Sdes}; 8197375Sdes 8297171Sdesstatic struct nlist nl[] = { 83143936Skeramida { .n_name = "_constty" }, 84143936Skeramida { .n_name = "_maxfiles" }, 85166696Sjhb { .n_name = "_openfiles" }, 86143936Skeramida { .n_name = "_tty_list" }, 87143936Skeramida { .n_name = "" } 881553Srgrimes}; 891553Srgrimes 90143929Skeramidastatic int humanflag; 9197171Sdesstatic int usenumflag; 9297171Sdesstatic int totalflag; 9397171Sdesstatic int swapflag; 9497174Sdesstatic char *nlistf; 9597174Sdesstatic char *memf; 9697171Sdesstatic kvm_t *kd; 971553Srgrimes 9897171Sdesstatic char *usagestr; 998495Sphk 10097172Sdesstatic void filemode(void); 10197367Sdesstatic int getfiles(char **, size_t *); 10297172Sdesstatic void swapmode(void); 10397172Sdesstatic void ttymode(void); 10497367Sdesstatic void ttyprt(struct xtty *); 10597172Sdesstatic void usage(void); 1061553Srgrimes 1071553Srgrimesint 10897172Sdesmain(int argc, char *argv[]) 1091553Srgrimes{ 1101553Srgrimes int ch, i, quit, ret; 11197173Sdes int fileflag, ttyflag; 1128495Sphk char buf[_POSIX2_LINE_MAX],*opts; 1131553Srgrimes 11497173Sdes fileflag = swapflag = ttyflag = 0; 1158495Sphk 1168495Sphk /* We will behave like good old swapinfo if thus invoked */ 11797378Sdes opts = strrchr(argv[0], '/'); 1188495Sphk if (opts) 1198495Sphk opts++; 1208495Sphk else 1218495Sphk opts = argv[0]; 12297378Sdes if (!strcmp(opts, "swapinfo")) { 1238495Sphk swapflag = 1; 124168227Smarkm opts = "ghkmM:N:"; 125168227Smarkm usagestr = "swapinfo [-ghkm] [-M core [-N system]]"; 1268495Sphk } else { 127168292Sru opts = "TM:N:fghkmnst"; 128168292Sru usagestr = "pstat [-Tfghkmnst] [-M core [-N system]]"; 1298495Sphk } 1308495Sphk 13124428Simp while ((ch = getopt(argc, argv, opts)) != -1) 1321553Srgrimes switch (ch) { 1331553Srgrimes case 'f': 1341553Srgrimes fileflag = 1; 1351553Srgrimes break; 136168227Smarkm case 'g': 137171195Sscf setenv("BLOCKSIZE", "1G", 1); 138168227Smarkm break; 139143929Skeramida case 'h': 140143929Skeramida humanflag = 1; 141143929Skeramida break; 1428495Sphk case 'k': 143171195Sscf setenv("BLOCKSIZE", "1K", 1); 1448495Sphk break; 145168227Smarkm case 'm': 146171195Sscf setenv("BLOCKSIZE", "1M", 1); 147168227Smarkm break; 1481553Srgrimes case 'M': 1491553Srgrimes memf = optarg; 1501553Srgrimes break; 1511553Srgrimes case 'N': 1521553Srgrimes nlistf = optarg; 1531553Srgrimes break; 1541553Srgrimes case 'n': 1551553Srgrimes usenumflag = 1; 1561553Srgrimes break; 1571553Srgrimes case 's': 15842955Sdillon ++swapflag; 1591553Srgrimes break; 1601553Srgrimes case 'T': 1611553Srgrimes totalflag = 1; 1621553Srgrimes break; 1631553Srgrimes case 't': 1641553Srgrimes ttyflag = 1; 1651553Srgrimes break; 1661553Srgrimes default: 16730243Scharnier usage(); 1681553Srgrimes } 1691553Srgrimes argc -= optind; 1701553Srgrimes argv += optind; 1711553Srgrimes 17297176Sdes if (memf != NULL) { 17397176Sdes kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf); 17497176Sdes if (kd == NULL) 17597176Sdes errx(1, "kvm_openfiles: %s", buf); 17697176Sdes if ((ret = kvm_nlist(kd, nl)) != 0) { 17797176Sdes if (ret == -1) 17897176Sdes errx(1, "kvm_nlist: %s", kvm_geterr(kd)); 17997176Sdes quit = 0; 18097375Sdes for (i = 0; nl[i].n_name[0] != '\0'; ++i) 18197375Sdes if (nl[i].n_value == 0) { 18297176Sdes quit = 1; 18397176Sdes warnx("undefined symbol: %s", 18497176Sdes nl[i].n_name); 18597176Sdes } 18697176Sdes if (quit) 18797176Sdes exit(1); 18897176Sdes } 1891553Srgrimes } 19097173Sdes if (!(fileflag | ttyflag | swapflag | totalflag)) 19130243Scharnier usage(); 1921553Srgrimes if (fileflag || totalflag) 1931553Srgrimes filemode(); 1941553Srgrimes if (ttyflag) 1951553Srgrimes ttymode(); 1961553Srgrimes if (swapflag || totalflag) 1971553Srgrimes swapmode(); 1981553Srgrimes exit (0); 1991553Srgrimes} 2001553Srgrimes 20130243Scharnierstatic void 20297172Sdesusage(void) 20330243Scharnier{ 20430243Scharnier fprintf(stderr, "usage: %s\n", usagestr); 20530243Scharnier exit (1); 20630243Scharnier} 20730243Scharnier 208110148Srobertstatic const char fhdr32[] = 209110148Srobert " LOC TYPE FLG CNT MSG DATA OFFSET\n"; 210110148Srobert/* c0000000 ------ RWAI 123 123 c0000000 1000000000000000 */ 211110148Srobert 212110148Srobertstatic const char fhdr64[] = 213110148Srobert " LOC TYPE FLG CNT MSG DATA OFFSET\n"; 214110148Srobert/* c000000000000000 ------ RWAI 123 123 c000000000000000 1000000000000000 */ 215110148Srobert 21697171Sdesstatic const char hdr[] = 217181905Sed" LINE INQ CAN LIN LOW OUTQ USE LOW COL SESS PGID STATE\n"; 2181553Srgrimes 21997171Sdesstatic void 22097375Sdesttymode_kvm(void) 2211553Srgrimes{ 222130267Sphk TAILQ_HEAD(, tty) tl; 22397375Sdes struct tty *tp, tty; 22497375Sdes struct xtty xt; 22597375Sdes 22697375Sdes (void)printf("%s", hdr); 22797375Sdes bzero(&xt, sizeof xt); 22897375Sdes xt.xt_size = sizeof xt; 22997375Sdes if (kvm_read(kd, nl[NL_TTY_LIST].n_value, &tl, sizeof tl) != sizeof tl) 23097375Sdes errx(1, "kvm_read(): %s", kvm_geterr(kd)); 231130267Sphk tp = TAILQ_FIRST(&tl); 23297375Sdes while (tp != NULL) { 23397375Sdes if (kvm_read(kd, (u_long)tp, &tty, sizeof tty) != sizeof tty) 23497375Sdes errx(1, "kvm_read(): %s", kvm_geterr(kd)); 235181905Sed xt.xt_insize = tty.t_inq.ti_nblocks * TTYINQ_DATASIZE; 236181905Sed xt.xt_incc = tty.t_inq.ti_linestart - tty.t_inq.ti_begin; 237181905Sed xt.xt_inlc = tty.t_inq.ti_end - tty.t_inq.ti_linestart; 238181905Sed xt.xt_inlow = tty.t_inlow; 239181905Sed xt.xt_outsize = tty.t_outq.to_nblocks * TTYOUTQ_DATASIZE; 240181905Sed xt.xt_outcc = tty.t_outq.to_end - tty.t_outq.to_begin; 241181905Sed xt.xt_outlow = tty.t_outlow; 242181905Sed xt.xt_column = tty.t_column; 243181905Sed /* xt.xt_pgid = ... */ 244181905Sed /* xt.xt_sid = ... */ 245181905Sed xt.xt_flags = tty.t_flags; 246181905Sed xt.xt_dev = NODEV; 24797375Sdes ttyprt(&xt); 248178987Sremko tp = TAILQ_NEXT(&tty, t_list); 24997375Sdes } 25097375Sdes} 25197375Sdes 25297375Sdesstatic void 25397375Sdesttymode_sysctl(void) 25497375Sdes{ 25597367Sdes struct xtty *xt, *end; 25697367Sdes void *xttys; 25797367Sdes size_t len; 2581553Srgrimes 25978378Sdd (void)printf("%s", hdr); 26097367Sdes if ((xttys = malloc(len = sizeof *xt)) == NULL) 26197367Sdes err(1, "malloc()"); 26297367Sdes while (sysctlbyname("kern.ttys", xttys, &len, 0, 0) == -1) { 26397367Sdes if (errno != ENOMEM) 26497367Sdes err(1, "sysctlbyname()"); 26597367Sdes len *= 2; 26697367Sdes if ((xttys = realloc(xttys, len)) == NULL) 26797367Sdes err(1, "realloc()"); 26849539Sphk } 26997367Sdes if (len > 0) { 27097367Sdes end = (struct xtty *)((char *)xttys + len); 27197367Sdes for (xt = xttys; xt < end; xt++) 27297367Sdes ttyprt(xt); 27397367Sdes } 2741553Srgrimes} 2751553Srgrimes 27697171Sdesstatic void 27797375Sdesttymode(void) 2781553Srgrimes{ 2791553Srgrimes 28097375Sdes if (kd != NULL) 28197375Sdes ttymode_kvm(); 28297375Sdes else 28397375Sdes ttymode_sysctl(); 2841553Srgrimes} 2851553Srgrimes 28697171Sdesstatic struct { 2871553Srgrimes int flag; 2881553Srgrimes char val; 2891553Srgrimes} ttystates[] = { 290181905Sed#if 0 291181905Sed { TF_NOPREFIX, 'N' }, 2929620Sbde#endif 293181905Sed { TF_INITLOCK, 'I' }, 294181905Sed { TF_CALLOUT, 'C' }, 295181905Sed 296181905Sed /* Keep these together -> 'Oi' and 'Oo'. */ 297181905Sed { TF_OPENED, 'O' }, 298181905Sed { TF_OPENED_IN, 'i' }, 299181905Sed { TF_OPENED_OUT,'o' }, 300181905Sed 301181905Sed { TF_GONE, 'G' }, 302181905Sed { TF_OPENCLOSE, 'B' }, 303181905Sed { TF_ASYNC, 'Y' }, 304181905Sed { TF_LITERAL, 'L' }, 305181905Sed 306181905Sed /* Keep these together -> 'Hi' and 'Ho'. */ 307181905Sed { TF_HIWAT, 'H' }, 308181905Sed { TF_HIWAT_IN, 'i' }, 309181905Sed { TF_HIWAT_OUT, 'o' }, 310181905Sed 311181905Sed { TF_STOPPED, 'S' }, 312181905Sed { TF_EXCLUDE, 'X' }, 313181905Sed { TF_BYPASS, 'l' }, 314181905Sed { TF_ZOMBIE, 'Z' }, 315181905Sed 316181905Sed { 0, '\0' }, 3171553Srgrimes}; 3181553Srgrimes 31997171Sdesstatic void 32097367Sdesttyprt(struct xtty *xt) 3211553Srgrimes{ 32223687Speter int i, j; 323181905Sed char *name; 3241553Srgrimes 32597367Sdes if (xt->xt_size != sizeof *xt) 32697367Sdes errx(1, "struct xtty size mismatch"); 32797367Sdes if (usenumflag || xt->xt_dev == 0 || 32897367Sdes (name = devname(xt->xt_dev, S_IFCHR)) == NULL) 329181905Sed printf("%5d,%4d ", major(xt->xt_dev), minor(xt->xt_dev)); 3301553Srgrimes else 331181905Sed printf("%10s ", name); 332181905Sed printf("%5zu %4zu %4zu %4zu %5zu %4zu %4zu %5u %5d %5d ", 333181905Sed xt->xt_insize, xt->xt_incc, xt->xt_inlc, 334181905Sed (xt->xt_insize - xt->xt_inlow), xt->xt_outsize, 335181905Sed xt->xt_outcc, (xt->xt_outsize - xt->xt_outlow), 336181905Sed xt->xt_column, xt->xt_sid, xt->xt_pgid); 3371553Srgrimes for (i = j = 0; ttystates[i].flag; i++) 338181905Sed if (xt->xt_flags & ttystates[i].flag) { 339181905Sed putchar(ttystates[i].val); 340181905Sed j++; 341181905Sed } 3421553Srgrimes if (j == 0) 343181905Sed putchar('-'); 344181905Sed putchar('\n'); 3451553Srgrimes} 3461553Srgrimes 34797171Sdesstatic void 34897172Sdesfilemode(void) 3491553Srgrimes{ 350101044Sdes struct xfile *fp; 3511553Srgrimes char *buf, flagbuf[16], *fbp; 35297378Sdes int maxf, openf; 35397176Sdes size_t len; 354110148Srobert static char *dtypes[] = { "???", "inode", "socket", "pipe", 355110148Srobert "fifo", "kqueue", "crypto" }; 356101044Sdes int i; 357110148Srobert int wid; 3581553Srgrimes 35997176Sdes if (kd != NULL) { 36097378Sdes if (kvm_read(kd, nl[NL_MAXFILES].n_value, 36197378Sdes &maxf, sizeof maxf) != sizeof maxf || 36297378Sdes kvm_read(kd, nl[NL_NFILES].n_value, 36397378Sdes &openf, sizeof openf) != sizeof openf) 36497378Sdes errx(1, "kvm_read(): %s", kvm_geterr(kd)); 36597176Sdes } else { 36697378Sdes len = sizeof(int); 36797378Sdes if (sysctlbyname("kern.maxfiles", &maxf, &len, 0, 0) == -1 || 36897378Sdes sysctlbyname("kern.openfiles", &openf, &len, 0, 0) == -1) 36997176Sdes err(1, "sysctlbyname()"); 37097176Sdes } 37197176Sdes 3721553Srgrimes if (totalflag) { 37397378Sdes (void)printf("%3d/%3d files\n", openf, maxf); 3741553Srgrimes return; 3751553Srgrimes } 3761553Srgrimes if (getfiles(&buf, &len) == -1) 3771553Srgrimes return; 378101044Sdes openf = len / sizeof *fp; 379110148Srobert 38097378Sdes (void)printf("%d/%d open files\n", openf, maxf); 381110148Srobert printf(sizeof(uintptr_t) == 4 ? fhdr32 : fhdr64); 382110148Srobert wid = (int)sizeof(uintptr_t) * 2; 383101044Sdes for (fp = (struct xfile *)buf, i = 0; i < openf; ++fp, ++i) { 384110148Srobert if ((size_t)fp->xf_type >= sizeof(dtypes) / sizeof(dtypes[0])) 3851553Srgrimes continue; 386110148Srobert (void)printf("%*jx", wid, (uintmax_t)(uintptr_t)fp->xf_file); 387110148Srobert (void)printf(" %-6.6s", dtypes[fp->xf_type]); 3881553Srgrimes fbp = flagbuf; 389101044Sdes if (fp->xf_flag & FREAD) 3901553Srgrimes *fbp++ = 'R'; 391101044Sdes if (fp->xf_flag & FWRITE) 3921553Srgrimes *fbp++ = 'W'; 393101044Sdes if (fp->xf_flag & FAPPEND) 3941553Srgrimes *fbp++ = 'A'; 395101044Sdes if (fp->xf_flag & FASYNC) 3961553Srgrimes *fbp++ = 'I'; 3971553Srgrimes *fbp = '\0'; 398110148Srobert (void)printf(" %4s %3d", flagbuf, fp->xf_count); 399110148Srobert (void)printf(" %3d", fp->xf_msgcount); 400110148Srobert (void)printf(" %*jx", wid, (uintmax_t)(uintptr_t)fp->xf_data); 401110148Srobert (void)printf(" %*jx\n", (int)sizeof(fp->xf_offset) * 2, 402110148Srobert (uintmax_t)fp->xf_offset); 4031553Srgrimes } 4041553Srgrimes free(buf); 4051553Srgrimes} 4061553Srgrimes 40797171Sdesstatic int 40897367Sdesgetfiles(char **abuf, size_t *alen) 4091553Srgrimes{ 4101553Srgrimes size_t len; 4111553Srgrimes int mib[2]; 4121553Srgrimes char *buf; 4131553Srgrimes 4141553Srgrimes /* 4151553Srgrimes * XXX 4161553Srgrimes * Add emulation of KINFO_FILE here. 4171553Srgrimes */ 41897176Sdes if (kd != NULL) 41930243Scharnier errx(1, "files on dead kernel, not implemented"); 4201553Srgrimes 4211553Srgrimes mib[0] = CTL_KERN; 4221553Srgrimes mib[1] = KERN_FILE; 4231553Srgrimes if (sysctl(mib, 2, NULL, &len, NULL, 0) == -1) { 4241553Srgrimes warn("sysctl: KERN_FILE"); 4251553Srgrimes return (-1); 4261553Srgrimes } 4271553Srgrimes if ((buf = malloc(len)) == NULL) 42830243Scharnier errx(1, "malloc"); 4291553Srgrimes if (sysctl(mib, 2, buf, &len, NULL, 0) == -1) { 4301553Srgrimes warn("sysctl: KERN_FILE"); 4311553Srgrimes return (-1); 4321553Srgrimes } 4331553Srgrimes *abuf = buf; 4341553Srgrimes *alen = len; 4351553Srgrimes return (0); 4361553Srgrimes} 4371553Srgrimes 4381553Srgrimes/* 4391553Srgrimes * swapmode is based on a program called swapinfo written 4401553Srgrimes * by Kevin Lahey <kml@rokkaku.atl.ga.us>. 4411553Srgrimes */ 44297176Sdes 443143929Skeramida#define CONVERT(v) ((int64_t)(v) * pagesize / blocksize) 44497176Sdesstatic struct kvm_swap swtot; 44597176Sdesstatic int nswdev; 44697176Sdes 44797171Sdesstatic void 44897176Sdesprint_swap_header(void) 4491553Srgrimes{ 450108457Smike int hlen; 45143046Sdillon long blocksize; 45297176Sdes const char *header; 4531553Srgrimes 4541553Srgrimes header = getbsize(&hlen, &blocksize); 45597176Sdes if (totalflag == 0) 456118275Sphk (void)printf("%-15s %*s %8s %8s %8s\n", 457108457Smike "Device", hlen, header, 458118275Sphk "Used", "Avail", "Capacity"); 45997176Sdes} 46042955Sdillon 46197176Sdesstatic void 462143929Skeramidaprint_swap_line(const char *devname, intmax_t nblks, intmax_t bused, 463143929Skeramida intmax_t bavail, float bpercent) 46497176Sdes{ 465143929Skeramida char usedbuf[5]; 466143929Skeramida char availbuf[5]; 467108457Smike int hlen, pagesize; 46897176Sdes long blocksize; 46997176Sdes 47097176Sdes pagesize = getpagesize(); 47197176Sdes getbsize(&hlen, &blocksize); 472143929Skeramida 473143929Skeramida printf("%-15s %*jd ", devname, hlen, CONVERT(nblks)); 474143929Skeramida if (humanflag) { 475143929Skeramida humanize_number(usedbuf, sizeof(usedbuf), 476143929Skeramida CONVERT(blocksize * bused), "", 477143929Skeramida HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 478143929Skeramida humanize_number(availbuf, sizeof(availbuf), 479143929Skeramida CONVERT(blocksize * bavail), "", 480143929Skeramida HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 481143929Skeramida printf("%8s %8s %5.0f%%\n", usedbuf, availbuf, bpercent); 482143929Skeramida } else { 483143929Skeramida printf("%8jd %8jd %5.0f%%\n", (intmax_t)CONVERT(bused), 484143929Skeramida (intmax_t)CONVERT(bavail), bpercent); 485143929Skeramida } 486143929Skeramida} 487143929Skeramida 488143929Skeramidastatic void 489143929Skeramidaprint_swap(struct kvm_swap *ksw) 490143929Skeramida{ 491143929Skeramida 49297176Sdes swtot.ksw_total += ksw->ksw_total; 49397176Sdes swtot.ksw_used += ksw->ksw_used; 49497176Sdes ++nswdev; 495143929Skeramida if (totalflag == 0) 496143929Skeramida print_swap_line(ksw->ksw_devname, ksw->ksw_total, 497152558Srwatson ksw->ksw_used, ksw->ksw_total - ksw->ksw_used, 498118275Sphk (ksw->ksw_used * 100.0) / ksw->ksw_total); 49997176Sdes} 50042955Sdillon 50197176Sdesstatic void 50297176Sdesprint_swap_total(void) 50397176Sdes{ 504108457Smike int hlen, pagesize; 50597176Sdes long blocksize; 50697176Sdes 50797176Sdes pagesize = getpagesize(); 50897176Sdes getbsize(&hlen, &blocksize); 50943046Sdillon if (totalflag) { 51043046Sdillon blocksize = 1024 * 1024; 511143929Skeramida (void)printf("%jdM/%jdM swap space\n", 51297176Sdes CONVERT(swtot.ksw_used), CONVERT(swtot.ksw_total)); 51397176Sdes } else if (nswdev > 1) { 514143929Skeramida print_swap_line("Total", swtot.ksw_total, swtot.ksw_used, 515143929Skeramida swtot.ksw_total - swtot.ksw_used, 51697176Sdes (swtot.ksw_used * 100.0) / swtot.ksw_total); 51797176Sdes } 51897176Sdes} 5191553Srgrimes 52097176Sdesstatic void 52197176Sdesswapmode_kvm(void) 52297176Sdes{ 52397176Sdes struct kvm_swap kswap[16]; 52497176Sdes int i, n; 52597176Sdes 52697176Sdes n = kvm_getswapinfo(kd, kswap, sizeof kswap / sizeof kswap[0], 527118278Sphk SWIF_DEV_PREFIX); 52897176Sdes 52997176Sdes print_swap_header(); 53097176Sdes for (i = 0; i < n; ++i) 53197176Sdes print_swap(&kswap[i]); 53297176Sdes print_swap_total(); 53397176Sdes} 53497176Sdes 53597176Sdesstatic void 53697176Sdesswapmode_sysctl(void) 53797176Sdes{ 53897176Sdes struct kvm_swap ksw; 53997176Sdes struct xswdev xsw; 54097176Sdes size_t mibsize, size; 54197176Sdes int mib[16], n; 54297176Sdes 54397176Sdes print_swap_header(); 54497176Sdes mibsize = sizeof mib / sizeof mib[0]; 54597176Sdes if (sysctlnametomib("vm.swap_info", mib, &mibsize) == -1) 54697176Sdes err(1, "sysctlnametomib()"); 54797176Sdes for (n = 0; ; ++n) { 54897176Sdes mib[mibsize] = n; 54997176Sdes size = sizeof xsw; 550126643Smarkm if (sysctl(mib, mibsize + 1, &xsw, &size, NULL, 0) == -1) 55197176Sdes break; 55297176Sdes if (xsw.xsw_version != XSWDEV_VERSION) 55397176Sdes errx(1, "xswdev version mismatch"); 554115882Sphk if (xsw.xsw_dev == NODEV) 555115882Sphk snprintf(ksw.ksw_devname, sizeof ksw.ksw_devname, 556115882Sphk "<NFSfile>"); 557115882Sphk else 558115882Sphk snprintf(ksw.ksw_devname, sizeof ksw.ksw_devname, 559115882Sphk "/dev/%s", devname(xsw.xsw_dev, S_IFCHR)); 56097176Sdes ksw.ksw_used = xsw.xsw_used; 56197176Sdes ksw.ksw_total = xsw.xsw_nblks; 56297176Sdes ksw.ksw_flags = xsw.xsw_flags; 56397176Sdes print_swap(&ksw); 5641553Srgrimes } 56597176Sdes if (errno != ENOENT) 56697176Sdes err(1, "sysctl()"); 56797176Sdes print_swap_total(); 5681553Srgrimes} 56997176Sdes 57097176Sdesstatic void 57197176Sdesswapmode(void) 57297176Sdes{ 57397176Sdes if (kd != NULL) 57497176Sdes swapmode_kvm(); 57597176Sdes else 57697176Sdes swapmode_sysctl(); 57797176Sdes} 578