1: /* 2: * Copyright (c) 1980 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: char copyright[] = 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10: All rights reserved.\n"; 11: #endif not lint 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)pstat.c 5.8 (Berkeley) 5/5/86"; 15: #endif not lint 16: 17: /* 18: * Print system stuff 19: */ 20: 21: #define mask(x) (x&0377) 22: #define clear(x) ((int)x&0x7fffffff) 23: 24: #include <sys/param.h> 25: #include <sys/dir.h> 26: #define KERNEL 27: #include <sys/file.h> 28: #undef KERNEL 29: #include <sys/user.h> 30: #include <sys/proc.h> 31: #include <sys/text.h> 32: #include <sys/inode.h> 33: #include <sys/map.h> 34: #include <sys/ioctl.h> 35: #include <sys/tty.h> 36: #include <sys/conf.h> 37: #include <sys/vm.h> 38: #include <nlist.h> 39: #include <machine/pte.h> 40: #include <stdio.h> 41: 42: char *fcore = "/dev/kmem"; 43: char *fmem = "/dev/mem"; 44: char *fnlist = "/vmunix"; 45: int fc, fm; 46: 47: struct nlist nl[] = { 48: #define SINODE 0 49: { "_inode" }, 50: #define STEXT 1 51: { "_text" }, 52: #define SPROC 2 53: { "_proc" }, 54: #define SDZ 3 55: { "_dz_tty" }, 56: #define SNDZ 4 57: { "_dz_cnt" }, 58: #define SKL 5 59: { "_cons" }, 60: #define SFIL 6 61: { "_file" }, 62: #define USRPTMA 7 63: { "_Usrptmap" }, 64: #define USRPT 8 65: { "_usrpt" }, 66: #define SWAPMAP 9 67: { "_swapmap" }, 68: #define SDH 10 69: { "_dh11" }, 70: #define SNDH 11 71: { "_ndh11" }, 72: #define SNPROC 12 73: { "_nproc" }, 74: #define SNTEXT 13 75: { "_ntext" }, 76: #define SNFILE 14 77: { "_nfile" }, 78: #define SNINODE 15 79: { "_ninode" }, 80: #define SNSWAPMAP 16 81: { "_nswapmap" }, 82: #define SPTY 17 83: { "_pt_tty" }, 84: #define SDMMIN 18 85: { "_dmmin" }, 86: #define SDMMAX 19 87: { "_dmmax" }, 88: #define SNSWDEV 20 89: { "_nswdev" }, 90: #define SSWDEVT 21 91: { "_swdevt" }, 92: #define SDMF 22 93: { "_dmf_tty" }, 94: #define SNDMF 23 95: { "_ndmf" }, 96: #define SNPTY 24 97: { "_npty" }, 98: #define SDHU 25 99: { "_dhu_tty" }, 100: #define SNDHU 26 101: { "_ndhu" }, 102: #define SYSMAP 27 103: { "_Sysmap" }, 104: #define SDMZ 28 105: { "_dmz_tty" }, 106: #define SNDMZ 29 107: { "_ndmz" }, 108: { "" } 109: }; 110: 111: int inof; 112: int txtf; 113: int prcf; 114: int ttyf; 115: int usrf; 116: long ubase; 117: int filf; 118: int swpf; 119: int totflg; 120: char partab[1]; 121: struct cdevsw cdevsw[1]; 122: struct bdevsw bdevsw[1]; 123: int allflg; 124: int kflg; 125: struct pte *Usrptma; 126: struct pte *usrpt; 127: u_long getw(); 128: off_t mkphys(); 129: 130: main(argc, argv) 131: char **argv; 132: { 133: register char *argp; 134: int allflags; 135: 136: argc--, argv++; 137: while (argc > 0 && **argv == '-') { 138: argp = *argv++; 139: argp++; 140: argc--; 141: while (*argp++) 142: switch (argp[-1]) { 143: 144: case 'T': 145: totflg++; 146: break; 147: 148: case 'a': 149: allflg++; 150: break; 151: 152: case 'i': 153: inof++; 154: break; 155: 156: case 'k': 157: kflg++; 158: fcore = fmem = "/vmcore"; 159: break; 160: 161: case 'x': 162: txtf++; 163: break; 164: 165: case 'p': 166: prcf++; 167: break; 168: 169: case 't': 170: ttyf++; 171: break; 172: 173: case 'u': 174: if (argc == 0) 175: break; 176: argc--; 177: usrf++; 178: sscanf( *argv++, "%x", &ubase); 179: break; 180: 181: case 'f': 182: filf++; 183: break; 184: case 's': 185: swpf++; 186: break; 187: default: 188: usage(); 189: exit(1); 190: } 191: } 192: if (argc>1) { 193: fcore = fmem = argv[1]; 194: kflg++; 195: } 196: if ((fc = open(fcore, 0)) < 0) { 197: printf("Can't find %s\n", fcore); 198: exit(1); 199: } 200: if ((fm = open(fmem, 0)) < 0) { 201: printf("Can't find %s\n", fmem); 202: exit(1); 203: } 204: if (argc>0) 205: fnlist = argv[0]; 206: nlist(fnlist, nl); 207: usrpt = (struct pte *)nl[USRPT].n_value; 208: Usrptma = (struct pte *)nl[USRPTMA].n_value; 209: if (nl[0].n_type == 0) { 210: printf("no namelist\n"); 211: exit(1); 212: } 213: allflags = filf | totflg | inof | prcf | txtf | ttyf | usrf | swpf; 214: if (allflags == 0) { 215: printf("pstat: one or more of -[aixptfsu] is required\n"); 216: exit(1); 217: } 218: if (filf||totflg) 219: dofile(); 220: if (inof||totflg) 221: doinode(); 222: if (prcf||totflg) 223: doproc(); 224: if (txtf||totflg) 225: dotext(); 226: if (ttyf) 227: dotty(); 228: if (usrf) 229: dousr(); 230: if (swpf||totflg) 231: doswap(); 232: } 233: 234: usage() 235: { 236: 237: printf("usage: pstat -[aixptfs] [-u [ubase]] [system] [core]\n"); 238: } 239: 240: doinode() 241: { 242: register struct inode *ip; 243: struct inode *xinode, *ainode; 244: register int nin; 245: int ninode; 246: 247: nin = 0; 248: ninode = getw(nl[SNINODE].n_value); 249: xinode = (struct inode *)calloc(ninode, sizeof (struct inode)); 250: ainode = (struct inode *)getw(nl[SINODE].n_value); 251: if (ninode < 0 || ninode > 10000) { 252: fprintf(stderr, "number of inodes is preposterous (%d)\n", 253: ninode); 254: return; 255: } 256: if (xinode == NULL) { 257: fprintf(stderr, "can't allocate memory for inode table\n"); 258: return; 259: } 260: lseek(fc, mkphys((off_t)ainode), 0); 261: read(fc, xinode, ninode * sizeof(struct inode)); 262: for (ip = xinode; ip < &xinode[ninode]; ip++) 263: if (ip->i_count) 264: nin++; 265: if (totflg) { 266: printf("%3d/%3d inodes\n", nin, ninode); 267: return; 268: } 269: printf("%d/%d active inodes\n", nin, ninode); 270: printf(" LOC FLAGS CNT DEVICE RDC WRC INO MODE NLK UID SIZE/DEV\n"); 271: for (ip = xinode; ip < &xinode[ninode]; ip++) { 272: if (ip->i_count == 0) 273: continue; 274: printf("%8.1x ", ainode + (ip - xinode)); 275: putf(ip->i_flag&ILOCKED, 'L'); 276: putf(ip->i_flag&IUPD, 'U'); 277: putf(ip->i_flag&IACC, 'A'); 278: putf(ip->i_flag&IMOUNT, 'M'); 279: putf(ip->i_flag&IWANT, 'W'); 280: putf(ip->i_flag&ITEXT, 'T'); 281: putf(ip->i_flag&ICHG, 'C'); 282: putf(ip->i_flag&ISHLOCK, 'S'); 283: putf(ip->i_flag&IEXLOCK, 'E'); 284: putf(ip->i_flag&ILWAIT, 'Z'); 285: printf("%4d", ip->i_count&0377); 286: printf("%4d,%3d", major(ip->i_dev), minor(ip->i_dev)); 287: printf("%4d", ip->i_shlockc&0377); 288: printf("%4d", ip->i_exlockc&0377); 289: printf("%6d", ip->i_number); 290: printf("%6x", ip->i_mode & 0xffff); 291: printf("%4d", ip->i_nlink); 292: printf("%4d", ip->i_uid); 293: if ((ip->i_mode&IFMT)==IFBLK || (ip->i_mode&IFMT)==IFCHR) 294: printf("%6d,%3d", major(ip->i_rdev), minor(ip->i_rdev)); 295: else 296: printf("%10ld", ip->i_size); 297: printf("\n"); 298: } 299: free(xinode); 300: } 301: 302: u_long 303: getw(loc) 304: off_t loc; 305: { 306: u_long word; 307: 308: if (kflg) 309: loc &= 0x7fffffff; 310: lseek(fc, loc, 0); 311: read(fc, &word, sizeof (word)); 312: return (word); 313: } 314: 315: putf(v, n) 316: { 317: if (v) 318: printf("%c", n); 319: else 320: printf(" "); 321: } 322: 323: dotext() 324: { 325: register struct text *xp; 326: int ntext; 327: struct text *xtext, *atext; 328: int ntx, ntxca; 329: 330: ntx = ntxca = 0; 331: ntext = getw(nl[SNTEXT].n_value); 332: xtext = (struct text *)calloc(ntext, sizeof (struct text)); 333: atext = (struct text *)getw(nl[STEXT].n_value); 334: if (ntext < 0 || ntext > 10000) { 335: fprintf(stderr, "number of texts is preposterous (%d)\n", 336: ntext); 337: return; 338: } 339: if (xtext == NULL) { 340: fprintf(stderr, "can't allocate memory for text table\n"); 341: return; 342: } 343: lseek(fc, mkphys((off_t)atext), 0); 344: read(fc, xtext, ntext * sizeof (struct text)); 345: for (xp = xtext; xp < &xtext[ntext]; xp++) { 346: if (xp->x_iptr != NULL) 347: ntxca++; 348: if (xp->x_count != 0) 349: ntx++; 350: } 351: if (totflg) { 352: printf("%3d/%3d texts active, %3d used\n", ntx, ntext, ntxca); 353: return; 354: } 355: printf("%d/%d active texts, %d used\n", ntx, ntext, ntxca); 356: printf("\ 357: LOC FLAGS DADDR CADDR RSS SIZE IPTR CNT CCNT FORW BACK\n"); 358: for (xp = xtext; xp < &xtext[ntext]; xp++) { 359: if (xp->x_iptr == NULL) 360: continue; 361: printf("%8.1x", atext + (xp - xtext)); 362: printf(" "); 363: putf(xp->x_flag&XPAGI, 'P'); 364: putf(xp->x_flag&XTRC, 'T'); 365: putf(xp->x_flag&XWRIT, 'W'); 366: putf(xp->x_flag&XLOAD, 'L'); 367: putf(xp->x_flag&XLOCK, 'K'); 368: putf(xp->x_flag&XWANT, 'w'); 369: printf("%5x", xp->x_daddr[0]); 370: printf("%10x", xp->x_caddr); 371: printf("%5d", xp->x_rssize); 372: printf("%5d", xp->x_size); 373: printf("%10.1x", xp->x_iptr); 374: printf("%5d", xp->x_count&0377); 375: printf("%5d", xp->x_ccount); 376: printf("%10x", xp->x_forw); 377: printf("%9x", xp->x_back); 378: printf("\n"); 379: } 380: free(xtext); 381: } 382: 383: doproc() 384: { 385: struct proc *xproc, *aproc; 386: int nproc; 387: register struct proc *pp; 388: register loc, np; 389: struct pte apte; 390: 391: nproc = getw(nl[SNPROC].n_value); 392: xproc = (struct proc *)calloc(nproc, sizeof (struct proc)); 393: aproc = (struct proc *)getw(nl[SPROC].n_value); 394: if (nproc < 0 || nproc > 10000) { 395: fprintf(stderr, "number of procs is preposterous (%d)\n", 396: nproc); 397: return; 398: } 399: if (xproc == NULL) { 400: fprintf(stderr, "can't allocate memory for proc table\n"); 401: return; 402: } 403: lseek(fc, mkphys((off_t)aproc), 0); 404: read(fc, xproc, nproc * sizeof (struct proc)); 405: np = 0; 406: for (pp=xproc; pp < &xproc[nproc]; pp++) 407: if (pp->p_stat) 408: np++; 409: if (totflg) { 410: printf("%3d/%3d processes\n", np, nproc); 411: return; 412: } 413: printf("%d/%d processes\n", np, nproc); 414: printf(" LOC S F POIP PRI SIG UID SLP TIM CPU NI PGRP PID PPID ADDR RSS SRSS SIZE WCHAN LINK TEXTP\n"); 415: for (pp=xproc; pp<&xproc[nproc]; pp++) { 416: if (pp->p_stat==0 && allflg==0) 417: continue; 418: printf("%8x", aproc + (pp - xproc)); 419: printf(" %2d", pp->p_stat); 420: printf(" %4x", pp->p_flag & 0xffff); 421: printf(" %4d", pp->p_poip); 422: printf(" %3d", pp->p_pri); 423: printf(" %8x", pp->p_sig); 424: printf(" %4d", pp->p_uid); 425: printf(" %3d", pp->p_slptime); 426: printf(" %3d", pp->p_time); 427: printf(" %4d", pp->p_cpu&0377); 428: printf(" %3d", pp->p_nice); 429: printf(" %6d", pp->p_pgrp); 430: printf(" %6d", pp->p_pid); 431: printf(" %6d", pp->p_ppid); 432: if (kflg) 433: pp->p_addr = (struct pte *)clear((int)pp->p_addr); 434: if (pp->p_flag & SLOAD) { 435: lseek(fc, (long)pp->p_addr, 0); 436: read(fc, &apte, sizeof(apte)); 437: printf(" %8x", apte.pg_pfnum); 438: } else 439: printf(" %8x", pp->p_swaddr); 440: printf(" %4x", pp->p_rssize); 441: printf(" %4x", pp->p_swrss); 442: printf(" %5x", pp->p_dsize+pp->p_ssize); 443: printf(" %7x", clear(pp->p_wchan)); 444: printf(" %7x", clear(pp->p_link)); 445: printf(" %7x", clear(pp->p_textp)); 446: printf("\n"); 447: } 448: free(xproc); 449: } 450: 451: static char mesg[] = 452: " # RAW CAN OUT MODE ADDR DEL COL STATE PGRP DISC\n"; 453: static int ttyspace = 128; 454: static struct tty *tty; 455: 456: dotty() 457: { 458: extern char *malloc(); 459: 460: if ((tty = (struct tty *)malloc(ttyspace * sizeof(*tty))) == 0) { 461: printf("pstat: out of memory\n"); 462: return; 463: } 464: printf("1 cons\n"); 465: if (kflg) 466: nl[SKL].n_value = clear(nl[SKL].n_value); 467: lseek(fc, (long)nl[SKL].n_value, 0); 468: read(fc, tty, sizeof(*tty)); 469: printf(mesg); 470: ttyprt(&tty[0], 0); 471: if (nl[SNDZ].n_type != 0) 472: dottytype("dz", SDZ, SNDZ); 473: if (nl[SNDH].n_type != 0) 474: dottytype("dh", SDH, SNDH); 475: if (nl[SNDMF].n_type != 0) 476: dottytype("dmf", SDMF, SNDMF); 477: if (nl[SNDHU].n_type != 0) 478: dottytype("dhu", SDHU, SNDHU); 479: if (nl[SNDMZ].n_type != 0) 480: dottytype("dmz", SDMZ, SNDMZ); 481: if (nl[SNPTY].n_type != 0) 482: dottytype("pty", SPTY, SNPTY); 483: } 484: 485: dottytype(name, type, number) 486: char *name; 487: { 488: int ntty; 489: register struct tty *tp; 490: extern char *realloc(); 491: 492: if (tty == (struct tty *)0) 493: return; 494: if (kflg) { 495: nl[number].n_value = clear(nl[number].n_value); 496: nl[type].n_value = clear(nl[type].n_value); 497: } 498: lseek(fc, (long)nl[number].n_value, 0); 499: read(fc, &ntty, sizeof(ntty)); 500: printf("%d %s lines\n", ntty, name); 501: if (ntty > ttyspace) { 502: ttyspace = ntty; 503: if ((tty = (struct tty *)realloc(tty, ttyspace * sizeof(*tty))) == 0) { 504: printf("pstat: out of memory\n"); 505: return; 506: } 507: } 508: lseek(fc, (long)nl[type].n_value, 0); 509: read(fc, tty, ntty * sizeof(struct tty)); 510: printf(mesg); 511: for (tp = tty; tp < &tty[ntty]; tp++) 512: ttyprt(tp, tp - tty); 513: } 514: 515: ttyprt(atp, line) 516: struct tty *atp; 517: { 518: register struct tty *tp; 519: 520: printf("%2d", line); 521: tp = atp; 522: switch (tp->t_line) { 523: 524: /* 525: case NETLDISC: 526: if (tp->t_rec) 527: printf("%4d%4d", 0, tp->t_inbuf); 528: else 529: printf("%4d%4d", tp->t_inbuf, 0); 530: break; 531: */ 532: 533: default: 534: printf("%4d%4d", tp->t_rawq.c_cc, tp->t_canq.c_cc); 535: } 536: printf("%4d %8x %8x%4d%4d", tp->t_outq.c_cc, tp->t_flags, 537: tp->t_addr, tp->t_delct, tp->t_col); 538: putf(tp->t_state&TS_TIMEOUT, 'T'); 539: putf(tp->t_state&TS_WOPEN, 'W'); 540: putf(tp->t_state&TS_ISOPEN, 'O'); 541: putf(tp->t_state&TS_FLUSH, 'F'); 542: putf(tp->t_state&TS_CARR_ON, 'C'); 543: putf(tp->t_state&TS_BUSY, 'B'); 544: putf(tp->t_state&TS_ASLEEP, 'A'); 545: putf(tp->t_state&TS_XCLUDE, 'X'); 546: putf(tp->t_state&TS_TTSTOP, 'S'); 547: putf(tp->t_state&TS_HUPCLS, 'H'); 548: printf("%6d", tp->t_pgrp); 549: switch (tp->t_line) { 550: 551: case OTTYDISC: 552: printf("\n"); 553: break; 554: 555: case NTTYDISC: 556: printf(" ntty\n"); 557: break; 558: 559: case NETLDISC: 560: printf(" berknet\n"); 561: break; 562: 563: case TABLDISC: 564: printf(" tab\n"); 565: break; 566: 567: default: 568: printf(" %d\n", tp->t_line); 569: } 570: } 571: 572: dousr() 573: { 574: struct user U; 575: register i, j, *ip; 576: register struct nameidata *nd = &U.u_nd; 577: 578: /* This wins only if CLBYTES >= sizeof (struct user) */ 579: lseek(fm, ubase * NBPG, 0); 580: read(fm, &U, sizeof(U)); 581: printf("pcb"); 582: ip = (int *)&U.u_pcb; 583: while (ip < &U.u_arg[0]) { 584: if ((ip - (int *)&U.u_pcb) % 4 == 0) 585: printf("\t"); 586: printf("%x ", *ip++); 587: if ((ip - (int *)&U.u_pcb) % 4 == 0) 588: printf("\n"); 589: } 590: if ((ip - (int *)&U.u_pcb) % 4 != 0) 591: printf("\n"); 592: printf("arg"); 593: for (i=0; i<sizeof(U.u_arg)/sizeof(U.u_arg[0]); i++) { 594: if (i%5==0) 595: printf("\t"); 596: printf(" %.1x", U.u_arg[i]); 597: if (i%5==4) 598: printf("\n"); 599: } 600: if (i%5) 601: printf("\n"); 602: printf("segflg\t%d\nerror %d\n", nd->ni_segflg, U.u_error); 603: printf("uids\t%d,%d,%d,%d\n", U.u_uid,U.u_gid,U.u_ruid,U.u_rgid); 604: printf("procp\t%.1x\n", U.u_procp); 605: printf("ap\t%.1x\n", U.u_ap); 606: printf("r_val?\t%.1x %.1x\n", U.u_r.r_val1, U.u_r.r_val2); 607: printf("base, count, offset %.1x %.1x %ld\n", nd->ni_base, 608: nd->ni_count, nd->ni_offset); 609: printf("cdir rdir %.1x %.1x\n", U.u_cdir, U.u_rdir); 610: printf("dirp %.1x\n", nd->ni_dirp); 611: printf("dent %d %.14s\n", nd->ni_dent.d_ino, nd->ni_dent.d_name); 612: printf("pdir %.1o\n", nd->ni_pdir); 613: printf("file"); 614: for (i=0; i<NOFILE; i++) { 615: if (i % 8 == 0) 616: printf("\t"); 617: printf("%9.1x", U.u_ofile[i]); 618: if (i % 8 == 7) 619: printf("\n"); 620: } 621: if (i % 8) 622: printf("\n"); 623: printf("pofile"); 624: for (i=0; i<NOFILE; i++) { 625: if (i % 8 == 0) 626: printf("\t"); 627: printf("%9.1x", U.u_pofile[i]); 628: if (i % 8 == 7) 629: printf("\n"); 630: } 631: if (i % 8) 632: printf("\n"); 633: printf("ssave"); 634: for (i=0; i<sizeof(label_t)/sizeof(int); i++) { 635: if (i%5==0) 636: printf("\t"); 637: printf("%9.1x", U.u_ssave.val[i]); 638: if (i%5==4) 639: printf("\n"); 640: } 641: if (i%5) 642: printf("\n"); 643: printf("sigs"); 644: for (i=0; i<NSIG; i++) { 645: if (i % 8 == 0) 646: printf("\t"); 647: printf("%.1x ", U.u_signal[i]); 648: if (i % 8 == 7) 649: printf("\n"); 650: } 651: if (i % 8) 652: printf("\n"); 653: printf("code\t%.1x\n", U.u_code); 654: printf("ar0\t%.1x\n", U.u_ar0); 655: printf("prof\t%X %X %X %X\n", U.u_prof.pr_base, U.u_prof.pr_size, 656: U.u_prof.pr_off, U.u_prof.pr_scale); 657: printf("\neosys\t%d\n", U.u_eosys); 658: printf("ttyp\t%.1x\n", U.u_ttyp); 659: printf("ttyd\t%d,%d\n", major(U.u_ttyd), minor(U.u_ttyd)); 660: printf("comm %.14s\n", U.u_comm); 661: printf("start\t%D\n", U.u_start); 662: printf("acflag\t%D\n", U.u_acflag); 663: printf("cmask\t%D\n", U.u_cmask); 664: printf("sizes\t%.1x %.1x %.1x\n", U.u_tsize, U.u_dsize, U.u_ssize); 665: printf("ru\t"); 666: ip = (int *)&U.u_ru; 667: for (i = 0; i < sizeof(U.u_ru)/sizeof(int); i++) 668: printf("%D ", ip[i]); 669: printf("\n"); 670: ip = (int *)&U.u_cru; 671: printf("cru\t"); 672: for (i = 0; i < sizeof(U.u_cru)/sizeof(int); i++) 673: printf("%D ", ip[i]); 674: printf("\n"); 675: /* 676: i = U.u_stack - &U; 677: while (U[++i] == 0); 678: i &= ~07; 679: while (i < 512) { 680: printf("%x ", 0140000+2*i); 681: for (j=0; j<8; j++) 682: printf("%9x", U[i++]); 683: printf("\n"); 684: } 685: */ 686: } 687: 688: oatoi(s) 689: char *s; 690: { 691: register v; 692: 693: v = 0; 694: while (*s) 695: v = (v<<3) + *s++ - '0'; 696: return(v); 697: } 698: 699: dofile() 700: { 701: int nfile; 702: struct file *xfile, *afile; 703: register struct file *fp; 704: register nf; 705: int loc; 706: static char *dtypes[] = { "???", "inode", "socket" }; 707: 708: nf = 0; 709: nfile = getw(nl[SNFILE].n_value); 710: xfile = (struct file *)calloc(nfile, sizeof (struct file)); 711: afile = (struct file *)getw(nl[SFIL].n_value); 712: if (nfile < 0 || nfile > 10000) { 713: fprintf(stderr, "number of files is preposterous (%d)\n", 714: nfile); 715: return; 716: } 717: if (xfile == NULL) { 718: fprintf(stderr, "can't allocate memory for file table\n"); 719: return; 720: } 721: lseek(fc, mkphys((off_t)afile), 0); 722: read(fc, xfile, nfile * sizeof (struct file)); 723: for (fp=xfile; fp < &xfile[nfile]; fp++) 724: if (fp->f_count) 725: nf++; 726: if (totflg) { 727: printf("%3d/%3d files\n", nf, nfile); 728: return; 729: } 730: printf("%d/%d open files\n", nf, nfile); 731: printf(" LOC TYPE FLG CNT MSG DATA OFFSET\n"); 732: for (fp=xfile,loc=(int)afile; fp < &xfile[nfile]; fp++,loc+=sizeof(xfile[0])) { 733: if (fp->f_count==0) 734: continue; 735: printf("%8x ", loc); 736: if (fp->f_type <= DTYPE_SOCKET) 737: printf("%-8.8s", dtypes[fp->f_type]); 738: else 739: printf("8d", fp->f_type); 740: putf(fp->f_flag&FREAD, 'R'); 741: putf(fp->f_flag&FWRITE, 'W'); 742: putf(fp->f_flag&FAPPEND, 'A'); 743: putf(fp->f_flag&FSHLOCK, 'S'); 744: putf(fp->f_flag&FEXLOCK, 'X'); 745: putf(fp->f_flag&FASYNC, 'I'); 746: printf(" %3d", mask(fp->f_count)); 747: printf(" %3d", mask(fp->f_msgcount)); 748: printf(" %8.1x", fp->f_data); 749: if (fp->f_offset < 0) 750: printf(" %x\n", fp->f_offset); 751: else 752: printf(" %ld\n", fp->f_offset); 753: } 754: free(xfile); 755: } 756: 757: int dmmin, dmmax, nswdev; 758: 759: doswap() 760: { 761: struct proc *proc; 762: int nproc; 763: struct text *xtext; 764: int ntext; 765: struct map *swapmap; 766: int nswapmap; 767: struct swdevt *swdevt, *sw; 768: register struct proc *pp; 769: int nswap, used, tused, free, waste; 770: int db, sb; 771: register struct mapent *me; 772: register struct text *xp; 773: int i, j; 774: 775: nproc = getw(nl[SNPROC].n_value); 776: ntext = getw(nl[SNTEXT].n_value); 777: if (nproc < 0 || nproc > 10000 || ntext < 0 || ntext > 10000) { 778: fprintf(stderr, "number of procs/texts is preposterous (%d, %d)\n", 779: nproc, ntext); 780: return; 781: } 782: proc = (struct proc *)calloc(nproc, sizeof (struct proc)); 783: if (proc == NULL) { 784: fprintf(stderr, "can't allocate memory for proc table\n"); 785: exit(1); 786: } 787: xtext = (struct text *)calloc(ntext, sizeof (struct text)); 788: if (xtext == NULL) { 789: fprintf(stderr, "can't allocate memory for text table\n"); 790: exit(1); 791: } 792: nswapmap = getw(nl[SNSWAPMAP].n_value); 793: swapmap = (struct map *)calloc(nswapmap, sizeof (struct map)); 794: if (swapmap == NULL) { 795: fprintf(stderr, "can't allocate memory for swapmap\n"); 796: exit(1); 797: } 798: nswdev = getw(nl[SNSWDEV].n_value); 799: swdevt = (struct swdevt *)calloc(nswdev, sizeof (struct swdevt)); 800: if (swdevt == NULL) { 801: fprintf(stderr, "can't allocate memory for swdevt table\n"); 802: exit(1); 803: } 804: lseek(fc, mkphys((off_t)nl[SSWDEVT].n_value), L_SET); 805: read(fc, swdevt, nswdev * sizeof (struct swdevt)); 806: lseek(fc, mkphys((off_t)getw(nl[SPROC].n_value)), 0); 807: read(fc, proc, nproc * sizeof (struct proc)); 808: lseek(fc, mkphys((off_t)getw(nl[STEXT].n_value)), 0); 809: read(fc, xtext, ntext * sizeof (struct text)); 810: lseek(fc, mkphys((off_t)getw(nl[SWAPMAP].n_value)), 0); 811: read(fc, swapmap, nswapmap * sizeof (struct map)); 812: swapmap->m_name = "swap"; 813: swapmap->m_limit = (struct mapent *)&swapmap[nswapmap]; 814: dmmin = getw(nl[SDMMIN].n_value); 815: dmmax = getw(nl[SDMMAX].n_value); 816: nswap = 0; 817: for (sw = swdevt; sw < &swdevt[nswdev]; sw++) 818: if (sw->sw_freed) 819: nswap += sw->sw_nblks; 820: free = 0; 821: for (me = (struct mapent *)(swapmap+1); 822: me < (struct mapent *)&swapmap[nswapmap]; me++) 823: free += me->m_size; 824: tused = 0; 825: for (xp = xtext; xp < &xtext[ntext]; xp++) 826: if (xp->x_iptr!=NULL) { 827: tused += ctod(clrnd(xp->x_size)); 828: if (xp->x_flag & XPAGI) 829: tused += ctod(clrnd(ctopt(xp->x_size))); 830: } 831: used = tused; 832: waste = 0; 833: for (pp = proc; pp < &proc[nproc]; pp++) { 834: if (pp->p_stat == 0 || pp->p_stat == SZOMB) 835: continue; 836: if (pp->p_flag & SSYS) 837: continue; 838: db = ctod(pp->p_dsize), sb = up(db); 839: used += sb; 840: waste += sb - db; 841: db = ctod(pp->p_ssize), sb = up(db); 842: used += sb; 843: waste += sb - db; 844: if ((pp->p_flag&SLOAD) == 0) 845: used += ctod(vusize(pp)); 846: } 847: if (totflg) { 848: #define btok(x) ((x) / (1024 / DEV_BSIZE)) 849: printf("%3d/%3d 00k swap\n", 850: btok(used/100), btok((used+free)/100)); 851: return; 852: } 853: printf("%dk used (%dk text), %dk free, %dk wasted, %dk missing\n", 854: btok(used), btok(tused), btok(free), btok(waste), 855: /* a dmmax/2 block goes to argmap */ 856: btok(nswap - dmmax/2 - (used + free))); 857: printf("avail: "); 858: for (i = dmmax; i >= dmmin; i /= 2) { 859: j = 0; 860: while (rmalloc(swapmap, i) != 0) 861: j++; 862: if (j) printf("%d*%dk ", j, btok(i)); 863: } 864: free = 0; 865: for (me = (struct mapent *)(swapmap+1); 866: me < (struct mapent *)&swapmap[nswapmap]; me++) 867: free += me->m_size; 868: printf("%d*1k\n", btok(free)); 869: } 870: 871: up(size) 872: register int size; 873: { 874: register int i, block; 875: 876: i = 0; 877: block = dmmin; 878: while (i < size) { 879: i += block; 880: if (block < dmmax) 881: block *= 2; 882: } 883: return (i); 884: } 885: 886: /* 887: * Compute number of pages to be allocated to the u. area 888: * and data and stack area page tables, which are stored on the 889: * disk immediately after the u. area. 890: */ 891: vusize(p) 892: register struct proc *p; 893: { 894: register int tsz = p->p_tsize / NPTEPG; 895: 896: /* 897: * We do not need page table space on the disk for page 898: * table pages wholly containing text. 899: */ 900: return (clrnd(UPAGES + 901: clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES)) - tsz)); 902: } 903: 904: /* 905: * Allocate 'size' units from the given 906: * map. Return the base of the allocated space. 907: * In a map, the addresses are increasing and the 908: * list is terminated by a 0 size. 909: * 910: * Algorithm is first-fit. 911: * 912: * This routine knows about the interleaving of the swapmap 913: * and handles that. 914: */ 915: long 916: rmalloc(mp, size) 917: register struct map *mp; 918: long size; 919: { 920: register struct mapent *ep = (struct mapent *)(mp+1); 921: register int addr; 922: register struct mapent *bp; 923: swblk_t first, rest; 924: 925: if (size <= 0 || size > dmmax) 926: return (0); 927: /* 928: * Search for a piece of the resource map which has enough 929: * free space to accomodate the request. 930: */ 931: for (bp = ep; bp->m_size; bp++) { 932: if (bp->m_size >= size) { 933: /* 934: * If allocating from swapmap, 935: * then have to respect interleaving 936: * boundaries. 937: */ 938: if (nswdev > 1 && 939: (first = dmmax - bp->m_addr%dmmax) < bp->m_size) { 940: if (bp->m_size - first < size) 941: continue; 942: addr = bp->m_addr + first; 943: rest = bp->m_size - first - size; 944: bp->m_size = first; 945: if (rest) 946: rmfree(mp, rest, addr+size); 947: return (addr); 948: } 949: /* 950: * Allocate from the map. 951: * If there is no space left of the piece 952: * we allocated from, move the rest of 953: * the pieces to the left. 954: */ 955: addr = bp->m_addr; 956: bp->m_addr += size; 957: if ((bp->m_size -= size) == 0) { 958: do { 959: bp++; 960: (bp-1)->m_addr = bp->m_addr; 961: } while ((bp-1)->m_size = bp->m_size); 962: } 963: if (addr % CLSIZE) 964: return (0); 965: return (addr); 966: } 967: } 968: return (0); 969: } 970: 971: /* 972: * Free the previously allocated space at addr 973: * of size units into the specified map. 974: * Sort addr into map and combine on 975: * one or both ends if possible. 976: */ 977: rmfree(mp, size, addr) 978: struct map *mp; 979: long size, addr; 980: { 981: struct mapent *firstbp; 982: register struct mapent *bp; 983: register int t; 984: 985: /* 986: * Both address and size must be 987: * positive, or the protocol has broken down. 988: */ 989: if (addr <= 0 || size <= 0) 990: goto badrmfree; 991: /* 992: * Locate the piece of the map which starts after the 993: * returned space (or the end of the map). 994: */ 995: firstbp = bp = (struct mapent *)(mp + 1); 996: for (; bp->m_addr <= addr && bp->m_size != 0; bp++) 997: continue; 998: /* 999: * If the piece on the left abuts us, 1000: * then we should combine with it. 1001: */ 1002: if (bp > firstbp && (bp-1)->m_addr+(bp-1)->m_size >= addr) { 1003: /* 1004: * Check no overlap (internal error). 1005: */ 1006: if ((bp-1)->m_addr+(bp-1)->m_size > addr) 1007: goto badrmfree; 1008: /* 1009: * Add into piece on the left by increasing its size. 1010: */ 1011: (bp-1)->m_size += size; 1012: /* 1013: * If the combined piece abuts the piece on 1014: * the right now, compress it in also, 1015: * by shifting the remaining pieces of the map over. 1016: */ 1017: if (bp->m_addr && addr+size >= bp->m_addr) { 1018: if (addr+size > bp->m_addr) 1019: goto badrmfree; 1020: (bp-1)->m_size += bp->m_size; 1021: while (bp->m_size) { 1022: bp++; 1023: (bp-1)->m_addr = bp->m_addr; 1024: (bp-1)->m_size = bp->m_size; 1025: } 1026: } 1027: goto done; 1028: } 1029: /* 1030: * Don't abut on the left, check for abutting on 1031: * the right. 1032: */ 1033: if (addr+size >= bp->m_addr && bp->m_size) { 1034: if (addr+size > bp->m_addr) 1035: goto badrmfree; 1036: bp->m_addr -= size; 1037: bp->m_size += size; 1038: goto done; 1039: } 1040: /* 1041: * Don't abut at all. Make a new entry 1042: * and check for map overflow. 1043: */ 1044: do { 1045: t = bp->m_addr; 1046: bp->m_addr = addr; 1047: addr = t; 1048: t = bp->m_size; 1049: bp->m_size = size; 1050: bp++; 1051: } while (size = t); 1052: /* 1053: * Segment at bp is to be the delimiter; 1054: * If there is not room for it 1055: * then the table is too full 1056: * and we must discard something. 1057: */ 1058: if (bp+1 > mp->m_limit) { 1059: /* 1060: * Back bp up to last available segment. 1061: * which contains a segment already and must 1062: * be made into the delimiter. 1063: * Discard second to last entry, 1064: * since it is presumably smaller than the last 1065: * and move the last entry back one. 1066: */ 1067: bp--; 1068: printf("%s: rmap ovflo, lost [%d,%d)\n", mp->m_name, 1069: (bp-1)->m_addr, (bp-1)->m_addr+(bp-1)->m_size); 1070: bp[-1] = bp[0]; 1071: bp[0].m_size = bp[0].m_addr = 0; 1072: } 1073: done: 1074: return; 1075: badrmfree: 1076: printf("bad rmfree\n"); 1077: } 1078: /* 1079: * "addr" is a kern virt addr and does not correspond 1080: * To a phys addr after zipping out the high bit.. 1081: * since it was valloc'd in the kernel. 1082: * 1083: * We return the phys addr by simulating kernel vm (/dev/kmem) 1084: * when we are reading a crash dump. 1085: */ 1086: off_t 1087: mkphys(addr) 1088: off_t addr; 1089: { 1090: register off_t o; 1091: 1092: if (!kflg) 1093: return(addr); 1094: o = addr & PGOFSET; 1095: addr >>= PGSHIFT; 1096: addr &= PG_PFNUM; 1097: addr *= NBPW; 1098: addr = getw(nl[SYSMAP].n_value + addr); 1099: addr = ((addr & PG_PFNUM) << PGSHIFT) | o; 1100: return(addr); 1101: }