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