1: #ifndef lint 2: static char *sccsid = "@(#)iostat.c 4.13 (Berkeley) 85/04/25"; 3: #endif 4: 5: /* 6: * iostat 7: */ 8: #include <stdio.h> 9: #include <ctype.h> 10: #include <nlist.h> 11: #include <signal.h> 12: 13: #include <sys/types.h> 14: #include <sys/file.h> 15: #include <sys/buf.h> 16: #include <sys/dk.h> 17: 18: struct nlist nl[] = { 19: { "_dk_busy" }, 20: #define X_DK_BUSY 0 21: { "_dk_time" }, 22: #define X_DK_TIME 1 23: { "_dk_xfer" }, 24: #define X_DK_XFER 2 25: { "_dk_wds" }, 26: #define X_DK_WDS 3 27: { "_tk_nin" }, 28: #define X_TK_NIN 4 29: { "_tk_nout" }, 30: #define X_TK_NOUT 5 31: { "_dk_seek" }, 32: #define X_DK_SEEK 6 33: { "_cp_time" }, 34: #define X_CP_TIME 7 35: { "_dk_mspw" }, 36: #define X_DK_MSPW 8 37: { "_hz" }, 38: #define X_HZ 9 39: { "_phz" }, 40: #define X_PHZ 10 41: { "_dk_ndrive" }, 42: #define X_DK_NDRIVE 11 43: #ifdef vax 44: { "_mbdinit" }, 45: #define X_MBDINIT 12 46: { "_ubdinit" }, 47: #define X_UBDINIT 13 48: #endif 49: { 0 }, 50: }; 51: 52: char **dr_name; 53: int *dr_select; 54: float *dk_mspw; 55: int dk_ndrive; 56: int ndrives = 0; 57: #ifdef vax 58: char *defdrives[] = { "hp0", "hp1", "hp2", 0 }; 59: #else 60: char *defdrives[] = { 0 }; 61: #endif 62: 63: struct { 64: int dk_busy; 65: long cp_time[CPUSTATES]; 66: long *dk_time; 67: long *dk_wds; 68: long *dk_seek; 69: long *dk_xfer; 70: long tk_nin; 71: long tk_nout; 72: } s, s1; 73: 74: int mf; 75: int hz; 76: int phz; 77: double etime; 78: int tohdr = 1; 79: int printhdr(); 80: 81: main(argc, argv) 82: char *argv[]; 83: { 84: extern char *ctime(); 85: register i; 86: int iter, ndrives; 87: double f1, f2; 88: long t; 89: char *arg, **cp, name[6], buf[BUFSIZ]; 90: 91: nlist("/vmunix", nl); 92: if(nl[X_DK_BUSY].n_type == 0) { 93: printf("dk_busy not found in /vmunix namelist\n"); 94: exit(1); 95: } 96: mf = open("/dev/kmem", 0); 97: if(mf < 0) { 98: printf("cannot open /dev/kmem\n"); 99: exit(1); 100: } 101: iter = 0; 102: for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) 103: ; 104: if (nl[DK_NDRIVE].n_value == 0) { 105: printf("dk_ndrive undefined in system\n"); 106: exit(1); 107: } 108: lseek(mf, nl[X_DK_NDRIVE].n_value, L_SET); 109: read(mf, &dk_ndrive, sizeof (dk_ndrive)); 110: if (dk_ndrive <= 0) { 111: printf("dk_ndrive %d\n", dk_ndrive); 112: exit(1); 113: } 114: dr_select = (int *)calloc(dk_ndrive, sizeof (int)); 115: dr_name = (char **)calloc(dk_ndrive, sizeof (char *)); 116: dk_mspw = (float *)calloc(dk_ndrive, sizeof (float)); 117: #define allocate(e, t) \ 118: s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \ 119: s1./**/e = (t *)calloc(dk_ndrive, sizeof (t)); 120: allocate(dk_time, long); 121: allocate(dk_wds, long); 122: allocate(dk_seek, long); 123: allocate(dk_xfer, long); 124: for (arg = buf, i = 0; i < dk_ndrive; i++) { 125: dr_name[i] = arg; 126: sprintf(dr_name[i], "dk%d", i); 127: arg += strlen(dr_name[i]) + 1; 128: } 129: read_names(); 130: lseek(mf, (long)nl[X_HZ].n_value, L_SET); 131: read(mf, &hz, sizeof hz); 132: lseek(mf, (long)nl[X_PHZ].n_value, L_SET); 133: read(mf, &phz, sizeof phz); 134: if (phz) 135: hz = phz; 136: lseek(mf, (long)nl[X_DK_MSPW].n_value, L_SET); 137: read(mf, dk_mspw, dk_ndrive*sizeof (dk_mspw)); 138: /* 139: * Choose drives to be displayed. Priority 140: * goes to (in order) drives supplied as arguments, 141: * default drives. If everything isn't filled 142: * in and there are drives not taken care of, 143: * display the first few that fit. 144: */ 145: ndrives = 0; 146: while (argc > 0 && !isdigit(argv[0][0])) { 147: for (i = 0; i < dk_ndrive; i++) { 148: if (strcmp(dr_name[i], argv[0])) 149: continue; 150: dr_select[i] = 1; 151: ndrives++; 152: } 153: argc--, argv++; 154: } 155: for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 156: if (dr_select[i] || dk_mspw[i] == 0.0) 157: continue; 158: for (cp = defdrives; *cp; cp++) 159: if (strcmp(dr_name[i], *cp) == 0) { 160: dr_select[i] = 1; 161: ndrives++; 162: break; 163: } 164: } 165: for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 166: if (dr_select[i]) 167: continue; 168: dr_select[i] = 1; 169: ndrives++; 170: } 171: if (argc > 1) 172: iter = atoi(argv[1]); 173: signal(SIGCONT, printhdr); 174: loop: 175: if (--tohdr == 0) 176: printhdr(); 177: lseek(mf, (long)nl[X_DK_BUSY].n_value, L_SET); 178: read(mf, &s.dk_busy, sizeof s.dk_busy); 179: lseek(mf, (long)nl[X_DK_TIME].n_value, L_SET); 180: read(mf, s.dk_time, dk_ndrive*sizeof (long)); 181: lseek(mf, (long)nl[X_DK_XFER].n_value, L_SET); 182: read(mf, s.dk_xfer, dk_ndrive*sizeof (long)); 183: lseek(mf, (long)nl[X_DK_WDS].n_value, L_SET); 184: read(mf, s.dk_wds, dk_ndrive*sizeof (long)); 185: lseek(mf, (long)nl[X_DK_SEEK].n_value, L_SET); 186: read(mf, s.dk_seek, dk_ndrive*sizeof (long)); 187: lseek(mf, (long)nl[X_TK_NIN].n_value, L_SET); 188: read(mf, &s.tk_nin, sizeof s.tk_nin); 189: lseek(mf, (long)nl[X_TK_NOUT].n_value, L_SET); 190: read(mf, &s.tk_nout, sizeof s.tk_nout); 191: lseek(mf, (long)nl[X_CP_TIME].n_value, L_SET); 192: read(mf, s.cp_time, sizeof s.cp_time); 193: for (i = 0; i < dk_ndrive; i++) { 194: if (!dr_select[i]) 195: continue; 196: #define X(fld) t = s.fld[i]; s.fld[i] -= s1.fld[i]; s1.fld[i] = t 197: X(dk_xfer); X(dk_seek); X(dk_wds); X(dk_time); 198: } 199: t = s.tk_nin; s.tk_nin -= s1.tk_nin; s1.tk_nin = t; 200: t = s.tk_nout; s.tk_nout -= s1.tk_nout; s1.tk_nout = t; 201: etime = 0; 202: for(i=0; i<CPUSTATES; i++) { 203: X(cp_time); 204: etime += s.cp_time[i]; 205: } 206: if (etime == 0.0) 207: etime = 1.0; 208: etime /= (float) hz; 209: printf("%4.0f%5.0f", s.tk_nin/etime, s.tk_nout/etime); 210: for (i=0; i<dk_ndrive; i++) 211: if (dr_select[i]) 212: stats(i); 213: for (i=0; i<CPUSTATES; i++) 214: stat1(i); 215: printf("\n"); 216: fflush(stdout); 217: contin: 218: if (--iter && argc > 0) { 219: sleep(atoi(argv[0])); 220: goto loop; 221: } 222: } 223: 224: printhdr() 225: { 226: register int i; 227: 228: printf(" tty"); 229: for (i = 0; i < dk_ndrive; i++) 230: if (dr_select[i]) 231: printf(" %3.3s ", dr_name[i]); 232: printf(" cpu\n"); 233: printf(" tin tout"); 234: for (i = 0; i < dk_ndrive; i++) 235: if (dr_select[i]) 236: printf(" bps tps msps "); 237: printf(" us ni sy id\n"); 238: tohdr = 19; 239: } 240: 241: stats(dn) 242: { 243: register i; 244: double atime, words, xtime, itime; 245: 246: if (dk_mspw[dn] == 0.0) { 247: printf("%4.0f%4.0f%5.1f ", 0.0, 0.0, 0.0); 248: return; 249: } 250: atime = s.dk_time[dn]; 251: atime /= (float) hz; 252: words = s.dk_wds[dn]*32.0; /* number of words transferred */ 253: xtime = dk_mspw[dn]*words; /* transfer time */ 254: itime = atime - xtime; /* time not transferring */ 255: if (xtime < 0) 256: itime += xtime, xtime = 0; 257: if (itime < 0) 258: xtime += itime, itime = 0; 259: printf("%4.0f", words/512/etime); 260: printf("%4.0f", s.dk_xfer[dn]/etime); 261: printf("%5.1f ", 262: s.dk_seek[dn] ? itime*1000./s.dk_seek[dn] : 0.0); 263: } 264: 265: stat1(o) 266: { 267: register i; 268: double time; 269: 270: time = 0; 271: for(i=0; i<CPUSTATES; i++) 272: time += s.cp_time[i]; 273: if (time == 0.0) 274: time = 1.0; 275: printf("%3.0f", 100.*s.cp_time[o]/time); 276: } 277: 278: #define steal(where, var) \ 279: lseek(mf, where, L_SET); read(mf, &var, sizeof var); 280: 281: #ifdef vax 282: #include <vaxuba/ubavar.h> 283: #include <vaxmba/mbavar.h> 284: 285: read_names() 286: { 287: struct mba_device mdev; 288: register struct mba_device *mp; 289: struct mba_driver mdrv; 290: short two_char; 291: char *cp = (char *) &two_char; 292: struct uba_device udev, *up; 293: struct uba_driver udrv; 294: 295: mp = (struct mba_device *) nl[X_MBDINIT].n_value; 296: up = (struct uba_device *) nl[X_UBDINIT].n_value; 297: if (up == 0) { 298: fprintf(stderr, "iostat: Disk init info not in namelist\n"); 299: exit(1); 300: } 301: if (mp) for (;;) { 302: steal(mp++, mdev); 303: if (mdev.mi_driver == 0) 304: break; 305: if (mdev.mi_dk < 0 || mdev.mi_alive == 0) 306: continue; 307: steal(mdev.mi_driver, mdrv); 308: steal(mdrv.md_dname, two_char); 309: sprintf(dr_name[mdev.mi_dk], "%c%c%d", 310: cp[0], cp[1], mdev.mi_unit); 311: } 312: if (up) for (;;) { 313: steal(up++, udev); 314: if (udev.ui_driver == 0) 315: break; 316: if (udev.ui_dk < 0 || udev.ui_alive == 0) 317: continue; 318: steal(udev.ui_driver, udrv); 319: steal(udrv.ud_dname, two_char); 320: sprintf(dr_name[udev.ui_dk], "%c%c%d", 321: cp[0], cp[1], udev.ui_unit); 322: } 323: } 324: #endif