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