|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.