1: /* 2: * IOSTAT 3: * 4: * For use with the 2.9 BSD (Berkeley PDP11) system. 5: */ 6: #include <sys/param.h> 7: #ifndef DISKMON 8: #define DISKMON /* force definition for systm.h */ 9: #endif 10: #include <sys/systm.h> 11: #include <stdio.h> 12: #include <a.out.h> 13: 14: #define MAXDISK 6 /* max disks that can be monitored */ 15: #define LSTDRV 0 /* last bit for drives (seek only) */ 16: 17: /* usec per word for the various disks */ 18: double xf[MAXDISK] = { 19: 2.48, /* RM02 */ 20: 2.48, /* RM02 */ 21: 11.1 /* RK05 */ 22: /* 1.95, Ampex 9300/Diva Comp 5 (33 sect.) */ 23: /* 2.05, RS04 */ 24: }; 25: 26: int bflg; 27: int dflg; 28: int iflg; 29: int aflg; 30: int sflg; 31: int oflg; /* Data only, no summary line, no headers */ 32: int uflg; 33: struct nlist nl[] = { 34: #define X_DKBUSY 0 35: "_dk_busy", 0, 0, 36: #define X_SYTIME 1 37: "_sy_time", 0, 0, 38: #define X_DKTIME 2 39: "_dk_time", 0, 0, 40: #define X_DKNUMB 3 41: "_dk_numb", 0, 0, 42: #define X_DKWDS 4 43: "_dk_wds", 0, 0, 44: #define X_NDISK 5 45: "_ndisk", 0, 0, 46: #define X_TIN 6 47: "_tk_nin", 0, 0, 48: #define X_TOUT 7 49: "_tk_nout", 0, 0, 50: #define X_IOINFO 8 51: "_io_info", 0, 0, 52: #define X_UBMETER 9 53: "_ub_meter", 0, 0, 54: "\0\0\0\0\0\0\0\0", 0, 0 55: }; 56: struct 57: { 58: int busy; 59: long sy_time[8]; 60: long dk_time[1<<MAXDISK]; 61: long numb[MAXDISK]; 62: long wds[MAXDISK]; 63: long tin; 64: long tout; 65: } s, s1; 66: 67: struct ubmeter { 68: long ub_requests; /* total # of calls to mapalloc */ 69: long ub_remaps; /* total # of buffer remappings */ 70: long ub_failures; /* total # of allocation failures */ 71: long ub_pages; /* total # of pages allocated */ 72: }; 73: 74: 75: int ndisk; 76: struct ioinfo io_info, io_delta; 77: struct ubmeter ub_meter, ub_delta; 78: 79: double etime; 80: 81: int skip=1; 82: int mf; 83: 84: main(argc, argv) 85: char *argv[]; 86: { 87: extern char *ctime(); 88: register i; 89: int iter; 90: double f1, f2; 91: long t; 92: 93: if ((nlist("/unix", nl) == -1) || (nl[0].n_type == 0)) { 94: printf("no /unix namelist\n"); 95: exit(1); 96: } 97: if(nl[X_SYTIME].n_type == 0) { 98: printf("sy_time not in namelist-- wrong iostat\n"); 99: exit(1); 100: } 101: mf = open("/dev/kmem", 0); 102: if(mf < 0) { 103: printf("cannot open /dev/kmem\n"); 104: exit(1); 105: } 106: iter = 0; 107: while (argc>1&&argv[1][0]=='-') { 108: if (argv[1][1]=='d') 109: dflg++; 110: else if (argv[1][1]=='s') 111: sflg++; 112: else if (argv[1][1]=='a') 113: aflg++; 114: else if (argv[1][1]=='i') 115: iflg++; 116: else if (argv[1][1]=='b') 117: bflg++; 118: else if (argv[1][1]=='o') 119: oflg++; 120: else if (argv[1][1]=='u') 121: uflg++; 122: argc--; 123: argv++; 124: } 125: if(argc > 2) 126: iter = atoi(argv[2]); 127: if(oflg && (iter != 0)) iter+=1; 128: lseek(mf, (long)nl[X_NDISK].n_value, 0); 129: read(mf, (char *)&ndisk, sizeof ndisk); 130: if (ndisk <=0 || ndisk > MAXDISK || ndisk <= LSTDRV) { 131: fprintf(stderr, "Too many disks monitored (or system mismatch)\n"); 132: exit(1); 133: } 134: if (!(sflg|iflg|oflg|bflg|uflg)) { 135: printf(" TTY "); 136: for (i=0; i <= LSTDRV; i++) 137: printf(" DK%d SEEK",i); 138: for ( ; i < ndisk; i++) 139: printf(" DK%d TRANSFER ",i); 140: printf(" PERCENT\n"); 141: printf("tin tout"); 142: for (i=0; i <= LSTDRV; i++) 143: printf(" sps msps"); 144: for ( ; i < ndisk; i++) 145: printf(" tps msps mspt"); 146: printf(" usr nic sys idle\n"); 147: } 148: if(iflg&&!oflg) 149: { 150: printf(" RESOURCE USAGE (in percent)\n"); 151: printf(" user nice sys idle iowt iact"); 152: for (i=0; i <= LSTDRV; i++) 153: printf(" dk%ds",i); 154: for ( ; i < ndisk; i++) 155: printf(" dk%dx",i); 156: printf("\n"); 157: } 158: if (bflg && !oflg) { 159: printf(" BUFFER CACHE USAGE\n"); 160: printf("read reada cache write\n"); 161: } 162: 163: if (uflg && !oflg) { 164: printf(" UNIBUS MAP USAGE\n"); 165: printf("requests buffer remaps raw i/o pages allocation failures\n"); 166: } 167: 168: loop: 169: if (bflg) { 170: biostats(); 171: goto contin; 172: } 173: 174: if (uflg) { 175: unibusstats(); 176: goto contin; 177: } 178: lseek(mf, (long)nl[X_DKBUSY].n_value, 0); 179: read(mf, (char *)&(s.busy), sizeof (s.busy)); 180: lseek(mf, (long)nl[X_SYTIME].n_value, 0); 181: read(mf, (char *)&(s.sy_time), sizeof (s.sy_time)); 182: lseek(mf, (long)nl[X_DKTIME].n_value, 0); 183: read(mf, (char *)&(s.dk_time), (1 << ndisk) * sizeof (s.dk_time[0])); 184: lseek(mf, (long)nl[X_DKNUMB].n_value, 0); 185: read(mf, (char *)&(s.numb), ndisk * sizeof (s.numb[0])); 186: lseek(mf, (long)nl[X_DKWDS].n_value, 0); 187: read(mf, (char *)&(s.wds), ndisk * sizeof (s.wds[0])); 188: lseek(mf, (long)nl[X_TIN].n_value, 0); 189: read(mf, (char *)&(s.tin), sizeof (s.tin)); 190: lseek(mf, (long)nl[X_TOUT].n_value, 0); 191: read(mf, (char *)&(s.tout), sizeof (s.tout)); 192: etime = 0; 193: for(i=0; i < 8; i++) { 194: t = s.sy_time[i]; 195: s.sy_time[i] -= s1.sy_time[i]; 196: s1.sy_time[i] = t; 197: etime += s.sy_time[i]; 198: } 199: if(etime == 0.) 200: etime = 1.; 201: for(i=0; i < (1 << ndisk); i++) { 202: t = s.dk_time[i]; 203: s.dk_time[i] -= s1.dk_time[i]; 204: s1.dk_time[i] = t; 205: } 206: for(i=0; i < ndisk; i++) { 207: t = s.numb[i]; 208: s.numb[i] -= s1.numb[i]; 209: s1.numb[i] = t; 210: t = s.wds[i]; 211: s.wds[i] -= s1.wds[i]; 212: s1.wds[i] = t; 213: } 214: t = s.tin; 215: s.tin -= s1.tin; 216: s1.tin = t; 217: t = s.tout; 218: s.tout -= s1.tout; 219: s1.tout = t; 220: 221: if(oflg && skip) 222: { 223: skip =0; 224: goto contin; 225: } 226: if (dflg) { 227: long tm; 228: time(&tm); 229: printf("%s", ctime(&tm)); 230: } 231: if (aflg) 232: printf("%.2f minutes total\n", etime/3600); 233: if (sflg) { 234: stats2(etime); 235: goto contin; 236: } 237: if (iflg) { 238: stats3(etime); 239: goto contin; 240: } 241: etime /= 60.; 242: f1 = s.tin; 243: f2 = s.tout; 244: printf(" %3.0f", f1/etime); 245: printf(" %3.0f", f2/etime); 246: for(i=0; i<ndisk; i++) 247: stats(i); 248: for(i=0; i<4; i++) 249: stat1(i); 250: printf("\n"); 251: contin: 252: --iter; 253: if(iter) 254: if(argc > 1) { 255: sleep(atoi(argv[1])); 256: goto loop; 257: } 258: } 259: 260: stats(dn) 261: { 262: register i; 263: double f1, f2, f3; 264: double f4, f5, f6; 265: long t; 266: 267: t = 0; 268: for(i=0; i < (1<<ndisk); i++) 269: if(i & (1<<dn)) 270: t += s.dk_time[i]; 271: f1 = t; 272: f1 = f1/60.; 273: f2 = s.numb[dn]; 274: if(f2 == 0.) { 275: if(dn>LSTDRV) 276: printf(" %4.0f %4.1f %4.1f", 0.0, 0.0, 0.0); 277: else 278: printf(" %4.0f %4.1f", 0.0, 0.0); 279: return; 280: } 281: f3 = s.wds[dn]; 282: f3 = f3*32.; 283: f4 = xf[dn]; 284: f4 = f4*1.0e-6; 285: f5 = f1 - f4*f3; 286: f6 = f1 - f5; 287: printf(" %4.0f", f2/etime); 288: printf(" %4.1f", f5*1000./f2); 289: if(dn >LSTDRV) 290: printf(" %4.1f", f6*1000./f2); /* no xfer time for seeks */ 291: } 292: 293: stat1(o) 294: { 295: double f; 296: 297: f = s.sy_time[2*o] +s.sy_time[2*o+1]; 298: printf(" %3.0f", f*(100./60.)/etime); 299: } 300: 301: stats2(t) 302: double t; 303: { 304: register i, j; 305: 306: t /= 100.; 307: printf("sy_time: "); 308: for (j=0; j<8; j++) 309: printf("%6.2f ", s.sy_time[j]/t); 310: printf("\ndk_time: "); 311: for (j=0; j < (1<<ndisk); j++) { 312: printf("%6.2f ", s.dk_time[j]); 313: if (j%8 == 7) 314: printf("\n "); 315: } 316: printf("\ndk_numb: "); 317: for(i=0; i<ndisk; i++) 318: printf("%12D",s.numb[i]); 319: printf("\ndk_wds: "); 320: for(i=0; i<ndisk; i++) 321: printf("%12D",s.wds[i]); 322: printf("\n\n"); 323: } 324: 325: stats3(t) 326: double t; 327: { 328: register i, j; 329: double sum; 330: 331: t /= 100; 332: sum = s.sy_time[0] + s.sy_time[1]; 333: printf(" %4.0f", sum/t); 334: sum = s.sy_time[2] + s.sy_time[3]; 335: printf(" %4.0f", sum/t); 336: sum = s.sy_time[4] + s.sy_time[5]; 337: printf(" %4.0f", sum/t); 338: sum = s.sy_time[6] + s.sy_time[7]; 339: printf(" %4.0f", sum/t); 340: printf(" %4.0f", s.sy_time[7]/t); 341: sum = s.sy_time[1] + s.sy_time[3] + s.sy_time[5] + s.sy_time[7]; 342: printf(" %4.0f", sum/t); 343: for (j=0; j < ndisk; j++) { 344: sum = 0; 345: for(i=0; i < (1<<ndisk); i++) 346: if(i & (01<<j)) 347: sum += s.dk_time[i]; 348: printf(" %4.0f", sum/t); 349: } 350: printf("\n"); 351: } 352: 353: biostats() 354: { 355: 356: if (nl[X_IOINFO].n_type == 0) { 357: printf("io_info not found in /unix namelist\n"); 358: exit(1); 359: } 360: lseek(mf,(long)nl[X_IOINFO].n_value, 0); 361: read(mf, (char *)&io_info, sizeof(io_info)); 362: printf("%D\t%D\t%D\t%D\n", 363: io_info.nread-io_delta.nread, io_info.nreada-io_delta.nreada, 364: io_info.ncache-io_delta.ncache, io_info.nwrite-io_delta.nwrite); 365: 366: io_delta = io_info; 367: } 368: 369: unibusstats() 370: { 371: if (nl[X_UBMETER].n_type == 0) { 372: printf("ub_meter not found in /unix name list\n"); 373: exit(1); 374: } 375: lseek(mf, (long)nl[X_UBMETER].n_value, 0); 376: read(mf, (char *) &ub_meter, sizeof(ub_meter)); 377: printf("%D\t\t%D\t\t%D\t\t%D\n", 378: ub_meter.ub_requests - ub_delta.ub_requests, 379: ub_meter.ub_remaps - ub_delta.ub_remaps, 380: ub_meter.ub_pages - ub_delta.ub_pages, 381: ub_meter.ub_failures - ub_delta.ub_failures 382: ); 383: ub_delta = ub_meter; 384: }