summaryrefslogtreecommitdiffstats
path: root/usr.sbin/pstat/pstat.c
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>1999-01-21 08:08:55 +0000
committerdillon <dillon@FreeBSD.org>1999-01-21 08:08:55 +0000
commitb494d8d4c2cd331ee495202254ba602b9dde89ab (patch)
tree302555c2271b112e87ea4568aba6f8dd68db04a2 /usr.sbin/pstat/pstat.c
parente1a2cb0a3335c7dad1903a419a54ee2a21b1443f (diff)
downloadFreeBSD-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.c360
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);
}
}
OpenPOWER on IntegriCloud