1 static char *sccsid = "@(#)iostat.c 4.6 (Berkeley) 81/04/21"; 2 /* 3 * iostat 4 */ 5 #include <stdio.h> 6 #include <nlist.h> 7 #include <sys/types.h> 8 #include <sys/buf.h> 9 #include <sys/ubavar.h> 10 #include <sys/mbavar.h> 11 #include <sys/dk.h> 12 13 struct nlist nl[] = { 14 { "_dk_busy" }, 15 #define X_DK_BUSY 0 16 { "_dk_time" }, 17 #define X_DK_TIME 1 18 { "_dk_xfer" }, 19 #define X_DK_XFER 2 20 { "_dk_wds" }, 21 #define X_DK_WDS 3 22 { "_tk_nin" }, 23 #define X_TK_NIN 4 24 { "_tk_nout" }, 25 #define X_TK_NOUT 5 26 { "_dk_seek" }, 27 #define X_DK_SEEK 6 28 { "_cp_time" }, 29 #define X_CP_TIME 7 30 { "_dk_mspw" }, 31 #define X_DK_MSPW 8 32 { "_mbdinit" }, 33 #define X_MBDINIT 9 34 { "_ubdinit" }, 35 #define X_UBDINIT 10 36 { 0 }, 37 }; 38 39 char dr_name[DK_NDRIVE][10]; 40 41 struct 42 { 43 int dk_busy; 44 long cp_time[CPUSTATES]; 45 long dk_time[DK_NDRIVE]; 46 long dk_wds[DK_NDRIVE]; 47 long dk_seek[DK_NDRIVE]; 48 long dk_xfer[DK_NDRIVE]; 49 float dk_mspw[DK_NDRIVE]; 50 long tk_nin; 51 long tk_nout; 52 } s, s1; 53 54 int mf; 55 double etime; 56 57 main(argc, argv) 58 char *argv[]; 59 { 60 extern char *ctime(); 61 register i; 62 int iter; 63 double f1, f2; 64 long t; 65 int tohdr = 1; 66 67 nlist("/vmunix", nl); 68 if(nl[X_DK_BUSY].n_type == 0) { 69 printf("dk_busy not found in /vmunix namelist\n"); 70 exit(1); 71 } 72 mf = open("/dev/kmem", 0); 73 if(mf < 0) { 74 printf("cannot open /dev/kmem\n"); 75 exit(1); 76 } 77 iter = 0; 78 while (argc>1&&argv[1][0]=='-') { 79 argc--; 80 argv++; 81 } 82 lseek(mf, (long)nl[X_DK_MSPW].n_value, 0); 83 read(mf, s.dk_mspw, sizeof s.dk_mspw); 84 for (i = 0; i < DK_NDRIVE; i++) 85 sprintf(dr_name[i], "dk%d", i); 86 read_names(); 87 if(argc > 2) 88 iter = atoi(argv[2]); 89 loop: 90 if (--tohdr == 0) { 91 printf(" tty"); 92 for (i = 0; i < DK_NDRIVE; i++) 93 if (s.dk_mspw[i] != 0.0) 94 printf(" %3.3s ", dr_name[i]); 95 printf(" cpu\n"); 96 printf(" tin tout"); 97 for (i = 0; i < DK_NDRIVE; i++) 98 if (s.dk_mspw[i] != 0.0) 99 printf(" sps tps msps "); 100 printf(" us ni sy id\n"); 101 tohdr = 19; 102 } 103 lseek(mf, (long)nl[X_DK_BUSY].n_value, 0); 104 read(mf, &s.dk_busy, sizeof s.dk_busy); 105 lseek(mf, (long)nl[X_DK_TIME].n_value, 0); 106 read(mf, s.dk_time, sizeof s.dk_time); 107 lseek(mf, (long)nl[X_DK_XFER].n_value, 0); 108 read(mf, s.dk_xfer, sizeof s.dk_xfer); 109 lseek(mf, (long)nl[X_DK_WDS].n_value, 0); 110 read(mf, s.dk_wds, sizeof s.dk_wds); 111 lseek(mf, (long)nl[X_TK_NIN].n_value, 0); 112 read(mf, &s.tk_nin, sizeof s.tk_nin); 113 lseek(mf, (long)nl[X_TK_NOUT].n_value, 0); 114 read(mf, &s.tk_nout, sizeof s.tk_nout); 115 lseek(mf, (long)nl[X_DK_SEEK].n_value, 0); 116 read(mf, s.dk_seek, sizeof s.dk_seek); 117 lseek(mf, (long)nl[X_CP_TIME].n_value, 0); 118 read(mf, s.cp_time, sizeof s.cp_time); 119 lseek(mf, (long)nl[X_DK_MSPW].n_value, 0); 120 read(mf, s.dk_mspw, sizeof s.dk_mspw); 121 for (i = 0; i < DK_NDRIVE; i++) { 122 #define X(fld) t = s.fld[i]; s.fld[i] -= s1.fld[i]; s1.fld[i] = t 123 X(dk_xfer); X(dk_seek); X(dk_wds); X(dk_time); 124 } 125 t = s.tk_nin; s.tk_nin -= s1.tk_nin; s1.tk_nin = t; 126 t = s.tk_nout; s.tk_nout -= s1.tk_nout; s1.tk_nout = t; 127 etime = 0; 128 for(i=0; i<CPUSTATES; i++) { 129 X(cp_time); 130 etime += s.cp_time[i]; 131 } 132 if (etime == 0.0) 133 etime = 1.0; 134 etime /= 60.0; 135 printf("%4.0f%5.0f", s.tk_nin/etime, s.tk_nout/etime); 136 for (i=0; i<DK_NDRIVE; i++) 137 if (s.dk_mspw[i] != 0.0) 138 stats(i); 139 for (i=0; i<CPUSTATES; i++) 140 stat1(i); 141 printf("\n"); 142 contin: 143 --iter; 144 if(iter) 145 if(argc > 1) { 146 sleep(atoi(argv[1])); 147 goto loop; 148 } 149 } 150 151 stats(dn) 152 { 153 register i; 154 double atime, words, xtime, itime; 155 156 if (s.dk_mspw[dn] == 0.0) { 157 printf("%4.0f%4.0f%5.1f ", 0.0, 0.0, 0.0); 158 return; 159 } 160 atime = s.dk_time[dn]; 161 atime /= 60.0; 162 words = s.dk_wds[dn]*32.0; /* number of words transferred */ 163 xtime = s.dk_mspw[dn]*words; /* transfer time */ 164 itime = atime - xtime; /* time not transferring */ 165 /* 166 printf("\ndn %d, words %8.2f, atime %6.2f, xtime %6.2f, itime %6.2f\n", 167 dn, words, atime, xtime, itime); 168 */ 169 if (xtime < 0) 170 itime += xtime, xtime = 0; 171 if (itime < 0) 172 xtime += itime, itime = 0; 173 printf("%4.0f", s.dk_seek[dn]/etime); 174 printf("%4.0f", s.dk_xfer[dn]/etime); 175 printf("%5.1f ", 176 s.dk_seek[dn] ? itime*1000./s.dk_seek[dn] : 0.0); 177 /* 178 printf("%4.1f", 179 s.dk_xfer[dn] ? xtime*1000./s.dk_xfer[dn] : 0.0); 180 */ 181 } 182 183 stat1(o) 184 { 185 register i; 186 double time; 187 188 time = 0; 189 for(i=0; i<CPUSTATES; i++) 190 time += s.cp_time[i]; 191 if (time == 0.0) 192 time = 1.0; 193 printf("%3.0f", 100*s.cp_time[o]/time); 194 } 195 196 /* 197 * Read the drive names out of kmem. 198 * ARGH ARGH ARGH ARGH !!!!!!!!!!!! 199 */ 200 201 #define steal(where, var) lseek(mf, where, 0); read(mf, &var, sizeof var); 202 read_names() 203 { 204 struct mba_device mdev; 205 register struct mba_device *mp; 206 struct mba_driver mdrv; 207 short two_char; 208 char *cp = (char *) &two_char; 209 struct uba_device udev, *up; 210 struct uba_driver udrv; 211 212 mp = (struct mba_device *) nl[X_MBDINIT].n_value; 213 up = (struct uba_device *) nl[X_UBDINIT].n_value; 214 if (up == 0) 215 { 216 fprintf(stderr, "iostat: Disk init info not in namelist\n"); 217 exit(1); 218 } 219 if (mp) 220 while(1) 221 { 222 steal(mp++, mdev); 223 if (mdev.mi_driver == 0) 224 break; 225 if (mdev.mi_dk < 0 || mdev.mi_alive == 0) 226 continue; 227 steal(mdev.mi_driver, mdrv); 228 steal(mdrv.md_dname, two_char); 229 sprintf(dr_name[mdev.mi_dk], "%c%c%d", cp[0], cp[1], mdev.mi_unit); 230 } 231 while(1) 232 { 233 steal(up++, udev); 234 if (udev.ui_driver == 0) 235 break; 236 if (udev.ui_dk < 0 || udev.ui_alive == 0) 237 continue; 238 steal(udev.ui_driver, udrv); 239 steal(udrv.ud_dname, two_char); 240 sprintf(dr_name[udev.ui_dk], "%c%c%d", cp[0], cp[1], udev.ui_unit); 241 } 242 } 243