iostat.c revision 1.72 1 1.72 mrg /* $NetBSD: iostat.c,v 1.72 2023/10/30 19:43:33 mrg Exp $ */
2 1.9 thorpej
3 1.9 thorpej /*
4 1.9 thorpej * Copyright (c) 1996 John M. Vinopal
5 1.9 thorpej * All rights reserved.
6 1.9 thorpej *
7 1.9 thorpej * Redistribution and use in source and binary forms, with or without
8 1.9 thorpej * modification, are permitted provided that the following conditions
9 1.9 thorpej * are met:
10 1.9 thorpej * 1. Redistributions of source code must retain the above copyright
11 1.9 thorpej * notice, this list of conditions and the following disclaimer.
12 1.9 thorpej * 2. Redistributions in binary form must reproduce the above copyright
13 1.9 thorpej * notice, this list of conditions and the following disclaimer in the
14 1.9 thorpej * documentation and/or other materials provided with the distribution.
15 1.9 thorpej * 3. All advertising materials mentioning features or use of this software
16 1.9 thorpej * must display the following acknowledgement:
17 1.9 thorpej * This product includes software developed for the NetBSD Project
18 1.9 thorpej * by John M. Vinopal.
19 1.9 thorpej * 4. The name of the author may not be used to endorse or promote products
20 1.9 thorpej * derived from this software without specific prior written permission.
21 1.9 thorpej *
22 1.9 thorpej * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 1.9 thorpej * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 1.9 thorpej * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 1.9 thorpej * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 1.9 thorpej * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 1.9 thorpej * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 1.9 thorpej * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 1.9 thorpej * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 1.9 thorpej * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 1.9 thorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 1.9 thorpej * SUCH DAMAGE.
33 1.9 thorpej */
34 1.8 thorpej
35 1.1 cgd /*-
36 1.6 cgd * Copyright (c) 1986, 1991, 1993
37 1.9 thorpej * The Regents of the University of California. All rights reserved.
38 1.1 cgd *
39 1.1 cgd * Redistribution and use in source and binary forms, with or without
40 1.1 cgd * modification, are permitted provided that the following conditions
41 1.1 cgd * are met:
42 1.1 cgd * 1. Redistributions of source code must retain the above copyright
43 1.1 cgd * notice, this list of conditions and the following disclaimer.
44 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
45 1.1 cgd * notice, this list of conditions and the following disclaimer in the
46 1.1 cgd * documentation and/or other materials provided with the distribution.
47 1.40 agc * 3. Neither the name of the University nor the names of its contributors
48 1.1 cgd * may be used to endorse or promote products derived from this software
49 1.1 cgd * without specific prior written permission.
50 1.1 cgd *
51 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 1.1 cgd * SUCH DAMAGE.
62 1.1 cgd */
63 1.1 cgd
64 1.12 lukem #include <sys/cdefs.h>
65 1.1 cgd #ifndef lint
66 1.52 lukem __COPYRIGHT("@(#) Copyright (c) 1986, 1991, 1993\
67 1.52 lukem The Regents of the University of California. All rights reserved.");
68 1.1 cgd #endif /* not lint */
69 1.1 cgd
70 1.1 cgd #ifndef lint
71 1.8 thorpej #if 0
72 1.11 mrg static char sccsid[] = "@(#)iostat.c 8.3 (Berkeley) 4/28/95";
73 1.8 thorpej #else
74 1.72 mrg __RCSID("$NetBSD: iostat.c,v 1.72 2023/10/30 19:43:33 mrg Exp $");
75 1.8 thorpej #endif
76 1.1 cgd #endif /* not lint */
77 1.1 cgd
78 1.11 mrg #include <sys/types.h>
79 1.37 simonb #include <sys/ioctl.h>
80 1.22 thorpej #include <sys/sched.h>
81 1.9 thorpej #include <sys/time.h>
82 1.6 cgd
83 1.6 cgd #include <err.h>
84 1.6 cgd #include <ctype.h>
85 1.6 cgd #include <signal.h>
86 1.1 cgd #include <stdio.h>
87 1.1 cgd #include <stdlib.h>
88 1.1 cgd #include <string.h>
89 1.6 cgd #include <unistd.h>
90 1.54 jakllsch #include <math.h>
91 1.62 mrg #include <fnmatch.h>
92 1.1 cgd
93 1.49 blymn #include "drvstats.h"
94 1.1 cgd
95 1.60 joerg int hz;
96 1.60 joerg static int reps, interval;
97 1.9 thorpej static int todo = 0;
98 1.38 simonb static int defdrives;
99 1.37 simonb static int winlines = 20;
100 1.38 simonb static int wincols = 80;
101 1.9 thorpej
102 1.69 kre static int *order, ordersize;
103 1.69 kre
104 1.69 kre static char Line_Marker[] = "________________________________________________";
105 1.69 kre
106 1.54 jakllsch #define MAX(a,b) (((a)>(b))?(a):(b))
107 1.69 kre #define MIN(a,b) (((a)<(b))?(a):(b))
108 1.54 jakllsch
109 1.36 simonb #define ISSET(x, a) ((x) & (a))
110 1.70 mrg #define SHOW_CPU (1u<<0)
111 1.70 mrg #define SHOW_TTY (1u<<1)
112 1.70 mrg #define SHOW_STATS_1 (1u<<2)
113 1.70 mrg #define SHOW_STATS_2 (1u<<3)
114 1.70 mrg #define SHOW_STATS_3 (1u<<4)
115 1.70 mrg #define SHOW_STATS_X (1u<<5)
116 1.70 mrg #define SHOW_STATS_Y (1u<<6)
117 1.70 mrg #define SHOW_UPDATES (1u<<7)
118 1.70 mrg #define SHOW_TOTALS (1u<<8)
119 1.70 mrg #define SHOW_NEW_TOTALS (1u<<9)
120 1.70 mrg #define SUPPRESS_ZERO (1u<<10)
121 1.69 kre
122 1.69 kre #define SHOW_STATS_ALL (SHOW_STATS_1 | SHOW_STATS_2 | \
123 1.70 mrg SHOW_STATS_3 | SHOW_STATS_X | SHOW_STATS_Y)
124 1.69 kre
125 1.69 kre /*
126 1.69 kre * Decide how many screen columns each output statistic is given
127 1.69 kre * (these are determined empirically ("looks good to me") and likely
128 1.69 kre * will require changes from time to time as technology advances).
129 1.69 kre *
130 1.69 kre * The odd "+ N" at the end of the summary (total width of stat) definition
131 1.69 kre * allows for the gaps between the columns, and is (#data cols - 1).
132 1.69 kre * So, tty stats have "in" and "out", 2 columns, so there is 1 extra space,
133 1.69 kre * whereas the cpu stats have 5 columns, so 4 extra spaces (etc).
134 1.69 kre */
135 1.69 kre #define LAYOUT_TTY_IN 4 /* tty input in last interval */
136 1.69 kre #define LAYOUT_TTY_TIN 7 /* tty input forever */
137 1.69 kre #define LAYOUT_TTY_OUT 5 /* tty output in last interval */
138 1.69 kre #define LAYOUT_TTY_TOUT 10 /* tty output forever */
139 1.69 kre #define LAYOUT_TTY (((todo & SHOW_TOTALS) \
140 1.69 kre ? (LAYOUT_TTY_TIN + LAYOUT_TTY_TOUT) \
141 1.69 kre : (LAYOUT_TTY_IN + LAYOUT_TTY_OUT)) + 1)
142 1.69 kre #define LAYOUT_TTY_GAP 0 /* always starts at left margin */
143 1.69 kre
144 1.69 kre #define LAYOUT_CPU_USER 2
145 1.69 kre #define LAYOUT_CPU_NICE 2
146 1.69 kre #define LAYOUT_CPU_SYS 2
147 1.69 kre #define LAYOUT_CPU_INT 2
148 1.69 kre #define LAYOUT_CPU_IDLE 3
149 1.69 kre #define LAYOUT_CPU (LAYOUT_CPU_USER + LAYOUT_CPU_NICE + LAYOUT_CPU_SYS + \
150 1.69 kre LAYOUT_CPU_INT + LAYOUT_CPU_IDLE + 4)
151 1.69 kre #define LAYOUT_CPU_GAP 2
152 1.69 kre
153 1.69 kre /* used for: w/o TOTALS w TOTALS */
154 1.69 kre #define LAYOUT_DRIVE_1_XSIZE 5 /* KB/t KB/t */
155 1.69 kre #define LAYOUT_DRIVE_1_RATE 6 /* t/s */
156 1.69 kre #define LAYOUT_DRIVE_1_XFER 10 /* xfr */
157 1.69 kre #define LAYOUT_DRIVE_1_SPEED 5 /* MB/s */
158 1.69 kre #define LAYOUT_DRIVE_1_VOLUME 8 /* MB */
159 1.69 kre #define LAYOUT_DRIVE_1_INCR 5 /* (inc) */
160 1.69 kre
161 1.69 kre #define LAYOUT_DRIVE_2_XSIZE 7 /* KB */
162 1.69 kre #define LAYOUT_DRIVE_2_VOLUME 11 /* KB */
163 1.69 kre #define LAYOUT_DRIVE_2_XFR 7 /* xfr */
164 1.69 kre #define LAYOUT_DRIVE_2_TXFR 10 /* xfr */
165 1.69 kre #define LAYOUT_DRIVE_2_INCR 5 /* (inc) */
166 1.69 kre #define LAYOUT_DRIVE_2_TBUSY 9 /* time */
167 1.69 kre #define LAYOUT_DRIVE_2_BUSY 5 /* time */
168 1.69 kre
169 1.70 mrg /* Layout 3 uses same sizes as 2, but with MB. */
170 1.70 mrg
171 1.69 kre #define LAYOUT_DRIVE_1 (LAYOUT_DRIVE_1_XSIZE + ((todo & SHOW_TOTALS) ? \
172 1.69 kre (LAYOUT_DRIVE_1_XFER + LAYOUT_DRIVE_1_VOLUME + \
173 1.69 kre ((todo&SHOW_UPDATES)? 2*LAYOUT_DRIVE_1_INCR+2 :0)) \
174 1.69 kre : (LAYOUT_DRIVE_1_RATE + LAYOUT_DRIVE_1_SPEED)) + 3)
175 1.69 kre #define LAYOUT_DRIVE_2 (((todo & SHOW_TOTALS) ? (LAYOUT_DRIVE_2_VOLUME + \
176 1.69 kre LAYOUT_DRIVE_2_TXFR + LAYOUT_DRIVE_2_TBUSY + \
177 1.69 kre ((todo&SHOW_UPDATES)? 2*LAYOUT_DRIVE_2_INCR+2 : 0))\
178 1.69 kre : (LAYOUT_DRIVE_2_XSIZE + LAYOUT_DRIVE_2_XFR + \
179 1.69 kre LAYOUT_DRIVE_2_BUSY)) + 3)
180 1.70 mrg #define LAYOUT_DRIVE_3 (((todo & SHOW_TOTALS) ? (LAYOUT_DRIVE_2_VOLUME + \
181 1.70 mrg LAYOUT_DRIVE_2_TBUSY + \
182 1.70 mrg ((todo&SHOW_UPDATES)? 2*LAYOUT_DRIVE_2_INCR+1 : 0))\
183 1.70 mrg : (LAYOUT_DRIVE_2_XSIZE + LAYOUT_DRIVE_2_BUSY)) + 2)
184 1.69 kre
185 1.69 kre #define LAYOUT_DRIVE_GAP 0 /* Gap included in column, always present */
186 1.69 kre
187 1.69 kre /* TODO: X & Y stats layouts */
188 1.9 thorpej
189 1.23 simonb static void cpustats(void);
190 1.65 mlelstv static double drive_time(double, int);
191 1.69 kre static void drive_stats(int, double);
192 1.69 kre static void drive_stats2(int, double);
193 1.69 kre static void drive_statsx(int, double);
194 1.69 kre static void drive_statsy(int, double);
195 1.64 mlelstv static void drive_statsy_io(double, double, double);
196 1.64 mlelstv static void drive_statsy_q(double, double, double, double, double, double);
197 1.39 mrg static void sig_header(int);
198 1.39 mrg static volatile int do_header;
199 1.69 kre static void header(int);
200 1.60 joerg __dead static void usage(void);
201 1.69 kre static void display(int);
202 1.68 kre static int selectdrives(int, char *[], int);
203 1.23 simonb
204 1.6 cgd int
205 1.23 simonb main(int argc, char *argv[])
206 1.1 cgd {
207 1.66 mrg int ch, hdrcnt, hdroffset, ndrives, lines;
208 1.28 mycroft struct timespec tv;
209 1.37 simonb struct ttysize ts;
210 1.69 kre long width = -1, height = -1;
211 1.69 kre char *ep;
212 1.9 thorpej
213 1.69 kre #if 0 /* -i and -u are not currently (sanely) implementable */
214 1.70 mrg while ((ch = getopt(argc, argv, "Cc:dDH:iITuw:W:xXyz")) != -1)
215 1.69 kre #else
216 1.70 mrg while ((ch = getopt(argc, argv, "Cc:dDH:ITw:W:xXyz")) != -1)
217 1.69 kre #endif
218 1.31 enami switch (ch) {
219 1.1 cgd case 'c':
220 1.6 cgd if ((reps = atoi(optarg)) <= 0)
221 1.6 cgd errx(1, "repetition count <= 0.");
222 1.1 cgd break;
223 1.9 thorpej case 'C':
224 1.9 thorpej todo |= SHOW_CPU;
225 1.9 thorpej break;
226 1.9 thorpej case 'd':
227 1.15 lukem todo &= ~SHOW_STATS_ALL;
228 1.9 thorpej todo |= SHOW_STATS_1;
229 1.9 thorpej break;
230 1.9 thorpej case 'D':
231 1.15 lukem todo &= ~SHOW_STATS_ALL;
232 1.9 thorpej todo |= SHOW_STATS_2;
233 1.9 thorpej break;
234 1.69 kre case 'H':
235 1.69 kre height = strtol(optarg, &ep, 10);
236 1.69 kre if (height < 0 || *ep != '\0')
237 1.69 kre errx(1, "bad height (-H) value.");
238 1.69 kre height += 2; /* magic, but needed to be sane */
239 1.69 kre break;
240 1.69 kre #if 0
241 1.69 kre case 'i':
242 1.69 kre todo |= SHOW_TOTALS | SHOW_NEW_TOTALS;
243 1.69 kre break;
244 1.69 kre #endif
245 1.9 thorpej case 'I':
246 1.9 thorpej todo |= SHOW_TOTALS;
247 1.9 thorpej break;
248 1.9 thorpej case 'T':
249 1.9 thorpej todo |= SHOW_TTY;
250 1.9 thorpej break;
251 1.69 kre #if 0
252 1.69 kre case 'u':
253 1.69 kre todo |= SHOW_UPDATES;
254 1.69 kre break;
255 1.69 kre #endif
256 1.1 cgd case 'w':
257 1.6 cgd if ((interval = atoi(optarg)) <= 0)
258 1.6 cgd errx(1, "interval <= 0.");
259 1.1 cgd break;
260 1.69 kre case 'W':
261 1.69 kre width = strtol(optarg, &ep, 10);
262 1.69 kre if (width < 0 || *ep != '\0')
263 1.69 kre errx(1, "bad width (-W) value.");
264 1.69 kre break;
265 1.15 lukem case 'x':
266 1.15 lukem todo &= ~SHOW_STATS_ALL;
267 1.15 lukem todo |= SHOW_STATS_X;
268 1.15 lukem break;
269 1.70 mrg case 'X':
270 1.70 mrg todo &= ~SHOW_STATS_ALL;
271 1.70 mrg todo |= SHOW_STATS_3;
272 1.70 mrg break;
273 1.64 mlelstv case 'y':
274 1.64 mlelstv todo &= ~SHOW_STATS_ALL;
275 1.64 mlelstv todo |= SHOW_STATS_Y;
276 1.64 mlelstv break;
277 1.69 kre case 'z':
278 1.69 kre todo |= SUPPRESS_ZERO;
279 1.69 kre break;
280 1.1 cgd case '?':
281 1.1 cgd default:
282 1.1 cgd usage();
283 1.1 cgd }
284 1.1 cgd argc -= optind;
285 1.1 cgd argv += optind;
286 1.1 cgd
287 1.15 lukem if (!ISSET(todo, SHOW_CPU | SHOW_TTY | SHOW_STATS_ALL))
288 1.9 thorpej todo |= SHOW_CPU | SHOW_TTY | SHOW_STATS_1;
289 1.15 lukem if (ISSET(todo, SHOW_STATS_X)) {
290 1.15 lukem todo &= ~(SHOW_CPU | SHOW_TTY | SHOW_STATS_ALL);
291 1.15 lukem todo |= SHOW_STATS_X;
292 1.15 lukem }
293 1.70 mrg if (ISSET(todo, SHOW_STATS_3)) {
294 1.70 mrg todo &= ~(SHOW_CPU | SHOW_TTY | SHOW_STATS_ALL);
295 1.70 mrg todo |= SHOW_STATS_3;
296 1.70 mrg }
297 1.64 mlelstv if (ISSET(todo, SHOW_STATS_Y)) {
298 1.64 mlelstv todo &= ~(SHOW_CPU | SHOW_TTY | SHOW_STATS_ALL | SHOW_TOTALS);
299 1.64 mlelstv todo |= SHOW_STATS_Y;
300 1.64 mlelstv }
301 1.6 cgd
302 1.38 simonb if (ioctl(STDOUT_FILENO, TIOCGSIZE, &ts) != -1) {
303 1.38 simonb if (ts.ts_lines)
304 1.38 simonb winlines = ts.ts_lines;
305 1.38 simonb if (ts.ts_cols)
306 1.38 simonb wincols = ts.ts_cols;
307 1.38 simonb }
308 1.38 simonb
309 1.69 kre if (height == -1) {
310 1.69 kre char *lns = getenv("LINES");
311 1.69 kre
312 1.69 kre if (lns == NULL || (height = strtol(lns, &ep, 10)) < 0 ||
313 1.69 kre *ep != '\0')
314 1.69 kre height = winlines;
315 1.69 kre }
316 1.69 kre winlines = height;
317 1.69 kre
318 1.69 kre if (width == -1) {
319 1.69 kre char *cols = getenv("COLUMNS");
320 1.69 kre
321 1.69 kre if (cols == NULL || (width = strtol(cols, &ep, 10)) < 0 ||
322 1.69 kre *ep != '\0')
323 1.69 kre width = wincols;
324 1.69 kre }
325 1.69 kre defdrives = width;
326 1.69 kre if (defdrives == 0) {
327 1.69 kre defdrives = 5000; /* anything absurdly big */
328 1.69 kre } else {
329 1.69 kre if (ISSET(todo, SHOW_CPU))
330 1.69 kre defdrives -= LAYOUT_CPU + LAYOUT_CPU_GAP;
331 1.69 kre if (ISSET(todo, SHOW_TTY))
332 1.69 kre defdrives -= LAYOUT_TTY + LAYOUT_TTY_GAP;
333 1.69 kre if (ISSET(todo, SHOW_STATS_2))
334 1.69 kre defdrives /= LAYOUT_DRIVE_2 + LAYOUT_DRIVE_GAP;
335 1.70 mrg if (ISSET(todo, SHOW_STATS_3))
336 1.70 mrg defdrives /= LAYOUT_DRIVE_3 + LAYOUT_DRIVE_GAP;
337 1.69 kre else
338 1.69 kre defdrives /= LAYOUT_DRIVE_1 + LAYOUT_DRIVE_GAP;
339 1.69 kre }
340 1.38 simonb
341 1.49 blymn drvinit(0);
342 1.48 dsl cpureadstats();
343 1.49 blymn drvreadstats();
344 1.69 kre ordersize = 0;
345 1.68 kre ndrives = selectdrives(argc, argv, 1);
346 1.34 enami if (ndrives == 0) {
347 1.49 blymn /* No drives are selected. No need to show drive stats. */
348 1.34 enami todo &= ~SHOW_STATS_ALL;
349 1.34 enami if (todo == 0)
350 1.34 enami errx(1, "no drives");
351 1.34 enami }
352 1.9 thorpej tv.tv_sec = interval;
353 1.28 mycroft tv.tv_nsec = 0;
354 1.1 cgd
355 1.9 thorpej /* print a new header on sigcont */
356 1.39 mrg (void)signal(SIGCONT, sig_header);
357 1.69 kre do_header = 1;
358 1.1 cgd
359 1.1 cgd for (hdrcnt = 1;;) {
360 1.72 mrg if (ISSET(todo, SHOW_STATS_X | SHOW_STATS_Y)) {
361 1.67 mlelstv lines = ndrives;
362 1.67 mlelstv hdroffset = 3;
363 1.72 mrg } else if (ISSET(todo, SHOW_STATS_3)) {
364 1.72 mrg lines = 1;
365 1.72 mrg hdroffset = 3;
366 1.67 mlelstv } else {
367 1.67 mlelstv lines = 1;
368 1.67 mlelstv hdroffset = 4;
369 1.67 mlelstv }
370 1.67 mlelstv
371 1.69 kre if (do_header || (winlines != 0 && (hdrcnt -= lines) <= 0)) {
372 1.39 mrg do_header = 0;
373 1.69 kre header(ndrives);
374 1.66 mrg hdrcnt = winlines - hdroffset;
375 1.1 cgd }
376 1.9 thorpej
377 1.69 kre if (!ISSET(todo, SHOW_TOTALS) || ISSET(todo, SHOW_NEW_TOTALS)) {
378 1.48 dsl cpuswap();
379 1.49 blymn drvswap();
380 1.50 simonb tkswap();
381 1.69 kre todo &= ~SHOW_NEW_TOTALS;
382 1.45 blymn }
383 1.49 blymn
384 1.69 kre display(ndrives);
385 1.1 cgd
386 1.1 cgd if (reps >= 0 && --reps <= 0)
387 1.1 cgd break;
388 1.28 mycroft nanosleep(&tv, NULL);
389 1.48 dsl cpureadstats();
390 1.49 blymn drvreadstats();
391 1.67 mlelstv
392 1.68 kre ndrives = selectdrives(argc, argv, 0);
393 1.1 cgd }
394 1.1 cgd exit(0);
395 1.1 cgd }
396 1.1 cgd
397 1.9 thorpej static void
398 1.39 mrg sig_header(int signo)
399 1.39 mrg {
400 1.39 mrg do_header = 1;
401 1.39 mrg }
402 1.39 mrg
403 1.39 mrg static void
404 1.69 kre header(int ndrives)
405 1.1 cgd {
406 1.69 kre int i;
407 1.1 cgd
408 1.29 mrg /* Main Headers. */
409 1.29 mrg if (ISSET(todo, SHOW_STATS_X)) {
410 1.29 mrg if (ISSET(todo, SHOW_TOTALS)) {
411 1.31 enami (void)printf(
412 1.42 dbj "device read KB/t xfr time MB ");
413 1.42 dbj (void)printf(" write KB/t xfr time MB\n");
414 1.29 mrg } else {
415 1.31 enami (void)printf(
416 1.31 enami "device read KB/t r/s time MB/s");
417 1.29 mrg (void)printf(" write KB/t w/s time MB/s\n");
418 1.29 mrg }
419 1.15 lukem return;
420 1.29 mrg }
421 1.15 lukem
422 1.64 mlelstv if (ISSET(todo, SHOW_STATS_Y)) {
423 1.64 mlelstv (void)printf("device read KB/t r/s MB/s write KB/t w/s MB/s");
424 1.64 mlelstv (void)printf(" wait actv wsvc_t asvc_t wtime time");
425 1.64 mlelstv (void)printf("\n");
426 1.64 mlelstv return;
427 1.64 mlelstv }
428 1.64 mlelstv
429 1.9 thorpej if (ISSET(todo, SHOW_TTY))
430 1.69 kre (void)printf("%*s", LAYOUT_TTY_GAP + LAYOUT_TTY, "tty");
431 1.9 thorpej
432 1.45 blymn if (ISSET(todo, SHOW_STATS_1)) {
433 1.69 kre for (i = 0; i < ndrives; i++) {
434 1.69 kre char *dname = cur.name[order[i]];
435 1.69 kre int dnlen = (int)strlen(dname);
436 1.69 kre
437 1.69 kre printf(" "); /* always a 1 column gap */
438 1.69 kre if (dnlen < LAYOUT_DRIVE_1 - 6)
439 1.69 kre printf("|%-*.*s ",
440 1.69 kre (LAYOUT_DRIVE_1 - 1 - dnlen - 1) / 2 - 1,
441 1.69 kre (LAYOUT_DRIVE_1 - 1 - dnlen - 1) / 2 - 1,
442 1.69 kre Line_Marker);
443 1.69 kre printf("%*.*s", ((dnlen >= LAYOUT_DRIVE_1 - 6) ?
444 1.69 kre MIN(MAX((LAYOUT_DRIVE_1 - dnlen) / 2, 0),
445 1.69 kre LAYOUT_DRIVE_1) : 0),
446 1.69 kre LAYOUT_DRIVE_1, dname);
447 1.69 kre if (dnlen < LAYOUT_DRIVE_1 - 6)
448 1.69 kre printf(" %*.*s|",
449 1.69 kre (LAYOUT_DRIVE_1 - 1 - dnlen - 2) / 2 - 1,
450 1.69 kre (LAYOUT_DRIVE_1 - 1 - dnlen - 2) / 2 - 1,
451 1.69 kre Line_Marker);
452 1.69 kre }
453 1.45 blymn }
454 1.9 thorpej
455 1.45 blymn if (ISSET(todo, SHOW_STATS_2)) {
456 1.69 kre for (i = 0; i < ndrives; i++) {
457 1.69 kre char *dname = cur.name[order[i]];
458 1.69 kre int dnlen = (int)strlen(dname);
459 1.69 kre
460 1.69 kre printf(" "); /* always a 1 column gap */
461 1.69 kre if (dnlen < LAYOUT_DRIVE_2 - 6)
462 1.69 kre printf("|%-*.*s ",
463 1.69 kre (LAYOUT_DRIVE_2 - 1 - dnlen - 1) / 2 - 1,
464 1.69 kre (LAYOUT_DRIVE_2 - 1 - dnlen - 1) / 2 - 1,
465 1.69 kre Line_Marker);
466 1.69 kre printf("%*.*s", ((dnlen >= LAYOUT_DRIVE_1 - 6) ?
467 1.69 kre MIN(MAX((LAYOUT_DRIVE_2 - dnlen) / 2, 0),
468 1.69 kre LAYOUT_DRIVE_2) : 0),
469 1.69 kre LAYOUT_DRIVE_1, dname);
470 1.69 kre if (dnlen < LAYOUT_DRIVE_2 - 6)
471 1.69 kre printf(" %*.*s|",
472 1.69 kre (LAYOUT_DRIVE_2 - 1 - dnlen - 2) / 2 - 1,
473 1.69 kre (LAYOUT_DRIVE_2 - 1 - dnlen - 2) / 2 - 1,
474 1.69 kre Line_Marker);
475 1.69 kre }
476 1.45 blymn }
477 1.49 blymn
478 1.70 mrg if (ISSET(todo, SHOW_STATS_3)) {
479 1.70 mrg for (i = 0; i < ndrives; i++) {
480 1.70 mrg char *dname = cur.name[order[i]];
481 1.70 mrg int dnlen = (int)strlen(dname);
482 1.70 mrg
483 1.70 mrg printf(" "); /* always a 1 column gap */
484 1.70 mrg if (dnlen < LAYOUT_DRIVE_3 - 6)
485 1.70 mrg printf("|%-*.*s ",
486 1.70 mrg (LAYOUT_DRIVE_3 - 1 - dnlen - 1) / 2 - 1,
487 1.70 mrg (LAYOUT_DRIVE_3 - 1 - dnlen - 1) / 2 - 1,
488 1.70 mrg Line_Marker);
489 1.70 mrg printf("%*.*s", ((dnlen >= LAYOUT_DRIVE_1 - 6) ?
490 1.70 mrg MIN(MAX((LAYOUT_DRIVE_3 - dnlen) / 2, 0),
491 1.70 mrg LAYOUT_DRIVE_3) : 0),
492 1.70 mrg LAYOUT_DRIVE_1, dname);
493 1.70 mrg if (dnlen < LAYOUT_DRIVE_3 - 6)
494 1.70 mrg printf(" %*.*s|",
495 1.70 mrg (LAYOUT_DRIVE_3 - 1 - dnlen - 2) / 2 - 1,
496 1.70 mrg (LAYOUT_DRIVE_3 - 1 - dnlen - 2) / 2 - 1,
497 1.70 mrg Line_Marker);
498 1.70 mrg }
499 1.70 mrg }
500 1.70 mrg
501 1.9 thorpej if (ISSET(todo, SHOW_CPU))
502 1.69 kre (void)printf("%*s", LAYOUT_CPU + LAYOUT_CPU_GAP, "CPU");
503 1.15 lukem
504 1.9 thorpej printf("\n");
505 1.9 thorpej
506 1.15 lukem /* Sub-Headers. */
507 1.69 kre if (ISSET(todo, SHOW_TTY)) {
508 1.69 kre printf("%*s %*s",
509 1.69 kre ((todo&SHOW_TOTALS)?LAYOUT_TTY_TIN:LAYOUT_TTY_IN), "tin",
510 1.69 kre ((todo&SHOW_TOTALS)?LAYOUT_TTY_TOUT:LAYOUT_TTY_OUT), "tout");
511 1.69 kre }
512 1.9 thorpej
513 1.15 lukem if (ISSET(todo, SHOW_STATS_1)) {
514 1.69 kre for (i = 0; i < ndrives; i++) {
515 1.69 kre if (ISSET(todo, SHOW_TOTALS)) {
516 1.69 kre (void)printf(" %*s %*s %*s",
517 1.69 kre LAYOUT_DRIVE_1_XFER, "xfr",
518 1.69 kre LAYOUT_DRIVE_1_XSIZE, "KB/t",
519 1.69 kre LAYOUT_DRIVE_1_VOLUME, "MB");
520 1.69 kre } else {
521 1.69 kre (void)printf(" %*s %*s %*s",
522 1.69 kre LAYOUT_DRIVE_1_RATE, "t/s",
523 1.69 kre LAYOUT_DRIVE_1_XSIZE, "KB/t",
524 1.69 kre LAYOUT_DRIVE_1_SPEED, "MB/s");
525 1.45 blymn }
526 1.69 kre }
527 1.15 lukem }
528 1.9 thorpej
529 1.45 blymn if (ISSET(todo, SHOW_STATS_2)) {
530 1.69 kre for (i = 0; i < ndrives; i++) {
531 1.69 kre if (ISSET(todo, SHOW_TOTALS)) {
532 1.69 kre (void)printf(" %*s %*s %*s",
533 1.69 kre LAYOUT_DRIVE_2_TXFR, "xfr",
534 1.69 kre LAYOUT_DRIVE_2_VOLUME, "KB",
535 1.69 kre LAYOUT_DRIVE_2_TBUSY, "time");
536 1.69 kre } else {
537 1.69 kre (void)printf(" %*s %*s %*s",
538 1.69 kre LAYOUT_DRIVE_2_XFR, "xfr",
539 1.69 kre LAYOUT_DRIVE_2_XSIZE, "KB",
540 1.69 kre LAYOUT_DRIVE_2_BUSY, "time");
541 1.69 kre }
542 1.69 kre }
543 1.45 blymn }
544 1.9 thorpej
545 1.70 mrg if (ISSET(todo, SHOW_STATS_3)) {
546 1.70 mrg for (i = 0; i < ndrives; i++) {
547 1.70 mrg if (ISSET(todo, SHOW_TOTALS)) {
548 1.70 mrg (void)printf(" %*s %*s",
549 1.70 mrg LAYOUT_DRIVE_2_VOLUME, "MB/s",
550 1.70 mrg LAYOUT_DRIVE_2_TBUSY, "time");
551 1.70 mrg } else {
552 1.70 mrg (void)printf(" %*s %*s",
553 1.70 mrg LAYOUT_DRIVE_2_XSIZE, "MB/s",
554 1.70 mrg LAYOUT_DRIVE_2_BUSY, "time");
555 1.70 mrg }
556 1.70 mrg }
557 1.70 mrg }
558 1.70 mrg
559 1.69 kre /* should do this properly, but it is such a simple case... */
560 1.9 thorpej if (ISSET(todo, SHOW_CPU))
561 1.69 kre (void)printf(" us ni sy in id");
562 1.9 thorpej printf("\n");
563 1.1 cgd }
564 1.1 cgd
565 1.65 mlelstv static double
566 1.65 mlelstv drive_time(double etime, int dn)
567 1.65 mlelstv {
568 1.65 mlelstv if (ISSET(todo, SHOW_TOTALS))
569 1.65 mlelstv return etime;
570 1.65 mlelstv
571 1.65 mlelstv if (cur.timestamp[dn].tv_sec || cur.timestamp[dn].tv_usec) {
572 1.65 mlelstv etime = (double)cur.timestamp[dn].tv_sec +
573 1.65 mlelstv ((double)cur.timestamp[dn].tv_usec / (double)1000000);
574 1.65 mlelstv }
575 1.65 mlelstv
576 1.65 mlelstv return etime;
577 1.65 mlelstv }
578 1.65 mlelstv
579 1.9 thorpej static void
580 1.69 kre drive_stats(int ndrives, double etime)
581 1.45 blymn {
582 1.69 kre int drive;
583 1.65 mlelstv double atime, dtime, mbps;
584 1.69 kre int c1, c2, c3;
585 1.69 kre
586 1.69 kre if (ISSET(todo, SHOW_TOTALS)) {
587 1.69 kre c1 = LAYOUT_DRIVE_1_XFER;
588 1.69 kre c2 = LAYOUT_DRIVE_1_XSIZE;
589 1.69 kre c3 = LAYOUT_DRIVE_1_VOLUME;
590 1.69 kre } else {
591 1.69 kre c1 = LAYOUT_DRIVE_1_RATE;
592 1.69 kre c2 = LAYOUT_DRIVE_1_XSIZE;
593 1.69 kre c3 = LAYOUT_DRIVE_1_SPEED;
594 1.69 kre }
595 1.45 blymn
596 1.69 kre for (drive = 0; drive < ndrives; ++drive) {
597 1.69 kre int dn = order[drive];
598 1.69 kre
599 1.69 kre if (!cur.select[dn]) /* should be impossible */
600 1.45 blymn continue;
601 1.65 mlelstv
602 1.69 kre if (todo & SUPPRESS_ZERO) {
603 1.69 kre if (cur.rxfer[dn] == 0 &&
604 1.69 kre cur.wxfer[dn] == 0 &&
605 1.69 kre cur.rbytes[dn] == 0 &&
606 1.69 kre cur.wbytes[dn] == 0) {
607 1.69 kre printf("%*s", c1 + 1 + c2 + 1 + c3 + 1, "");
608 1.69 kre continue;
609 1.69 kre }
610 1.69 kre }
611 1.69 kre
612 1.65 mlelstv dtime = drive_time(etime, dn);
613 1.65 mlelstv
614 1.69 kre /* average transfers per second. */
615 1.69 kre (void)printf(" %*.0f", c1,
616 1.69 kre (cur.rxfer[dn] + cur.wxfer[dn]) / dtime);
617 1.69 kre
618 1.45 blymn /* average Kbytes per transfer. */
619 1.49 blymn if (cur.rxfer[dn] + cur.wxfer[dn])
620 1.49 blymn mbps = ((cur.rbytes[dn] + cur.wbytes[dn]) /
621 1.49 blymn 1024.0) / (cur.rxfer[dn] + cur.wxfer[dn]);
622 1.45 blymn else
623 1.45 blymn mbps = 0.0;
624 1.69 kre (void)printf(" %*.*f", c2,
625 1.59 enami MAX(0, 3 - (int)floor(log10(fmax(1.0, mbps)))), mbps);
626 1.45 blymn
627 1.49 blymn /* time busy in drive activity */
628 1.49 blymn atime = (double)cur.time[dn].tv_sec +
629 1.49 blymn ((double)cur.time[dn].tv_usec / (double)1000000);
630 1.45 blymn
631 1.45 blymn /* Megabytes per second. */
632 1.45 blymn if (atime != 0.0)
633 1.49 blymn mbps = (cur.rbytes[dn] + cur.wbytes[dn]) /
634 1.45 blymn (double)(1024 * 1024);
635 1.45 blymn else
636 1.45 blymn mbps = 0;
637 1.65 mlelstv mbps /= dtime;
638 1.69 kre (void)printf(" %*.*f", c3,
639 1.59 enami MAX(0, 3 - (int)floor(log10(fmax(1.0, mbps)))), mbps);
640 1.45 blymn }
641 1.45 blymn }
642 1.45 blymn
643 1.45 blymn static void
644 1.69 kre drive_stats2(int ndrives, double etime)
645 1.45 blymn {
646 1.69 kre int drive;
647 1.65 mlelstv double atime, dtime;
648 1.69 kre int c1, c2, c3;
649 1.69 kre
650 1.69 kre if (ISSET(todo, SHOW_TOTALS)) {
651 1.69 kre c1 = LAYOUT_DRIVE_2_TXFR;
652 1.69 kre c2 = LAYOUT_DRIVE_2_VOLUME;
653 1.69 kre c3 = LAYOUT_DRIVE_2_TBUSY;
654 1.69 kre } else {
655 1.69 kre c1 = LAYOUT_DRIVE_2_XFR;
656 1.69 kre c2 = LAYOUT_DRIVE_2_XSIZE;
657 1.69 kre c3 = LAYOUT_DRIVE_2_BUSY;
658 1.69 kre }
659 1.45 blymn
660 1.69 kre for (drive = 0; drive < ndrives; ++drive) {
661 1.69 kre int dn = order[drive];
662 1.69 kre
663 1.69 kre if (!cur.select[dn]) /* should be impossible */
664 1.45 blymn continue;
665 1.45 blymn
666 1.69 kre if (todo & SUPPRESS_ZERO) {
667 1.69 kre if (cur.rxfer[dn] == 0 &&
668 1.69 kre cur.wxfer[dn] == 0 &&
669 1.69 kre cur.rbytes[dn] == 0 &&
670 1.69 kre cur.wbytes[dn] == 0) {
671 1.69 kre printf("%*s", c1 + 1 + c2 + 1 + c3 + 1, "");
672 1.69 kre continue;
673 1.69 kre }
674 1.69 kre }
675 1.69 kre
676 1.65 mlelstv dtime = drive_time(etime, dn);
677 1.65 mlelstv
678 1.69 kre /* average transfers per second. */
679 1.70 mrg if (ISSET(todo, SHOW_STATS_2)) {
680 1.70 mrg (void)printf(" %*.0f", c1,
681 1.70 mrg (cur.rxfer[dn] + cur.wxfer[dn]) / dtime);
682 1.70 mrg }
683 1.69 kre
684 1.70 mrg /* average mbytes per second. */
685 1.69 kre (void)printf(" %*.0f", c2,
686 1.70 mrg (cur.rbytes[dn] + cur.wbytes[dn]) /
687 1.70 mrg (double)(1024 * 1024) / dtime);
688 1.45 blymn
689 1.69 kre /* average time busy in dn activity */
690 1.49 blymn atime = (double)cur.time[dn].tv_sec +
691 1.49 blymn ((double)cur.time[dn].tv_usec / (double)1000000);
692 1.69 kre (void)printf(" %*.2f", c3, atime / dtime);
693 1.45 blymn }
694 1.45 blymn }
695 1.45 blymn
696 1.45 blymn static void
697 1.69 kre drive_statsx(int ndrives, double etime)
698 1.45 blymn {
699 1.69 kre int dn, drive;
700 1.65 mlelstv double atime, dtime, kbps;
701 1.45 blymn
702 1.69 kre for (drive = 0; drive < ndrives; ++drive) {
703 1.69 kre dn = order[drive];
704 1.69 kre
705 1.69 kre if (!cur.select[dn]) /* impossible */
706 1.45 blymn continue;
707 1.45 blymn
708 1.69 kre (void)printf("%-8.8s", cur.name[dn]);
709 1.69 kre
710 1.69 kre if (todo & SUPPRESS_ZERO) {
711 1.69 kre if (cur.rbytes[dn] == 0 && cur.rxfer[dn] == 0 &&
712 1.69 kre cur.wbytes[dn] == 0 && cur.wxfer[dn] == 0) {
713 1.69 kre printf("\n");
714 1.69 kre continue;
715 1.69 kre }
716 1.69 kre }
717 1.69 kre
718 1.65 mlelstv dtime = drive_time(etime, dn);
719 1.65 mlelstv
720 1.45 blymn /* average read Kbytes per transfer */
721 1.49 blymn if (cur.rxfer[dn])
722 1.49 blymn kbps = (cur.rbytes[dn] / 1024.0) / cur.rxfer[dn];
723 1.45 blymn else
724 1.45 blymn kbps = 0.0;
725 1.45 blymn (void)printf(" %8.2f", kbps);
726 1.45 blymn
727 1.45 blymn /* average read transfers
728 1.45 blymn (per second) */
729 1.65 mlelstv (void)printf(" %6.0f", cur.rxfer[dn] / dtime);
730 1.45 blymn
731 1.49 blymn /* time read busy in drive activity */
732 1.49 blymn atime = (double)cur.time[dn].tv_sec +
733 1.49 blymn ((double)cur.time[dn].tv_usec / (double)1000000);
734 1.65 mlelstv (void)printf(" %6.2f", atime / dtime);
735 1.45 blymn
736 1.45 blymn /* average read megabytes
737 1.45 blymn (per second) */
738 1.45 blymn (void)printf(" %8.2f",
739 1.65 mlelstv cur.rbytes[dn] / (1024.0 * 1024) / dtime);
740 1.45 blymn
741 1.45 blymn
742 1.45 blymn /* average write Kbytes per transfer */
743 1.49 blymn if (cur.wxfer[dn])
744 1.49 blymn kbps = (cur.wbytes[dn] / 1024.0) / cur.wxfer[dn];
745 1.45 blymn else
746 1.45 blymn kbps = 0.0;
747 1.45 blymn (void)printf(" %8.2f", kbps);
748 1.45 blymn
749 1.45 blymn /* average write transfers
750 1.45 blymn (per second) */
751 1.65 mlelstv (void)printf(" %6.0f", cur.wxfer[dn] / dtime);
752 1.45 blymn
753 1.49 blymn /* time write busy in drive activity */
754 1.49 blymn atime = (double)cur.time[dn].tv_sec +
755 1.49 blymn ((double)cur.time[dn].tv_usec / (double)1000000);
756 1.65 mlelstv (void)printf(" %6.2f", atime / dtime);
757 1.45 blymn
758 1.45 blymn /* average write megabytes
759 1.45 blymn (per second) */
760 1.45 blymn (void)printf(" %8.2f\n",
761 1.65 mlelstv cur.wbytes[dn] / (1024.0 * 1024) / dtime);
762 1.45 blymn }
763 1.45 blymn }
764 1.45 blymn
765 1.45 blymn static void
766 1.64 mlelstv drive_statsy_io(double elapsed, double count, double volume)
767 1.64 mlelstv {
768 1.64 mlelstv double kbps;
769 1.64 mlelstv
770 1.64 mlelstv /* average Kbytes per transfer */
771 1.64 mlelstv if (count)
772 1.64 mlelstv kbps = (volume / 1024.0) / count;
773 1.64 mlelstv else
774 1.64 mlelstv kbps = 0.0;
775 1.64 mlelstv (void)printf(" %8.2f", kbps);
776 1.64 mlelstv
777 1.64 mlelstv /* average transfers (per second) */
778 1.64 mlelstv (void)printf(" %6.0f", count / elapsed);
779 1.64 mlelstv
780 1.64 mlelstv /* average megabytes (per second) */
781 1.64 mlelstv (void)printf(" %8.2f", volume / (1024.0 * 1024) / elapsed);
782 1.64 mlelstv }
783 1.64 mlelstv
784 1.64 mlelstv static void
785 1.64 mlelstv drive_statsy_q(double elapsed, double busy, double wait, double busysum, double waitsum, double count)
786 1.64 mlelstv {
787 1.64 mlelstv /* average wait queue length */
788 1.64 mlelstv (void)printf(" %6.1f", waitsum / elapsed);
789 1.64 mlelstv
790 1.64 mlelstv /* average busy queue length */
791 1.64 mlelstv (void)printf(" %6.1f", busysum / elapsed);
792 1.64 mlelstv
793 1.64 mlelstv /* average wait time */
794 1.64 mlelstv (void)printf(" %7.2f", count > 0 ? waitsum / count * 1000.0 : 0.0);
795 1.64 mlelstv
796 1.64 mlelstv /* average service time */
797 1.64 mlelstv (void)printf(" %7.2f", count > 0 ? busysum / count * 1000.0 : 0.0);
798 1.64 mlelstv
799 1.64 mlelstv /* time waiting for drive activity */
800 1.64 mlelstv (void)printf(" %6.2f", wait / elapsed);
801 1.64 mlelstv
802 1.64 mlelstv /* time busy in drive activity */
803 1.64 mlelstv (void)printf(" %6.2f", busy / elapsed);
804 1.64 mlelstv }
805 1.64 mlelstv
806 1.64 mlelstv static void
807 1.69 kre drive_statsy(int ndrives, double etime)
808 1.64 mlelstv {
809 1.69 kre int drive, dn;
810 1.65 mlelstv double atime, await, abusysum, awaitsum, dtime;
811 1.64 mlelstv
812 1.69 kre for (drive = 0; drive < ndrives; ++drive) {
813 1.69 kre dn = order[drive];
814 1.69 kre if (!cur.select[dn]) /* impossible */
815 1.64 mlelstv continue;
816 1.64 mlelstv
817 1.69 kre (void)printf("%-8.8s", cur.name[dn]);
818 1.69 kre
819 1.69 kre if (todo & SUPPRESS_ZERO) {
820 1.69 kre if (cur.rbytes[dn] == 0 && cur.rxfer[dn] == 0 &&
821 1.69 kre cur.wbytes[dn] == 0 && cur.wxfer[dn] == 0) {
822 1.69 kre printf("\n");
823 1.69 kre continue;
824 1.69 kre }
825 1.69 kre }
826 1.69 kre
827 1.65 mlelstv dtime = drive_time(etime, dn);
828 1.65 mlelstv
829 1.64 mlelstv atime = (double)cur.time[dn].tv_sec +
830 1.64 mlelstv ((double)cur.time[dn].tv_usec / (double)1000000);
831 1.64 mlelstv await = (double)cur.wait[dn].tv_sec +
832 1.64 mlelstv ((double)cur.wait[dn].tv_usec / (double)1000000);
833 1.64 mlelstv abusysum = (double)cur.busysum[dn].tv_sec +
834 1.64 mlelstv ((double)cur.busysum[dn].tv_usec / (double)1000000);
835 1.64 mlelstv awaitsum = (double)cur.waitsum[dn].tv_sec +
836 1.64 mlelstv ((double)cur.waitsum[dn].tv_usec / (double)1000000);
837 1.64 mlelstv
838 1.65 mlelstv drive_statsy_io(dtime, cur.rxfer[dn], cur.rbytes[dn]);
839 1.64 mlelstv (void)printf(" ");
840 1.65 mlelstv drive_statsy_io(dtime, cur.wxfer[dn], cur.wbytes[dn]);
841 1.65 mlelstv drive_statsy_q(dtime, atime, await, abusysum, awaitsum, cur.rxfer[dn]+cur.wxfer[dn]);
842 1.64 mlelstv
843 1.64 mlelstv (void)printf("\n");
844 1.64 mlelstv }
845 1.64 mlelstv }
846 1.64 mlelstv
847 1.64 mlelstv static void
848 1.23 simonb cpustats(void)
849 1.1 cgd {
850 1.12 lukem int state;
851 1.53 lukem double ttime;
852 1.1 cgd
853 1.69 kre static int cwidth[CPUSTATES] = {
854 1.69 kre LAYOUT_CPU_USER,
855 1.69 kre LAYOUT_CPU_NICE,
856 1.69 kre LAYOUT_CPU_SYS,
857 1.69 kre LAYOUT_CPU_INT,
858 1.69 kre LAYOUT_CPU_IDLE
859 1.69 kre };
860 1.69 kre
861 1.53 lukem ttime = 0;
862 1.1 cgd for (state = 0; state < CPUSTATES; ++state)
863 1.53 lukem ttime += cur.cp_time[state];
864 1.53 lukem if (!ttime)
865 1.53 lukem ttime = 1.0;
866 1.69 kre
867 1.69 kre printf("%*s", LAYOUT_CPU_GAP - 1, ""); /* the 1 is the next space */
868 1.69 kre for (state = 0; state < CPUSTATES; ++state) {
869 1.69 kre if ((todo & SUPPRESS_ZERO) && cur.cp_time[state] == 0) {
870 1.69 kre printf(" %*s", cwidth[state], "");
871 1.69 kre continue;
872 1.69 kre }
873 1.69 kre printf(" %*.0f", cwidth[state],
874 1.69 kre 100. * cur.cp_time[state] / ttime);
875 1.69 kre }
876 1.1 cgd }
877 1.1 cgd
878 1.9 thorpej static void
879 1.23 simonb usage(void)
880 1.1 cgd {
881 1.13 mrg
882 1.71 wiz (void)fprintf(stderr, "usage: iostat [-CDdITXxyz] [-c count] "
883 1.69 kre "[-H height] [-W width] [-w wait] [drives]\n");
884 1.1 cgd exit(1);
885 1.9 thorpej }
886 1.9 thorpej
887 1.9 thorpej static void
888 1.69 kre display(int ndrives)
889 1.9 thorpej {
890 1.9 thorpej double etime;
891 1.9 thorpej
892 1.9 thorpej /* Sum up the elapsed ticks. */
893 1.27 sommerfe etime = cur.cp_etime;
894 1.9 thorpej
895 1.34 enami /*
896 1.34 enami * If we're showing totals only, then don't divide by the
897 1.9 thorpej * system time.
898 1.9 thorpej */
899 1.9 thorpej if (ISSET(todo, SHOW_TOTALS))
900 1.9 thorpej etime = 1.0;
901 1.9 thorpej
902 1.34 enami if (ISSET(todo, SHOW_STATS_X)) {
903 1.69 kre drive_statsx(ndrives, etime);
904 1.34 enami goto out;
905 1.34 enami }
906 1.34 enami
907 1.64 mlelstv if (ISSET(todo, SHOW_STATS_Y)) {
908 1.69 kre drive_statsy(ndrives, etime);
909 1.64 mlelstv goto out;
910 1.64 mlelstv }
911 1.64 mlelstv
912 1.9 thorpej if (ISSET(todo, SHOW_TTY))
913 1.69 kre printf("%*.0f %*.0f",
914 1.69 kre ((todo & SHOW_TOTALS) ? LAYOUT_TTY_TIN : LAYOUT_TTY_IN),
915 1.69 kre cur.tk_nin / etime,
916 1.69 kre ((todo & SHOW_TOTALS) ? LAYOUT_TTY_TOUT : LAYOUT_TTY_OUT),
917 1.69 kre cur.tk_nout / etime);
918 1.27 sommerfe
919 1.45 blymn if (ISSET(todo, SHOW_STATS_1)) {
920 1.69 kre drive_stats(ndrives, etime);
921 1.45 blymn }
922 1.49 blymn
923 1.70 mrg if (ISSET(todo, SHOW_STATS_2) || ISSET(todo, SHOW_STATS_3)) {
924 1.69 kre drive_stats2(ndrives, etime);
925 1.45 blymn }
926 1.49 blymn
927 1.9 thorpej if (ISSET(todo, SHOW_CPU))
928 1.9 thorpej cpustats();
929 1.9 thorpej
930 1.34 enami (void)printf("\n");
931 1.34 enami
932 1.34 enami out:
933 1.9 thorpej (void)fflush(stdout);
934 1.9 thorpej }
935 1.9 thorpej
936 1.34 enami static int
937 1.68 kre selectdrives(int argc, char *argv[], int first)
938 1.9 thorpej {
939 1.34 enami int i, maxdrives, ndrives, tried;
940 1.9 thorpej
941 1.9 thorpej /*
942 1.9 thorpej * Choose drives to be displayed. Priority goes to (in order) drives
943 1.9 thorpej * supplied as arguments and default drives. If everything isn't
944 1.9 thorpej * filled in and there are drives not taken care of, display the first
945 1.9 thorpej * few that fit.
946 1.9 thorpej *
947 1.9 thorpej * The backward compatibility #ifdefs permit the syntax:
948 1.9 thorpej * iostat [ drives ] [ interval [ count ] ]
949 1.9 thorpej */
950 1.19 tron
951 1.9 thorpej #define BACKWARD_COMPATIBILITY
952 1.34 enami for (tried = ndrives = 0; *argv; ++argv) {
953 1.34 enami #ifdef BACKWARD_COMPATIBILITY
954 1.43 dsl if (isdigit((unsigned char)**argv))
955 1.9 thorpej break;
956 1.9 thorpej #endif
957 1.34 enami tried++;
958 1.53 lukem for (i = 0; i < (int)ndrive; i++) {
959 1.62 mrg if (fnmatch(*argv, cur.name[i], 0))
960 1.33 christos continue;
961 1.49 blymn cur.select[i] = 1;
962 1.69 kre if (ordersize <= ndrives) {
963 1.69 kre int *new = realloc(order,
964 1.69 kre (ordersize + 8) * sizeof *order);
965 1.69 kre if (new == NULL)
966 1.69 kre break;
967 1.69 kre ordersize += 8;
968 1.69 kre order = new;
969 1.69 kre }
970 1.69 kre order[ndrives++] = i;
971 1.45 blymn }
972 1.49 blymn
973 1.9 thorpej }
974 1.34 enami
975 1.34 enami if (ndrives == 0 && tried == 0) {
976 1.34 enami /*
977 1.38 simonb * Pick up to defdrives (or all if -x is given) drives
978 1.34 enami * if none specified.
979 1.34 enami */
980 1.64 mlelstv maxdrives = (ISSET(todo, SHOW_STATS_X | SHOW_STATS_Y) ||
981 1.53 lukem (int)ndrive < defdrives)
982 1.53 lukem ? (int)(ndrive) : defdrives;
983 1.69 kre ordersize = maxdrives;
984 1.69 kre free(order);
985 1.69 kre order = calloc(ordersize, sizeof *order);
986 1.69 kre if (order == NULL)
987 1.69 kre errx(1, "Insufficient memory");
988 1.34 enami for (i = 0; i < maxdrives; i++) {
989 1.49 blymn cur.select[i] = 1;
990 1.69 kre order[i] = i;
991 1.49 blymn
992 1.34 enami ++ndrives;
993 1.64 mlelstv if (!ISSET(todo, SHOW_STATS_X | SHOW_STATS_Y) &&
994 1.64 mlelstv ndrives == defdrives)
995 1.34 enami break;
996 1.34 enami }
997 1.34 enami }
998 1.34 enami
999 1.34 enami #ifdef BACKWARD_COMPATIBILITY
1000 1.68 kre if (first && *argv) {
1001 1.9 thorpej interval = atoi(*argv);
1002 1.9 thorpej if (*++argv)
1003 1.9 thorpej reps = atoi(*argv);
1004 1.9 thorpej }
1005 1.9 thorpej #endif
1006 1.9 thorpej
1007 1.9 thorpej if (interval) {
1008 1.9 thorpej if (!reps)
1009 1.9 thorpej reps = -1;
1010 1.9 thorpej } else
1011 1.9 thorpej if (reps)
1012 1.9 thorpej interval = 1;
1013 1.9 thorpej
1014 1.34 enami return (ndrives);
1015 1.1 cgd }
1016