diff options
author | dillon <dillon@FreeBSD.org> | 1999-01-21 08:08:55 +0000 |
---|---|---|
committer | dillon <dillon@FreeBSD.org> | 1999-01-21 08:08:55 +0000 |
commit | b494d8d4c2cd331ee495202254ba602b9dde89ab (patch) | |
tree | 302555c2271b112e87ea4568aba6f8dd68db04a2 /usr.sbin/pstat/pstat.c | |
parent | e1a2cb0a3335c7dad1903a419a54ee2a21b1443f (diff) | |
download | FreeBSD-src-b494d8d4c2cd331ee495202254ba602b9dde89ab.zip FreeBSD-src-b494d8d4c2cd331ee495202254ba602b9dde89ab.tar.gz |
Update pstat -s to handle both old and new swapper.
Add pstat -ss to dump new swapper's radix tree.
Diffstat (limited to 'usr.sbin/pstat/pstat.c')
-rw-r--r-- | usr.sbin/pstat/pstat.c | 360 |
1 files changed, 285 insertions, 75 deletions
diff --git a/usr.sbin/pstat/pstat.c b/usr.sbin/pstat/pstat.c index 0cc4339..157068d 100644 --- a/usr.sbin/pstat/pstat.c +++ b/usr.sbin/pstat/pstat.c @@ -42,7 +42,7 @@ static const char copyright[] = static char sccsid[] = "@(#)pstat.c 8.16 (Berkeley) 5/9/95"; #endif static const char rcsid[] = - "$Id: pstat.c,v 1.36 1998/07/06 20:28:05 bde Exp $"; + "$Id: pstat.c,v 1.37 1998/08/19 01:32:28 bde Exp $"; #endif /* not lint */ #include <sys/param.h> @@ -68,6 +68,7 @@ static const char rcsid[] = #include <sys/tty.h> #include <sys/conf.h> #include <sys/rlist.h> +#include <sys/blist.h> #include <sys/user.h> #include <sys/sysctl.h> @@ -85,76 +86,77 @@ static const char rcsid[] = struct nlist nl[] = { #define VM_SWAPLIST 0 { "_swaplist" },/* list of free swap areas */ +#define NLMANDATORYBEG 1 #define VM_SWDEVT 1 { "_swdevt" }, /* list of swap devices and sizes */ -#define VM_NSWAP 2 - { "_nswap" }, /* size of largest swap device */ -#define VM_NSWDEV 3 +#define VM_NSWDEV 2 { "_nswdev" }, /* number of swap devices */ -#define VM_DMMAX 4 +#define VM_DMMAX 3 { "_dmmax" }, /* maximum size of a swap block */ -#define V_MOUNTLIST 5 +#define V_MOUNTLIST 4 { "_mountlist" }, /* address of head of mount list. */ -#define V_NUMV 6 +#define V_NUMV 5 { "_numvnodes" }, -#define FNL_NFILE 7 +#define FNL_NFILE 6 {"_nfiles"}, -#define FNL_MAXFILE 8 +#define FNL_MAXFILE 7 {"_maxfiles"}, -#define NLMANDATORY FNL_MAXFILE /* names up to here are mandatory */ -#define SCONS NLMANDATORY + 1 +#define NLMANDATORYEND FNL_MAXFILE /* names up to here are mandatory */ +#define SCONS NLMANDATORYEND + 1 { "_cons" }, -#define SPTY NLMANDATORY + 2 +#define SPTY NLMANDATORYEND + 2 { "_pt_tty" }, -#define SNPTY NLMANDATORY + 3 +#define SNPTY NLMANDATORYEND + 3 { "_npty" }, +#define VM_SWAPBLIST NLMANDATORYEND + 4 + { "_swapblist" }, #ifdef hp300 -#define SDCA (SNPTY+1) +#define SDCA (VM_SWAPBLIST+1) { "_dca_tty" }, -#define SNDCA (SNPTY+2) +#define SNDCA (VM_SWAPBLIST+2) { "_ndca" }, -#define SDCM (SNPTY+3) +#define SDCM (VM_SWAPBLIST+3) { "_dcm_tty" }, -#define SNDCM (SNPTY+4) +#define SNDCM (VM_SWAPBLIST+4) { "_ndcm" }, -#define SDCL (SNPTY+5) +#define SDCL (VM_SWAPBLIST+5) { "_dcl_tty" }, -#define SNDCL (SNPTY+6) +#define SNDCL (VM_SWAPBLIST+6) { "_ndcl" }, -#define SITE (SNPTY+7) +#define SITE (VM_SWAPBLIST+7) { "_ite_tty" }, -#define SNITE (SNPTY+8) +#define SNITE (VM_SWAPBLIST+8) { "_nite" }, #endif #ifdef mips -#define SDC (SNPTY+1) +#define SDC (VM_SWAPBLIST+1) { "_dc_tty" }, -#define SNDC (SNPTY+2) +#define SNDC (VM_SWAPBLIST+2) { "_dc_cnt" }, #endif #ifdef __FreeBSD__ -#define SCCONS (SNPTY+1) +#define SCCONS (VM_SWAPBLIST+1) { "_sccons" }, -#define NSCCONS (SNPTY+2) +#define NSCCONS (VM_SWAPBLIST+2) { "_nsccons" }, -#define SIO (SNPTY+3) +#define SIO (VM_SWAPBLIST+3) { "_sio_tty" }, -#define NSIO (SNPTY+4) +#define NSIO (VM_SWAPBLIST+4) { "_nsio_tty" }, -#define RC (SNPTY+5) +#define RC (VM_SWAPBLIST+5) { "_rc_tty" }, -#define NRC (SNPTY+6) +#define NRC (VM_SWAPBLIST+6) { "_nrc_tty" }, -#define CY (SNPTY+7) +#define CY (VM_SWAPBLIST+7) { "_cy_tty" }, -#define NCY (SNPTY+8) +#define NCY (VM_SWAPBLIST+8) { "_ncy_tty" }, -#define SI (SNPTY+9) +#define SI (VM_SWAPBLIST+9) { "_si_tty" }, -#define NSI (SNPTY+10) +#define NSI (VM_SWAPBLIST+10) { "_si_Nports" }, #endif { "" } @@ -162,6 +164,7 @@ struct nlist nl[] = { int usenumflag; int totalflag; +int swapflag; char *nlistf = NULL; char *memf = NULL; kvm_t *kd; @@ -212,6 +215,12 @@ struct { #define KGET2(addr, p, s, msg) \ if (kvm_read(kd, (u_long)(addr), p, s) != s) \ warnx("cannot read %s: %s", msg, kvm_geterr(kd)) +#define KGETN(idx, var) \ + KGET1N(idx, &var, sizeof(var), SVAR(var)) +#define KGET1N(idx, p, s, msg) \ + KGET2N(nl[idx].n_value, p, s, msg) +#define KGET2N(addr, p, s, msg) \ + ((kvm_read(kd, (u_long)(addr), p, s) == s) ? 1 : 0) #define KGETRET(addr, p, s, msg) \ if (kvm_read(kd, (u_long)(addr), p, s) != s) { \ warnx("cannot read %s: %s", msg, kvm_geterr(kd)); \ @@ -248,7 +257,7 @@ main(argc, argv) char *argv[]; { int ch, i, quit, ret; - int fileflag, swapflag, ttyflag, vnodeflag; + int fileflag, ttyflag, vnodeflag; char buf[_POSIX2_LINE_MAX],*opts; fileflag = swapflag = ttyflag = vnodeflag = 0; @@ -286,7 +295,7 @@ main(argc, argv) usenumflag = 1; break; case 's': - swapflag = 1; + ++swapflag; break; case 'T': totalflag = 1; @@ -320,7 +329,7 @@ main(argc, argv) if ((ret = kvm_nlist(kd, nl)) != 0) { if (ret == -1) errx(1, "kvm_nlist: %s", kvm_geterr(kd)); - for (i = quit = 0; i <= NLMANDATORY; i++) + for (i = NLMANDATORYBEG, quit = 0; i <= NLMANDATORYEND; i++) if (!nl[i].n_value) { quit = 1; warnx("undefined symbol: %s", nl[i].n_name); @@ -1026,26 +1035,190 @@ getfiles(abuf, alen) } /* + * scanradix() - used by swapmode() to scan the swap device's new style + * radix tree + */ + +#define TABME tab, tab, "" + +int +scanradix( + blmeta_t *scan, + daddr_t blk, + daddr_t radix, + daddr_t skip, + daddr_t count, + int dmmax, + int nswdev, + long *perdev, + int tab +) { + blmeta_t meta; + + KGET2(scan, &meta, sizeof(meta), "blmeta_t"); + + /* + * Terminator + */ + if (meta.bm_bighint == (daddr_t)-1) { + if (swapflag > 1) { + printf("%*.*s(0x%06x,%d) Terminator\n", + TABME, + blk, + radix + ); + } + return(-1); + } + + if (radix == BLIST_BMAP_RADIX) { + /* + * Leaf bitmap + */ + int i; + + if (swapflag > 1) { + printf("%*.*s(0x%06x,%d) Bitmap %08x big=%d\n", + TABME, + blk, + radix, + (int)meta.u.bmu_bitmap, + meta.bm_bighint + ); + } + + /* + * If not all allocated, count. + */ + if (meta.u.bmu_bitmap != 0) { + for (i = 0; i < BLIST_BMAP_RADIX && i < count; ++i) { + /* + * A 0 bit means allocated + */ + if ((meta.u.bmu_bitmap & (1 << i))) { + int t = 0; + + if (nswdev) + t = (blk + i) / dmmax % nswdev; + ++perdev[t]; + } + } + } + } else if (meta.u.bmu_avail == radix) { + /* + * Meta node if all free + */ + if (swapflag > 1) { + printf("%*.*s(0x%06x,%d) Submap ALL-FREE {\n", + TABME, + blk, + radix, + (int)meta.u.bmu_avail, + meta.bm_bighint + ); + } + /* + * Note: both dmmax and radix are powers of 2. However, dmmax + * may be larger then radix so use a smaller increment if + * necessary. + */ + { + int t; + int tinc = dmmax; + + while (tinc > radix) + tinc >>= 1; + + for (t = blk; t < blk + radix; t += tinc) { + if (nswdev) + perdev[0] += tinc; + else + perdev[t / dmmax % nswdev] += tinc; + } + } + } else if (meta.u.bmu_avail == 0) { + /* + * Meta node if all used + */ + if (swapflag > 1) { + printf("%*.*s(0x%06x,%d) Submap ALL-ALLOCATED\n", + TABME, + blk, + radix, + (int)meta.u.bmu_avail, + meta.bm_bighint + ); + } + } else { + /* + * Meta node if not all free + */ + int i; + int next_skip; + + radix >>= BLIST_META_RADIX_SHIFT; + next_skip = skip >> BLIST_META_RADIX_SHIFT; + + if (swapflag > 1) { + printf("%*.*s(0x%06x,%d) Submap avail=%d big=%d {\n", + TABME, + blk, + radix, + (int)meta.u.bmu_avail, + meta.bm_bighint + ); + } + + for (i = 1; i <= skip; i += next_skip) { + int r; + daddr_t vcount = (count > radix) ? radix : count; + + r = scanradix( + &scan[i], + blk, + radix, + next_skip - 1, + vcount, + dmmax, + nswdev, + perdev, + tab + 4 + ); + if (r < 0) + break; + blk += radix; + } + if (swapflag > 1) { + printf("%*.*s}\n", TABME); + } + } + return(0); +} + + +/* * swapmode is based on a program called swapinfo written * by Kevin Lahey <kml@rokkaku.atl.ga.us>. */ void -swapmode() +swapmode(void) { char *header, *p; - int hlen, nswap, nswdev, dmmax; - int i, div, avail, nfree, npfree, used; + int hlen, nswdev, dmmax; + int i, div, mul, avail, nfree, npfree, used; struct swdevt *sw; long blocksize, *perdev; struct rlist head; struct rlisthdr swaplist; - struct rlist *swapptr; + struct blist *swapblist = NULL; u_long ptr; - KGET(VM_NSWAP, nswap); KGET(VM_NSWDEV, nswdev); - KGET(VM_DMMAX, dmmax); - KGET1(VM_SWAPLIST, &swaplist, sizeof swaplist, "swaplist"); + KGET(VM_DMMAX, dmmax); /* PAGE_BSIZE'd or PAGE_SIZE'd depending */ + if (!KGET1N(VM_SWAPLIST, &swaplist, sizeof swaplist, "swaplist")) { + KGET1(VM_SWAPBLIST, &swapblist, sizeof swapblist, "swapblist"); + } + if ((sw = malloc(nswdev * sizeof(*sw))) == NULL || (perdev = malloc(nswdev * sizeof(*perdev))) == NULL) errx(1, "malloc"); @@ -1055,39 +1228,63 @@ swapmode() /* Count up swap space. */ nfree = 0; memset(perdev, 0, nswdev * sizeof(*perdev)); - swapptr = swaplist.rlh_list; - while (swapptr) { - int top, bottom, next_block; - KGET2(swapptr, &head, sizeof(struct rlist), "swapptr"); + if (swapblist) { + /* + * New swap radix tree (ugh!) + */ + struct blist blcopy = { 0 }; + KGET2(swapblist, &blcopy, sizeof(blcopy), "*swapblist"); + if (swapflag > 1) { + printf("radix tree: %d/%d/%d blocks, %dK wired\n", + blcopy.bl_free, + blcopy.bl_blocks, + blcopy.bl_radix, + (blcopy.bl_rootblks * sizeof(blmeta_t) + 1023)/ + 1024 + ); + } + scanradix(blcopy.bl_root, 0, blcopy.bl_radix, blcopy.bl_skip, blcopy.bl_rootblks, dmmax, nswdev, perdev, 0); + } else { + /* + * Old swap + */ + struct rlist *swapptr; - top = head.rl_end; - bottom = head.rl_start; + swapptr = swaplist.rlh_list; + while (swapptr) { + int top, bottom, next_block; - nfree += top - bottom + 1; + KGET2(swapptr, &head, sizeof(struct rlist), "swapptr"); - /* - * Swap space is split up among the configured disks. - * - * For interleaved swap devices, the first dmmax blocks - * of swap space some from the first disk, the next dmmax - * blocks from the next, and so on up to nswap blocks. - * - * The list of free space joins adjacent free blocks, - * ignoring device boundries. If we want to keep track - * of this information per device, we'll just have to - * extract it ourselves. - */ - while (top / dmmax != bottom / dmmax) { - next_block = ((bottom + dmmax) / dmmax); + top = head.rl_end; + bottom = head.rl_start; + + nfree += top - bottom + 1; + + /* + * Swap space is split up among the configured disks. + * + * For interleaved swap devices, the first dmmax blocks + * of swap space some from the first disk, the next + * dmmax blocks from the next, and so. + * + * The list of free space joins adjacent free blocks, + * ignoring device boundries. If we want to keep track + * of this information per device, we'll just have to + * extract it ourselves. + */ + while (top / dmmax != bottom / dmmax) { + next_block = ((bottom + dmmax) / dmmax); + perdev[(bottom / dmmax) % nswdev] += + next_block * dmmax - bottom; + bottom = next_block * dmmax; + } perdev[(bottom / dmmax) % nswdev] += - next_block * dmmax - bottom; - bottom = next_block * dmmax; - } - perdev[(bottom / dmmax) % nswdev] += - top - bottom + 1; + top - bottom + 1; - swapptr = head.rl_next; + swapptr = head.rl_next; + } } header = getbsize(&hlen, &blocksize); @@ -1095,7 +1292,20 @@ swapmode() (void)printf("%-11s %*s %8s %8s %8s %s\n", "Device", hlen, header, "Used", "Avail", "Capacity", "Type"); - div = blocksize / 512; + + mul = 1; + if (swapblist) { + if ((div = blocksize / PAGE_SIZE) == 0) { + mul = PAGE_SIZE / blocksize; + div = 1; + } + } else { + if ((div = blocksize / DEV_BSIZE) == 0) { + mul = DEV_BSIZE / blocksize; + div = 1; + } + } + avail = npfree = 0; for (i = 0; i < nswdev; i++) { int xsize, xfree; @@ -1112,10 +1322,10 @@ swapmode() p = devname(sw[i].sw_dev, S_IFBLK); (void)printf("/dev/%-6s %*d ", p == NULL ? "??" : p, - hlen, sw[i].sw_nblks / div); + hlen, sw[i].sw_nblks * mul / div); } else (void)printf("[NFS swap] %*d ", - hlen, sw[i].sw_nblks / div); + hlen, sw[i].sw_nblks * mul / div); /* The first dmmax is never allocated to avoid trashing of * disklabels @@ -1128,7 +1338,7 @@ swapmode() if (totalflag) continue; (void)printf("%8d %8d %5.0f%% %s\n", - used / div, xfree / div, + used * mul / div, xfree * mul / div, (double)used / (double)xsize * 100.0, (sw[i].sw_flags & SW_SEQUENTIAL) ? "Sequential" : "Interleaved"); @@ -1147,7 +1357,7 @@ swapmode() } if (npfree > 1) { (void)printf("%-11s %*d %8d %8d %5.0f%%\n", - "Total", hlen, avail / div, used / div, nfree / div, + "Total", hlen, avail * mul / div, used * mul / div, nfree * mul / div, (double)used / (double)avail * 100.0); } } |