X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/cea9ae1e9d6ed20892cd3ab1e80720d6eb0a47c8..0dc27808f14f3b6d4ad456d2063601b17a60a98d:/usr/src/usr.sbin/pstat/pstat.c diff --git a/usr/src/usr.sbin/pstat/pstat.c b/usr/src/usr.sbin/pstat/pstat.c index 07f07aba72..b784c59106 100644 --- a/usr/src/usr.sbin/pstat/pstat.c +++ b/usr/src/usr.sbin/pstat/pstat.c @@ -1,31 +1,48 @@ -static char *sccsid = "@(#)pstat.c 4.7 (Berkeley) %G%"; /* - * Print system stuff + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. */ -#define mask(x) (x&0377) -#define clear(x) ((int)x&0x7fffffff) +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)pstat.c 5.17 (Berkeley) %G%"; +#endif /* not lint */ + +/* + * Print system stuff + */ #include #include +#define KERNEL #include +#undef KERNEL #include #include #include #include #include +#include #include #include #include #include -#include -#define KERNEL -#include -#undef KERNEL +#include +#include + +#define mask(x) (x&0377) +#define clear(x) ((int)x &~ KERNBASE) char *fcore = "/dev/kmem"; +char *fmem = "/dev/mem"; char *fnlist = "/vmunix"; -int fc; +int fc, fm; struct nlist nl[] = { #define SINODE 0 @@ -34,43 +51,73 @@ struct nlist nl[] = { { "_text" }, #define SPROC 2 { "_proc" }, -#define SDZ 3 - { "_dz_tty" }, -#define SNDZ 4 - { "_dz_cnt" }, -#define SKL 5 +#define SCONS 3 { "_cons" }, -#define SFIL 6 +#define SFIL 4 { "_file" }, -#define USRPTMA 7 +#define USRPTMA 5 { "_Usrptmap" }, -#define USRPT 8 +#define USRPT 6 { "_usrpt" }, -#define SNSWAP 9 - { "_nswap" }, -#define SWAPMAP 10 +#define SWAPMAP 7 { "_swapmap" }, -#define SDH 11 - { "_dh11" }, -#define SNDH 12 - { "_ndh11" }, -#define SGROUP 13 - { "_groups" }, -#define SCHANS 14 - { "_chans" }, -#define SSCHANS 15 - { "_schans" }, -#define SNPROC 16 +#define SNPROC 8 { "_nproc" }, -#define SNTEXT 17 +#define SNTEXT 9 { "_ntext" }, -#define SNFILE 18 +#define SNFILE 10 { "_nfile" }, -#define SNINODE 19 +#define SNINODE 11 { "_ninode" }, -#define SNSWAPMAP 20 +#define SNSWAPMAP 12 { "_nswapmap" }, - 0, +#define SPTY 13 + { "_pt_tty" }, +#define SDMMIN 14 + { "_dmmin" }, +#define SDMMAX 15 + { "_dmmax" }, +#define SNSWDEV 16 + { "_nswdev" }, +#define SSWDEVT 17 + { "_swdevt" }, +#define SYSMAP 18 + { "_Sysmap" }, +#define SNPTY 19 + { "_npty" }, +#ifdef vax +#define SDZ (SNPTY+1) + { "_dz_tty" }, +#define SNDZ (SNPTY+2) + { "_dz_cnt" }, +#define SDMF (SNPTY+3) + { "_dmf_tty" }, +#define SNDMF (SNPTY+4) + { "_ndmf" }, +#define SDH (SNPTY+5) + { "_dh11" }, +#define SNDH (SNPTY+6) + { "_ndh11" }, +#define SDHU (SNPTY+7) + { "_dhu_tty" }, +#define SNDHU (SNPTY+8) + { "_ndhu" }, +#define SDMZ (SNPTY+9) + { "_dmz_tty" }, +#define SNDMZ (SNPTY+10) + { "_ndmz" }, +#define SQD (SNPTY+11) + { "_qd_tty" }, +#define SNQD (SNPTY+12) + { "_nNQD" }, +#endif +#ifdef tahoe +#define SVX (SNPTY+1) + { "_vx_tty" }, +#define SNVX (SNPTY+2) + { "_nvx" }, +#endif + { "" } }; int inof; @@ -78,8 +125,6 @@ int txtf; int prcf; int ttyf; int usrf; -int mpxf; -int groupf; long ubase; int filf; int swpf; @@ -91,84 +136,82 @@ int allflg; int kflg; struct pte *Usrptma; struct pte *usrpt; +u_long getword(); +off_t mkphys(); main(argc, argv) -char **argv; + int argc; + char **argv; { - register char *argp; - - argc--, argv++; - while (argc > 0 && **argv == '-') { - argp = *argv++; - argp++; - argc--; - while (*argp++) - switch (argp[-1]) { + extern char *optarg; + extern int optind; + int ch; + while ((ch = getopt(argc, argv, "Tafikptu:sx")) != EOF) + switch((char)ch) { case 'T': totflg++; break; - case 'a': allflg++; + /*FALLTHROUGH*/ + case 'p': + prcf++; + break; + case 'f': + filf++; break; - case 'i': inof++; break; - - case 'k': + case 'k': /* undocumented */ kflg++; - fcore = "/vmcore"; - break; - - case 'x': - txtf++; - break; - - case 'p': - prcf++; + fcore = fmem = "/vmcore"; break; - case 't': ttyf++; break; - case 'u': - if (argc == 0) - break; - argc--; usrf++; - sscanf( *argv++, "%x", &ubase); - break; - - case 'f': - filf++; + sscanf(optarg, "%x", &ubase); break; case 's': swpf++; break; - case 'm': - mpxf++; - break; - case 'g': - groupf++; + case 'x': + txtf++; break; + case '?': + default: + printf("usage: pstat -[Tafiptsx] [-u [ubase]] [system] [core]\n"); + exit(1); } + argc -= optind; + argv += optind; + + if (argc>1) { + fcore = fmem = argv[1]; + kflg++; } - if (argc>0) - fcore = argv[0]; - if ((fc = open(fcore, 0)) < 0) { - printf("Can't find %s\n", fcore); + if ((fc = open(fcore, O_RDONLY, 0)) < 0) { + perror(fcore); exit(1); } - if (argc>1) - fnlist = argv[1]; + if ((fm = open(fmem, O_RDONLY, 0)) < 0) { + perror(fmem); + exit(1); + } + if (argc>0) + fnlist = argv[0]; nlist(fnlist, nl); + if (nl[0].n_type == 0) { + printf("pstat: no namelist.\n"); + exit(1); + } usrpt = (struct pte *)nl[USRPT].n_value; Usrptma = (struct pte *)nl[USRPTMA].n_value; - if (nl[0].n_type == 0) { - printf("no namelist\n"); + if (!(filf | totflg | inof | prcf | txtf | ttyf | usrf | swpf)) { + printf("pstat: one or more of -[aixptfsu] is required\n"); exit(1); } if (filf||totflg) @@ -185,10 +228,6 @@ char **argv; dousr(); if (swpf||totflg) doswap(); - if (mpxf) - dompx(); - if (groupf) - dogroup(); } doinode() @@ -199,9 +238,19 @@ doinode() int ninode; nin = 0; - ninode = getw(nl[SNINODE].n_value); + ninode = getword(nl[SNINODE].n_value); xinode = (struct inode *)calloc(ninode, sizeof (struct inode)); - lseek(fc, (int)(ainode = (struct inode *)getw(nl[SINODE].n_value)), 0); + ainode = (struct inode *)getword(nl[SINODE].n_value); + if (ninode < 0 || ninode > 10000) { + fprintf(stderr, "number of inodes is preposterous (%d)\n", + ninode); + return; + } + if (xinode == NULL) { + fprintf(stderr, "can't allocate memory for inode table\n"); + return; + } + lseek(fc, mkphys((off_t)ainode), 0); read(fc, xinode, ninode * sizeof(struct inode)); for (ip = xinode; ip < &xinode[ninode]; ip++) if (ip->i_count) @@ -211,25 +260,31 @@ doinode() return; } printf("%d/%d active inodes\n", nin, ninode); - printf(" LOC FLAGS CNT DEVICE INO MODE NLK UID SIZE/DEV\n"); +printf(" LOC FLAGS CNT DEVICE RDC WRC INO MODE NLK UID SIZE/DEV\n"); for (ip = xinode; ip < &xinode[ninode]; ip++) { if (ip->i_count == 0) continue; printf("%8.1x ", ainode + (ip - xinode)); - putf(ip->i_flag&ILOCK, 'L'); + putf(ip->i_flag&ILOCKED, 'L'); putf(ip->i_flag&IUPD, 'U'); putf(ip->i_flag&IACC, 'A'); putf(ip->i_flag&IMOUNT, 'M'); putf(ip->i_flag&IWANT, 'W'); putf(ip->i_flag&ITEXT, 'T'); + putf(ip->i_flag&ICHG, 'C'); + putf(ip->i_flag&ISHLOCK, 'S'); + putf(ip->i_flag&IEXLOCK, 'E'); + putf(ip->i_flag&ILWAIT, 'Z'); printf("%4d", ip->i_count&0377); printf("%4d,%3d", major(ip->i_dev), minor(ip->i_dev)); + printf("%4d", ip->i_shlockc&0377); + printf("%4d", ip->i_exlockc&0377); printf("%6d", ip->i_number); printf("%6x", ip->i_mode & 0xffff); printf("%4d", ip->i_nlink); printf("%4d", ip->i_uid); if ((ip->i_mode&IFMT)==IFBLK || (ip->i_mode&IFMT)==IFCHR) - printf("%6d,%3d", major(ip->i_un.i_rdev), minor(ip->i_un.i_rdev)); + printf("%6d,%3d", major(ip->i_rdev), minor(ip->i_rdev)); else printf("%10ld", ip->i_size); printf("\n"); @@ -237,13 +292,14 @@ doinode() free(xinode); } -getw(loc) +u_long +getword(loc) off_t loc; { - int word; + u_long word; if (kflg) - loc &= 0x7fffffff; + loc = clear(loc); lseek(fc, loc, 0); read(fc, &word, sizeof (word)); return (word); @@ -262,22 +318,36 @@ dotext() register struct text *xp; int ntext; struct text *xtext, *atext; - int ntx; + int ntx, ntxca; - ntx = 0; - ntext = getw(nl[SNTEXT].n_value); + ntx = ntxca = 0; + ntext = getword(nl[SNTEXT].n_value); xtext = (struct text *)calloc(ntext, sizeof (struct text)); - lseek(fc, (int)(atext = (struct text *)getw(nl[STEXT].n_value)), 0); + atext = (struct text *)getword(nl[STEXT].n_value); + if (ntext < 0 || ntext > 10000) { + fprintf(stderr, "number of texts is preposterous (%d)\n", + ntext); + return; + } + if (xtext == NULL) { + fprintf(stderr, "can't allocate memory for text table\n"); + return; + } + lseek(fc, mkphys((off_t)atext), 0); read(fc, xtext, ntext * sizeof (struct text)); - for (xp = xtext; xp < &xtext[ntext]; xp++) - if (xp->x_iptr!=NULL) + for (xp = xtext; xp < &xtext[ntext]; xp++) { + if (xp->x_iptr != NULL) + ntxca++; + if (xp->x_count != 0) ntx++; + } if (totflg) { - printf("%3d/%3d texts\n", ntx, ntext); + printf("%3d/%3d texts active, %3d used\n", ntx, ntext, ntxca); return; } - printf("%d/%d active texts\n", ntx, ntext); - printf(" LOC FLAGS DADDR CADDR RSS SIZE IPTR CNT CCNT\n"); + printf("%d/%d active texts, %d used\n", ntx, ntext, ntxca); + printf("\ + LOC FLAGS DADDR CADDR RSS SIZE IPTR CNT CCNT FORW BACK\n"); for (xp = xtext; xp < &xtext[ntext]; xp++) { if (xp->x_iptr == NULL) continue; @@ -290,12 +360,14 @@ dotext() putf(xp->x_flag&XLOCK, 'K'); putf(xp->x_flag&XWANT, 'w'); printf("%5x", xp->x_daddr[0]); - printf("%11x", xp->x_caddr); + printf("%10x", xp->x_caddr); printf("%5d", xp->x_rssize); printf("%5d", xp->x_size); printf("%10.1x", xp->x_iptr); printf("%5d", xp->x_count&0377); printf("%5d", xp->x_ccount); + printf("%10x", xp->x_forw); + printf("%9x", xp->x_back); printf("\n"); } free(xtext); @@ -309,9 +381,19 @@ doproc() register loc, np; struct pte apte; - nproc = getw(nl[SNPROC].n_value); + nproc = getword(nl[SNPROC].n_value); xproc = (struct proc *)calloc(nproc, sizeof (struct proc)); - lseek(fc, (int)(aproc = (struct proc *)getw(nl[SPROC].n_value)), 0); + aproc = (struct proc *)getword(nl[SPROC].n_value); + if (nproc < 0 || nproc > 10000) { + fprintf(stderr, "number of procs is preposterous (%d)\n", + nproc); + return; + } + if (xproc == NULL) { + fprintf(stderr, "can't allocate memory for proc table\n"); + return; + } + lseek(fc, mkphys((off_t)aproc), 0); read(fc, xproc, nproc * sizeof (struct proc)); np = 0; for (pp=xproc; pp < &xproc[nproc]; pp++) @@ -322,7 +404,7 @@ doproc() return; } printf("%d/%d processes\n", np, nproc); - printf(" LOC S F POIP PRI SIG UID SLP TIM CPU NI PGRP PID PPID ADDR RSS SRSS SIZE WCHAN LINK TEXTP CLKT\n"); + printf(" LOC S F POIP PRI SIG UID SLP TIM CPU NI PGRP PID PPID ADDR RSS SRSS SIZE WCHAN LINK TEXTP\n"); for (pp=xproc; pp<&xproc[nproc]; pp++) { if (pp->p_stat==0 && allflg==0) continue; @@ -342,52 +424,118 @@ doproc() printf(" %6d", pp->p_ppid); if (kflg) pp->p_addr = (struct pte *)clear((int)pp->p_addr); - lseek(fc, (long)(Usrptma+btokmx(pp->p_addr)), 0); - read(fc, &apte, sizeof(apte)); - printf(" %8x", ctob(apte.pg_pfnum+1) - sizeof(struct pte) * UPAGES); + if (pp->p_flag & SLOAD) { + lseek(fc, (long)pp->p_addr, 0); + read(fc, &apte, sizeof(apte)); + printf(" %8x", apte.pg_pfnum); + } else + printf(" %8x", pp->p_swaddr); printf(" %4x", pp->p_rssize); printf(" %4x", pp->p_swrss); printf(" %5x", pp->p_dsize+pp->p_ssize); printf(" %7x", clear(pp->p_wchan)); printf(" %7x", clear(pp->p_link)); printf(" %7x", clear(pp->p_textp)); - printf(" %u", pp->p_clktim); printf("\n"); } + free(xproc); } +static char mesg[] = +" # RAW CAN OUT MODE ADDR DEL COL STATE PGRP DISC\n"; +static int ttyspace = 128; +static struct tty *tty; + dotty() { - struct tty dz_tty[64]; - int ndz; - register struct tty *tp; - register char *mesg; + extern char *malloc(); + if ((tty = (struct tty *)malloc(ttyspace * sizeof(*tty))) == 0) { + printf("pstat: out of memory\n"); + return; + } printf("1 cons\n"); - lseek(fc, (long)nl[SKL].n_value, 0); - read(fc, dz_tty, sizeof(dz_tty[0])); - mesg = " # RAW CAN OUT MODE ADDR DEL COL STATE PGRP DISC\n"; + if (kflg) + nl[SCONS].n_value = clear(nl[SCONS].n_value); + lseek(fc, (long)nl[SCONS].n_value, 0); + read(fc, tty, sizeof(*tty)); printf(mesg); - ttyprt(&dz_tty[0], 0); - if (nl[SNDZ].n_type == 0) - goto dh; - lseek(fc, (long)nl[SNDZ].n_value, 0); - read(fc, &ndz, sizeof(ndz)); - printf("%d dz lines\n", ndz); - lseek(fc, (long)nl[SDZ].n_value, 0); - read(fc, dz_tty, sizeof(dz_tty)); - for (tp = dz_tty; tp < &dz_tty[ndz]; tp++) - ttyprt(tp, tp - dz_tty); -dh: - if (nl[SNDH].n_type == 0) + ttyprt(&tty[0], 0); +#ifdef vax + if (nl[SNQD].n_type != 0) + doqdss(); + if (nl[SNDZ].n_type != 0) + dottytype("dz", SDZ, SNDZ); + if (nl[SNDH].n_type != 0) + dottytype("dh", SDH, SNDH); + if (nl[SNDMF].n_type != 0) + dottytype("dmf", SDMF, SNDMF); + if (nl[SNDHU].n_type != 0) + dottytype("dhu", SDHU, SNDHU); + if (nl[SNDMZ].n_type != 0) + dottytype("dmz", SDMZ, SNDMZ); +#endif +#ifdef tahoe + if (nl[SNVX].n_type != 0) + dottytype("vx", SVX, SNVX); +#endif + if (nl[SNPTY].n_type != 0) + dottytype("pty", SPTY, SNPTY); +} + +/* + * Special case the qdss because there are 4 tty structs per qdss + * and only the first of each is used as a tty. + */ +#ifdef vax +doqdss() +{ + int nqd; + register struct tty *tp; + + if (kflg) { + nl[SNQD].n_value = clear(nl[SNQD].n_value); + nl[SQD].n_value = clear(nl[SQD].n_value); + } + lseek(fc, (long)nl[SNQD].n_value, 0); + read(fc, &nqd, sizeof(nqd)); + printf("%d qd\n", nqd); + lseek(fc, (long)nl[SQD].n_value, 0); + read(fc, tty, nqd * sizeof(struct tty) * 4); + printf(mesg); + for (tp = tty; tp < &tty[nqd * 4]; tp += 4) + ttyprt(tp, tp - tty); +} +#endif + +dottytype(name, type, number) +char *name; +{ + int ntty; + register struct tty *tp; + extern char *realloc(); + + if (tty == (struct tty *)0) return; - lseek(fc, (long)nl[SNDH].n_value, 0); - read(fc, &ndz, sizeof(ndz)); - printf("%d dh lines\n", ndz); - lseek(fc, (long)nl[SDH].n_value, 0); - read(fc, dz_tty, sizeof(dz_tty)); - for (tp = dz_tty; tp < &dz_tty[ndz]; tp++) - ttyprt(tp, tp - dz_tty); + if (kflg) { + nl[number].n_value = clear(nl[number].n_value); + nl[type].n_value = clear(nl[type].n_value); + } + lseek(fc, (long)nl[number].n_value, 0); + read(fc, &ntty, sizeof(ntty)); + printf("%d %s lines\n", ntty, name); + if (ntty > ttyspace) { + ttyspace = ntty; + if ((tty = (struct tty *)realloc(tty, ttyspace * sizeof(*tty))) == 0) { + printf("pstat: out of memory\n"); + return; + } + } + lseek(fc, (long)nl[type].n_value, 0); + read(fc, tty, ntty * sizeof(struct tty)); + printf(mesg); + for (tp = tty; tp < &tty[ntty]; tp++) + ttyprt(tp, tp - tty); } ttyprt(atp, line) @@ -399,54 +547,67 @@ struct tty *atp; tp = atp; switch (tp->t_line) { +#ifdef notdef case NETLDISC: if (tp->t_rec) printf("%4d%4d", 0, tp->t_inbuf); else printf("%4d%4d", tp->t_inbuf, 0); break; +#endif default: - printf("%4d", tp->t_rawq.c_cc); - printf("%4d", tp->t_canq.c_cc); - } - printf("%4d", tp->t_outq.c_cc); - printf("%8.1o", tp->t_flags); - printf(" %8.1x", tp->t_addr); - printf("%3d", tp->t_delct); - printf("%4d ", tp->t_col); - putf(tp->t_state&TIMEOUT, 'T'); - putf(tp->t_state&WOPEN, 'W'); - putf(tp->t_state&ISOPEN, 'O'); - putf(tp->t_state&CARR_ON, 'C'); - putf(tp->t_state&BUSY, 'B'); - putf(tp->t_state&ASLEEP, 'A'); - putf(tp->t_state&XCLUDE, 'X'); -/* - putf(tp->t_state&HUPCLS, 'H'); - */ + printf("%4d%4d", tp->t_rawq.c_cc, tp->t_canq.c_cc); + } + printf("%4d %8x %8x%4d%4d", tp->t_outq.c_cc, tp->t_flags, + tp->t_addr, tp->t_delct, tp->t_col); + putf(tp->t_state&TS_TIMEOUT, 'T'); + putf(tp->t_state&TS_WOPEN, 'W'); + putf(tp->t_state&TS_ISOPEN, 'O'); + putf(tp->t_state&TS_FLUSH, 'F'); + putf(tp->t_state&TS_CARR_ON, 'C'); + putf(tp->t_state&TS_BUSY, 'B'); + putf(tp->t_state&TS_ASLEEP, 'A'); + putf(tp->t_state&TS_XCLUDE, 'X'); + putf(tp->t_state&TS_TTSTOP, 'S'); + putf(tp->t_state&TS_HUPCLS, 'H'); printf("%6d", tp->t_pgrp); switch (tp->t_line) { + case OTTYDISC: + printf("\n"); + break; + case NTTYDISC: - printf(" ntty"); + printf(" ntty\n"); break; case NETLDISC: - printf(" net"); + printf(" berknet\n"); + break; + + case TABLDISC: + printf(" tab\n"); + break; + + case SLIPDISC: + printf(" slip\n"); break; + + default: + printf(" %d\n", tp->t_line); } - printf("\n"); } dousr() { struct user U; register i, j, *ip; + register struct nameidata *nd = &U.u_nd; - /* This wins only if PAGSIZ > sizeof (struct user) */ - lseek(fc, ubase * NBPG, 0); - read(fc, &U, sizeof(U)); + /* This wins only if CLBYTES >= sizeof (struct user) */ + lseek(fm, ubase * NBPG, 0); + read(fm, &U, sizeof(U)); printf("pcb"); ip = (int *)&U.u_pcb; while (ip < &U.u_arg[0]) { @@ -458,89 +619,90 @@ dousr() } if ((ip - (int *)&U.u_pcb) % 4 != 0) printf("\n"); - printf("arg\t"); - for (i=0; i<5; i++) - printf(" %.1x", U.u_arg[i]); - printf("\n"); - for (i=0; ini_segflg, U.u_error); printf("uids\t%d,%d,%d,%d\n", U.u_uid,U.u_gid,U.u_ruid,U.u_rgid); printf("procp\t%.1x\n", U.u_procp); printf("ap\t%.1x\n", U.u_ap); printf("r_val?\t%.1x %.1x\n", U.u_r.r_val1, U.u_r.r_val2); - printf("base, count, offset %.1x %.1x %ld\n", U.u_base, - U.u_count, U.u_offset); + printf("base, count, offset %.1x %.1x %ld\n", nd->ni_base, + nd->ni_count, nd->ni_offset); printf("cdir rdir %.1x %.1x\n", U.u_cdir, U.u_rdir); - printf("dbuf %.14s\n", U.u_dbuf); - printf("dirp %.1x\n", U.u_dirp); - printf("dent %d %.14s\n", U.u_dent.d_ino, U.u_dent.d_name); - printf("pdir %.1o\n", U.u_pdir); - printf("file\t"); - for (i=0; i<10; i++) - printf("%9.1x", U.u_ofile[i]); - printf("\n\t"); - for (i=10; ini_dirp); + printf("dent %d %.14s\n", nd->ni_dent.d_ino, nd->ni_dent.d_name); + printf("pdir %.1o\n", nd->ni_pdir); + printf("file"); + for (i=0; i 10000) { + fprintf(stderr, "number of files is preposterous (%d)\n", + nfile); + return; + } + if (xfile == NULL) { + fprintf(stderr, "can't allocate memory for file table\n"); + return; + } + lseek(fc, mkphys((off_t)afile), 0); read(fc, xfile, nfile * sizeof (struct file)); for (fp=xfile; fp < &xfile[nfile]; fp++) if (fp->f_count) @@ -585,20 +758,34 @@ dofile() return; } printf("%d/%d open files\n", nf, nfile); - printf(" LOC FLG CNT INO OFFS\n"); - for (fp=xfile,loc=nl[SFIL].n_value; fp < &xfile[nfile]; fp++,loc+=sizeof(xfile[0])) { + printf(" LOC TYPE FLG CNT MSG DATA OFFSET\n"); + for (fp=xfile,loc=(int)afile; fp < &xfile[nfile]; fp++,loc+=sizeof(xfile[0])) { if (fp->f_count==0) continue; printf("%8x ", loc); + if (fp->f_type <= DTYPE_SOCKET) + printf("%-8.8s", dtypes[fp->f_type]); + else + printf("%8d", fp->f_type); putf(fp->f_flag&FREAD, 'R'); putf(fp->f_flag&FWRITE, 'W'); - putf(fp->f_flag&FPIPE, 'P'); - printf("%4d", mask(fp->f_count)); - printf("%9.1x", fp->f_inode); - printf(" %ld\n", fp->f_un.f_offset); + putf(fp->f_flag&FAPPEND, 'A'); + putf(fp->f_flag&FSHLOCK, 'S'); + putf(fp->f_flag&FEXLOCK, 'X'); + putf(fp->f_flag&FASYNC, 'I'); + printf(" %3d", mask(fp->f_count)); + printf(" %3d", mask(fp->f_msgcount)); + printf(" %8.1x", fp->f_data); + if (fp->f_offset < 0) + printf(" %x\n", fp->f_offset); + else + printf(" %ld\n", fp->f_offset); } + free(xfile); } +int dmmin, dmmax, nswdev; + doswap() { struct proc *proc; @@ -607,49 +794,109 @@ doswap() int ntext; struct map *swapmap; int nswapmap; + struct swdevt *swdevt, *sw; register struct proc *pp; - int nswap, used, tused, free; + int nswap, used, tused, free, waste; + int db, sb; register struct mapent *me; register struct text *xp; + int i, j; + long rmalloc(); - nproc = getw(nl[SNPROC].n_value); + nproc = getword(nl[SNPROC].n_value); + ntext = getword(nl[SNTEXT].n_value); + if (nproc < 0 || nproc > 10000 || ntext < 0 || ntext > 10000) { + fprintf(stderr, "number of procs/texts is preposterous (%d, %d)\n", + nproc, ntext); + return; + } proc = (struct proc *)calloc(nproc, sizeof (struct proc)); - lseek(fc, getw(nl[SPROC].n_value), 0); - read(fc, proc, nproc * sizeof (struct proc)); - nswapmap = getw(nl[SNSWAPMAP].n_value); + if (proc == NULL) { + fprintf(stderr, "can't allocate memory for proc table\n"); + exit(1); + } + xtext = (struct text *)calloc(ntext, sizeof (struct text)); + if (xtext == NULL) { + fprintf(stderr, "can't allocate memory for text table\n"); + exit(1); + } + nswapmap = getword(nl[SNSWAPMAP].n_value); swapmap = (struct map *)calloc(nswapmap, sizeof (struct map)); - lseek(fc, getw(nl[SWAPMAP].n_value), 0); + if (swapmap == NULL) { + fprintf(stderr, "can't allocate memory for swapmap\n"); + exit(1); + } + nswdev = getword(nl[SNSWDEV].n_value); + swdevt = (struct swdevt *)calloc(nswdev, sizeof (struct swdevt)); + if (swdevt == NULL) { + fprintf(stderr, "can't allocate memory for swdevt table\n"); + exit(1); + } + lseek(fc, mkphys((off_t)nl[SSWDEVT].n_value), L_SET); + read(fc, swdevt, nswdev * sizeof (struct swdevt)); + lseek(fc, mkphys((off_t)getword(nl[SPROC].n_value)), 0); + read(fc, proc, nproc * sizeof (struct proc)); + lseek(fc, mkphys((off_t)getword(nl[STEXT].n_value)), 0); + read(fc, xtext, ntext * sizeof (struct text)); + lseek(fc, mkphys((off_t)getword(nl[SWAPMAP].n_value)), 0); read(fc, swapmap, nswapmap * sizeof (struct map)); - nswap = getw(nl[SNSWAP].n_value); + swapmap->m_name = "swap"; + swapmap->m_limit = (struct mapent *)&swapmap[nswapmap]; + dmmin = getword(nl[SDMMIN].n_value); + dmmax = getword(nl[SDMMAX].n_value); + nswap = 0; + for (sw = swdevt; sw < &swdevt[nswdev]; sw++) + if (sw->sw_freed) + nswap += sw->sw_nblks; free = 0; for (me = (struct mapent *)(swapmap+1); me < (struct mapent *)&swapmap[nswapmap]; me++) free += me->m_size; - ntext = getw(nl[SNTEXT].n_value); - xtext = (struct text *)calloc(ntext, sizeof (struct text)); - lseek(fc, getw(nl[STEXT].n_value), 0); - read(fc, xtext, ntext * sizeof (struct text)); tused = 0; for (xp = xtext; xp < &xtext[ntext]; xp++) - if (xp->x_iptr!=NULL) - tused += xdsize(xp); + if (xp->x_iptr!=NULL) { + tused += ctod(clrnd(xp->x_size)); + if (xp->x_flag & XPAGI) + tused += ctod(clrnd(ctopt(xp->x_size))); + } used = tused; + waste = 0; for (pp = proc; pp < &proc[nproc]; pp++) { if (pp->p_stat == 0 || pp->p_stat == SZOMB) continue; if (pp->p_flag & SSYS) continue; - used += up(pp->p_dsize) + up(pp->p_ssize); + db = ctod(pp->p_dsize), sb = up(db); + used += sb; + waste += sb - db; + db = ctod(pp->p_ssize), sb = up(db); + used += sb; + waste += sb - db; if ((pp->p_flag&SLOAD) == 0) - used += vusize(pp); + used += ctod(vusize(pp)); } - /* a DMMAX/2 block goes to argmap */ if (totflg) { - printf("%3d/%3d 00k swap\n", used/2/100, (used+free)/2/100); +#define btok(x) ((x) / (1024 / DEV_BSIZE)) + printf("%3d/%3d 00k swap\n", + btok(used/100), btok((used+free)/100)); return; } - printf("%d used (%d text), %d free, %d missing\n", - used/2, tused/2, free/2, (nswap - DMMAX/2 - (used + free))/2); + printf("%dk used (%dk text), %dk free, %dk wasted, %dk missing\n", + btok(used), btok(tused), btok(free), btok(waste), +/* a dmmax/2 block goes to argmap */ + btok(nswap - dmmax/2 - (used + free))); + printf("avail: "); + for (i = dmmax; i >= dmmin; i /= 2) { + j = 0; + while (rmalloc(swapmap, i) != 0) + j++; + if (j) printf("%d*%dk ", j, btok(i)); + } + free = 0; + for (me = (struct mapent *)(swapmap+1); + me < (struct mapent *)&swapmap[nswapmap]; me++) + free += me->m_size; + printf("%d*1k\n", btok(free)); } up(size) @@ -658,126 +905,229 @@ up(size) register int i, block; i = 0; - block = DMMIN; + block = dmmin; while (i < size) { i += block; - if (block < DMMAX) + if (block < dmmax) block *= 2; } return (i); } +/* + * Compute number of pages to be allocated to the u. area + * and data and stack area page tables, which are stored on the + * disk immediately after the u. area. + */ vusize(p) -struct proc *p; + register struct proc *p; { register int tsz = p->p_tsize / NPTEPG; - return (clrnd(UPAGES + clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES)) - tsz)); + /* + * We do not need page table space on the disk for page + * table pages wholly containing text. + */ + return (clrnd(UPAGES + + clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES)) - tsz)); } -xdsize(xp) -struct text *xp; +/* + * Allocate 'size' units from the given + * map. Return the base of the allocated space. + * In a map, the addresses are increasing and the + * list is terminated by a 0 size. + * + * Algorithm is first-fit. + * + * This routine knows about the interleaving of the swapmap + * and handles that. + */ +long +rmalloc(mp, size) + register struct map *mp; + long size; { + register struct mapent *ep = (struct mapent *)(mp+1); + register int addr; + register struct mapent *bp; + swblk_t first, rest; - if (xp->x_flag & XPAGI) - return (clrnd(xp->x_size + ctopt(xp->x_size))); - return (xp->x_size); + if (size <= 0 || size > dmmax) + return (0); + /* + * Search for a piece of the resource map which has enough + * free space to accomodate the request. + */ + for (bp = ep; bp->m_size; bp++) { + if (bp->m_size >= size) { + /* + * If allocating from swapmap, + * then have to respect interleaving + * boundaries. + */ + if (nswdev > 1 && + (first = dmmax - bp->m_addr%dmmax) < bp->m_size) { + if (bp->m_size - first < size) + continue; + addr = bp->m_addr + first; + rest = bp->m_size - first - size; + bp->m_size = first; + if (rest) + rmfree(mp, rest, addr+size); + return (addr); + } + /* + * Allocate from the map. + * If there is no space left of the piece + * we allocated from, move the rest of + * the pieces to the left. + */ + addr = bp->m_addr; + bp->m_addr += size; + if ((bp->m_size -= size) == 0) { + do { + bp++; + (bp-1)->m_addr = bp->m_addr; + } while ((bp-1)->m_size = bp->m_size); + } + if (addr % CLSIZE) + return (0); + return (addr); + } + } + return (0); } -dompx() +/* + * Free the previously allocated space at addr + * of size units into the specified map. + * Sort addr into map and combine on + * one or both ends if possible. + */ +rmfree(mp, size, addr) + struct map *mp; + long size, addr; { - register int i; - struct chan chans[NCHANS]; - struct schan schans[NPORTS]; - - lseek(fc, (long)nl[SCHANS].n_value, 0); - read(fc, chans, sizeof chans); - lseek(fc, (long)nl[SSCHANS].n_value, 0); - read(fc, schans, sizeof schans); - - printf("CHAN FLAGS INDEX LINE GROUP FILE TTYP CTLX PGRP OTTYP OLINE DATQ CTLY\n"); - for (i = 0; i < NCHANS; i++) { - printf("%3d ", i); - putf(chans[i].c_flags&INUSE, 'I'); - putf(chans[i].c_flags&SIOCTL, 'S'); - putf(chans[i].c_flags&XGRP, 'X'); - putf(chans[i].c_flags&YGRP, 'Y'); - putf(chans[i].c_flags&WCLOSE, 'W'); - putf(chans[i].c_flags&ISGRP, 'i'); - putf(chans[i].c_flags&BLOCK, 'B'); - putf(chans[i].c_flags&EOTMARK, 'E'); - putf(chans[i].c_flags&SIGBLK, 's'); - putf(chans[i].c_flags&BLKMSG, 'b'); - putf(chans[i].c_flags&ENAMSG, 'e'); - putf(chans[i].c_flags&WFLUSH, 'w'); - putf(chans[i].c_flags&NMBUF, 'N'); - putf(chans[i].c_flags&PORT, 'P'); - putf(chans[i].c_flags&ALT, 'A'); - putf(chans[i].c_flags&FBLOCK, 'F'); - printf("%8x ", chans[i].c_index); - printf("%3d ", chans[i].c_line); - printf("%8x ", chans[i].c_group); - printf("%8x ", chans[i].c_fy); - printf("%8x ", chans[i].c_ttyp); - printf("%8x ", chans[i].c_ctlx); - printf("%6d ", chans[i].c_pgrp); - printf("%8x ", chans[i].c_ottyp); - printf("%3d ", chans[i].c_oline); - printf("%8x ", chans[i].cx.datq); - printf("%8x\n", chans[i].c_ctly); - } - - printf("\nCHAN FLAGS INDEX LINE GROUP FILE TTYP CTLX PGRP\n"); - for (i = 0; i < NPORTS; i++) { - printf("%3d ", i); - putf(schans[i].c_flags&INUSE, 'I'); - putf(schans[i].c_flags&SIOCTL, 'S'); - putf(schans[i].c_flags&XGRP, 'X'); - putf(schans[i].c_flags&YGRP, 'Y'); - putf(schans[i].c_flags&WCLOSE, 'W'); - putf(schans[i].c_flags&ISGRP, 'i'); - putf(schans[i].c_flags&BLOCK, 'B'); - putf(schans[i].c_flags&EOTMARK, 'E'); - putf(schans[i].c_flags&SIGBLK, 's'); - putf(schans[i].c_flags&BLKMSG, 'b'); - putf(schans[i].c_flags&ENAMSG, 'e'); - putf(schans[i].c_flags&WFLUSH, 'w'); - putf(schans[i].c_flags&NMBUF, 'N'); - putf(schans[i].c_flags&PORT, 'P'); - putf(schans[i].c_flags&ALT, 'A'); - putf(schans[i].c_flags&FBLOCK, 'F'); - printf("%8x ", schans[i].c_index); - printf("%3d ", schans[i].c_line); - printf("%8x ", schans[i].c_group); - printf("%8x ", schans[i].c_fy); - printf("%8x ", schans[i].c_ttyp); - printf("%8x ", schans[i].c_ctlx); - printf("%6d\n", schans[i].c_pgrp); + struct mapent *firstbp; + register struct mapent *bp; + register int t; + + /* + * Both address and size must be + * positive, or the protocol has broken down. + */ + if (addr <= 0 || size <= 0) + goto badrmfree; + /* + * Locate the piece of the map which starts after the + * returned space (or the end of the map). + */ + firstbp = bp = (struct mapent *)(mp + 1); + for (; bp->m_addr <= addr && bp->m_size != 0; bp++) + continue; + /* + * If the piece on the left abuts us, + * then we should combine with it. + */ + if (bp > firstbp && (bp-1)->m_addr+(bp-1)->m_size >= addr) { + /* + * Check no overlap (internal error). + */ + if ((bp-1)->m_addr+(bp-1)->m_size > addr) + goto badrmfree; + /* + * Add into piece on the left by increasing its size. + */ + (bp-1)->m_size += size; + /* + * If the combined piece abuts the piece on + * the right now, compress it in also, + * by shifting the remaining pieces of the map over. + */ + if (bp->m_addr && addr+size >= bp->m_addr) { + if (addr+size > bp->m_addr) + goto badrmfree; + (bp-1)->m_size += bp->m_size; + while (bp->m_size) { + bp++; + (bp-1)->m_addr = bp->m_addr; + (bp-1)->m_size = bp->m_size; + } + } + goto done; + } + /* + * Don't abut on the left, check for abutting on + * the right. + */ + if (addr+size >= bp->m_addr && bp->m_size) { + if (addr+size > bp->m_addr) + goto badrmfree; + bp->m_addr -= size; + bp->m_size += size; + goto done; } + /* + * Don't abut at all. Make a new entry + * and check for map overflow. + */ + do { + t = bp->m_addr; + bp->m_addr = addr; + addr = t; + t = bp->m_size; + bp->m_size = size; + bp++; + } while (size = t); + /* + * Segment at bp is to be the delimiter; + * If there is not room for it + * then the table is too full + * and we must discard something. + */ + if (bp+1 > mp->m_limit) { + /* + * Back bp up to last available segment. + * which contains a segment already and must + * be made into the delimiter. + * Discard second to last entry, + * since it is presumably smaller than the last + * and move the last entry back one. + */ + bp--; + printf("%s: rmap ovflo, lost [%d,%d)\n", mp->m_name, + (bp-1)->m_addr, (bp-1)->m_addr+(bp-1)->m_size); + bp[-1] = bp[0]; + bp[0].m_size = bp[0].m_addr = 0; + } +done: + return; +badrmfree: + printf("bad rmfree\n"); } - -dogroup() +/* + * "addr" is a kern virt addr and does not correspond + * To a phys addr after zipping out the high bit.. + * since it was valloc'd in the kernel. + * + * We return the phys addr by simulating kernel vm (/dev/kmem) + * when we are reading a crash dump. + */ +off_t +mkphys(addr) + off_t addr; { - register int i, j; - struct group *groups[NGROUPS]; - struct group g; - - lseek(fc, (long)nl[SGROUP].n_value, 0); - read(fc, groups, sizeof groups); - printf("GROUP STATE INDEX ROT *GROUP *INODE *FILE ROTM DATQ\n"); - for (i = 0; i < NGROUPS; i++) { - if (groups[i] == 0) - continue; - lseek(fc, (long) groups[i], 0); - read(fc, &g, sizeof g); - printf("%3d ", i); - printf("%8x ", g.g_state); - printf("%8x ", g.g_index); - printf("%3d ", g.g_rot); - printf("%8x ", g.g_group); - printf("%8x ", g.g_inode); - printf("%8x ", g.g_file); - printf("%3d ", g.g_rotmask); - printf("%3d\n", g.g_datq); - } + register off_t o; + + if (!kflg) + return(addr); + addr = clear(addr); + o = addr & PGOFSET; + addr >>= PGSHIFT; + addr &= PG_PFNUM; + addr *= NBPW; + addr = getword(nl[SYSMAP].n_value + addr); + addr = ((addr & PG_PFNUM) << PGSHIFT) | o; + return(addr); }