Home | History | Annotate | Line # | Download | only in iostat
iostat.c revision 1.63.2.1
      1 /*	$NetBSD: iostat.c,v 1.63.2.1 2017/03/20 06:58:07 pgoyette Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1996 John M. Vinopal
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *      This product includes software developed for the NetBSD Project
     18  *      by John M. Vinopal.
     19  * 4. The name of the author may not be used to endorse or promote products
     20  *    derived from this software without specific prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32  * SUCH DAMAGE.
     33  */
     34 
     35 /*-
     36  * Copyright (c) 1986, 1991, 1993
     37  *      The Regents of the University of California.  All rights reserved.
     38  *
     39  * Redistribution and use in source and binary forms, with or without
     40  * modification, are permitted provided that the following conditions
     41  * are met:
     42  * 1. Redistributions of source code must retain the above copyright
     43  *    notice, this list of conditions and the following disclaimer.
     44  * 2. Redistributions in binary form must reproduce the above copyright
     45  *    notice, this list of conditions and the following disclaimer in the
     46  *    documentation and/or other materials provided with the distribution.
     47  * 3. Neither the name of the University nor the names of its contributors
     48  *    may be used to endorse or promote products derived from this software
     49  *    without specific prior written permission.
     50  *
     51  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     52  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     53  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     54  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     55  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     59  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     60  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     61  * SUCH DAMAGE.
     62  */
     63 
     64 #include <sys/cdefs.h>
     65 #ifndef lint
     66 __COPYRIGHT("@(#) Copyright (c) 1986, 1991, 1993\
     67  The Regents of the University of California.  All rights reserved.");
     68 #endif /* not lint */
     69 
     70 #ifndef lint
     71 #if 0
     72 static char sccsid[] = "@(#)iostat.c	8.3 (Berkeley) 4/28/95";
     73 #else
     74 __RCSID("$NetBSD: iostat.c,v 1.63.2.1 2017/03/20 06:58:07 pgoyette Exp $");
     75 #endif
     76 #endif /* not lint */
     77 
     78 #include <sys/types.h>
     79 #include <sys/ioctl.h>
     80 #include <sys/sched.h>
     81 #include <sys/time.h>
     82 
     83 #include <err.h>
     84 #include <ctype.h>
     85 #include <signal.h>
     86 #include <stdio.h>
     87 #include <stdlib.h>
     88 #include <string.h>
     89 #include <unistd.h>
     90 #include <math.h>
     91 #include <fnmatch.h>
     92 
     93 #include "drvstats.h"
     94 
     95 int		hz;
     96 static int	reps, interval;
     97 static int	todo = 0;
     98 static int	defdrives;
     99 static int	winlines = 20;
    100 static int	wincols = 80;
    101 
    102 #define	MAX(a,b)	(((a)>(b))?(a):(b))
    103 
    104 #define	ISSET(x, a)	((x) & (a))
    105 #define	SHOW_CPU	(1<<0)
    106 #define	SHOW_TTY	(1<<1)
    107 #define	SHOW_STATS_1	(1<<2)
    108 #define	SHOW_STATS_2	(1<<3)
    109 #define	SHOW_STATS_X	(1<<4)
    110 #define	SHOW_STATS_Y	(1<<5)
    111 #define	SHOW_TOTALS	(1<<7)
    112 #define	SHOW_STATS_ALL	(SHOW_STATS_1 | SHOW_STATS_2 | SHOW_STATS_X | SHOW_STATS_Y)
    113 
    114 static void cpustats(void);
    115 static void drive_stats(double);
    116 static void drive_stats2(double);
    117 static void drive_statsx(double);
    118 static void drive_statsy(double);
    119 static void drive_statsy_io(double, double, double);
    120 static void drive_statsy_q(double, double, double, double, double, double);
    121 static void sig_header(int);
    122 static volatile int do_header;
    123 static void header(void);
    124 __dead static void usage(void);
    125 static void display(void);
    126 static int selectdrives(int, char *[]);
    127 
    128 int
    129 main(int argc, char *argv[])
    130 {
    131 	int ch, hdrcnt, ndrives, lines;
    132 	struct timespec	tv;
    133 	struct ttysize ts;
    134 
    135 	while ((ch = getopt(argc, argv, "Cc:dDITw:xy")) != -1)
    136 		switch (ch) {
    137 		case 'c':
    138 			if ((reps = atoi(optarg)) <= 0)
    139 				errx(1, "repetition count <= 0.");
    140 			break;
    141 		case 'C':
    142 			todo |= SHOW_CPU;
    143 			break;
    144 		case 'd':
    145 			todo &= ~SHOW_STATS_ALL;
    146 			todo |= SHOW_STATS_1;
    147 			break;
    148 		case 'D':
    149 			todo &= ~SHOW_STATS_ALL;
    150 			todo |= SHOW_STATS_2;
    151 			break;
    152 		case 'I':
    153 			todo |= SHOW_TOTALS;
    154 			break;
    155 		case 'T':
    156 			todo |= SHOW_TTY;
    157 			break;
    158 		case 'w':
    159 			if ((interval = atoi(optarg)) <= 0)
    160 				errx(1, "interval <= 0.");
    161 			break;
    162 		case 'x':
    163 			todo &= ~SHOW_STATS_ALL;
    164 			todo |= SHOW_STATS_X;
    165 			break;
    166 		case 'y':
    167 			todo &= ~SHOW_STATS_ALL;
    168 			todo |= SHOW_STATS_Y;
    169 			break;
    170 		case '?':
    171 		default:
    172 			usage();
    173 		}
    174 	argc -= optind;
    175 	argv += optind;
    176 
    177 	if (!ISSET(todo, SHOW_CPU | SHOW_TTY | SHOW_STATS_ALL))
    178 		todo |= SHOW_CPU | SHOW_TTY | SHOW_STATS_1;
    179 	if (ISSET(todo, SHOW_STATS_X)) {
    180 		todo &= ~(SHOW_CPU | SHOW_TTY | SHOW_STATS_ALL);
    181 		todo |= SHOW_STATS_X;
    182 	}
    183 	if (ISSET(todo, SHOW_STATS_Y)) {
    184 		todo &= ~(SHOW_CPU | SHOW_TTY | SHOW_STATS_ALL | SHOW_TOTALS);
    185 		todo |= SHOW_STATS_Y;
    186 	}
    187 
    188 	if (ioctl(STDOUT_FILENO, TIOCGSIZE, &ts) != -1) {
    189 		if (ts.ts_lines)
    190 			winlines = ts.ts_lines;
    191 		if (ts.ts_cols)
    192 			wincols = ts.ts_cols;
    193 	}
    194 
    195 	defdrives = wincols;
    196 	if (ISSET(todo, SHOW_CPU))
    197 		defdrives -= 16;	/* XXX magic number */
    198 	if (ISSET(todo, SHOW_TTY))
    199 		defdrives -= 10;	/* XXX magic number */
    200 	defdrives /= 18;		/* XXX magic number */
    201 
    202 	drvinit(0);
    203 	cpureadstats();
    204 	drvreadstats();
    205 	ndrives = selectdrives(argc, argv);
    206 	if (ndrives == 0) {
    207 		/* No drives are selected.  No need to show drive stats. */
    208 		todo &= ~SHOW_STATS_ALL;
    209 		if (todo == 0)
    210 			errx(1, "no drives");
    211 	}
    212 	if (ISSET(todo, SHOW_STATS_X | SHOW_STATS_Y))
    213 		lines = ndrives;
    214 	else
    215 		lines = 1;
    216 
    217 	tv.tv_sec = interval;
    218 	tv.tv_nsec = 0;
    219 
    220 	/* print a new header on sigcont */
    221 	(void)signal(SIGCONT, sig_header);
    222 
    223 	for (hdrcnt = 1;;) {
    224 		if (do_header || lines > 1 || (hdrcnt -= lines) <= 0) {
    225 			do_header = 0;
    226 			header();
    227 			hdrcnt = winlines - 4;
    228 		}
    229 
    230 		if (!ISSET(todo, SHOW_TOTALS)) {
    231 			cpuswap();
    232 			drvswap();
    233 			tkswap();
    234 		}
    235 
    236 		display();
    237 
    238 		if (reps >= 0 && --reps <= 0)
    239 			break;
    240 		nanosleep(&tv, NULL);
    241 		cpureadstats();
    242 		drvreadstats();
    243 	}
    244 	exit(0);
    245 }
    246 
    247 static void
    248 sig_header(int signo)
    249 {
    250 	do_header = 1;
    251 }
    252 
    253 static void
    254 header(void)
    255 {
    256 	size_t i;
    257 
    258 					/* Main Headers. */
    259 	if (ISSET(todo, SHOW_STATS_X)) {
    260 		if (ISSET(todo, SHOW_TOTALS)) {
    261 			(void)printf(
    262 			    "device  read KB/t    xfr   time     MB  ");
    263 			(void)printf(" write KB/t    xfr   time     MB\n");
    264 		} else {
    265 			(void)printf(
    266 			    "device  read KB/t    r/s   time     MB/s");
    267 			(void)printf(" write KB/t    w/s   time     MB/s\n");
    268 		}
    269 		return;
    270 	}
    271 
    272 	if (ISSET(todo, SHOW_STATS_Y)) {
    273 		(void)printf("device  read KB/t    r/s     MB/s write KB/t    w/s     MB/s");
    274 		(void)printf("   wait   actv  wsvc_t  asvc_t  wtime   time");
    275 		(void)printf("\n");
    276 		return;
    277 	}
    278 
    279 	if (ISSET(todo, SHOW_TTY))
    280 		(void)printf("      tty");
    281 
    282 	if (ISSET(todo, SHOW_STATS_1)) {
    283 		for (i = 0; i < ndrive; i++)
    284 			if (cur.select[i])
    285 				(void)printf("        %9.9s ", cur.name[i]);
    286 	}
    287 
    288 	if (ISSET(todo, SHOW_STATS_2)) {
    289 		for (i = 0; i < ndrive; i++)
    290 			if (cur.select[i])
    291 				(void)printf("        %9.9s ", cur.name[i]);
    292 	}
    293 
    294 	if (ISSET(todo, SHOW_CPU))
    295 		(void)printf("            CPU");
    296 
    297 	printf("\n");
    298 
    299 					/* Sub-Headers. */
    300 	if (ISSET(todo, SHOW_TTY))
    301 		printf(" tin  tout");
    302 
    303 	if (ISSET(todo, SHOW_STATS_1)) {
    304 		for (i = 0; i < ndrive; i++)
    305 			if (cur.select[i]) {
    306 				if (ISSET(todo, SHOW_TOTALS))
    307 					(void)printf("  KB/t  xfr  MB   ");
    308 				else
    309 					(void)printf("  KB/t  t/s  MB/s ");
    310 			}
    311 	}
    312 
    313 	if (ISSET(todo, SHOW_STATS_2)) {
    314 		for (i = 0; i < ndrive; i++)
    315 			if (cur.select[i])
    316 				(void)printf("    KB   xfr time ");
    317 	}
    318 
    319 	if (ISSET(todo, SHOW_CPU))
    320 		(void)printf(" us ni sy in id");
    321 	printf("\n");
    322 }
    323 
    324 static void
    325 drive_stats(double etime)
    326 {
    327 	size_t dn;
    328 	double atime, mbps;
    329 
    330 	for (dn = 0; dn < ndrive; ++dn) {
    331 		if (!cur.select[dn])
    332 			continue;
    333 					/* average Kbytes per transfer. */
    334 		if (cur.rxfer[dn] + cur.wxfer[dn])
    335 			mbps = ((cur.rbytes[dn] + cur.wbytes[dn]) /
    336 			    1024.0) / (cur.rxfer[dn] + cur.wxfer[dn]);
    337 		else
    338 			mbps = 0.0;
    339 		(void)printf(" %5.*f",
    340 		    MAX(0, 3 - (int)floor(log10(fmax(1.0, mbps)))), mbps);
    341 
    342 					/* average transfers per second. */
    343 		(void)printf(" %4.0f",
    344 		    (cur.rxfer[dn] + cur.wxfer[dn]) / etime);
    345 
    346 					/* time busy in drive activity */
    347 		atime = (double)cur.time[dn].tv_sec +
    348 		    ((double)cur.time[dn].tv_usec / (double)1000000);
    349 
    350 					/* Megabytes per second. */
    351 		if (atime != 0.0)
    352 			mbps = (cur.rbytes[dn] + cur.wbytes[dn]) /
    353 			    (double)(1024 * 1024);
    354 		else
    355 			mbps = 0;
    356 		mbps /= etime;
    357 		(void)printf(" %5.*f ",
    358 		    MAX(0, 3 - (int)floor(log10(fmax(1.0, mbps)))), mbps);
    359 	}
    360 }
    361 
    362 static void
    363 drive_stats2(double etime)
    364 {
    365 	size_t dn;
    366 	double atime;
    367 
    368 	for (dn = 0; dn < ndrive; ++dn) {
    369 		if (!cur.select[dn])
    370 			continue;
    371 
    372 					/* average kbytes per second. */
    373 		(void)printf(" %5.0f",
    374 		    (cur.rbytes[dn] + cur.wbytes[dn]) / 1024.0 / etime);
    375 
    376 					/* average transfers per second. */
    377 		(void)printf(" %5.0f",
    378 		    (cur.rxfer[dn] + cur.wxfer[dn]) / etime);
    379 
    380 					/* average time busy in drive activity */
    381 		atime = (double)cur.time[dn].tv_sec +
    382 		    ((double)cur.time[dn].tv_usec / (double)1000000);
    383 		(void)printf(" %4.2f ", atime / etime);
    384 	}
    385 }
    386 
    387 static void
    388 drive_statsx(double etime)
    389 {
    390 	size_t dn;
    391 	double atime, kbps;
    392 
    393 	for (dn = 0; dn < ndrive; ++dn) {
    394 		if (!cur.select[dn])
    395 			continue;
    396 
    397 		(void)printf("%-8.8s", cur.name[dn]);
    398 
    399 					/* average read Kbytes per transfer */
    400 		if (cur.rxfer[dn])
    401 			kbps = (cur.rbytes[dn] / 1024.0) / cur.rxfer[dn];
    402 		else
    403 			kbps = 0.0;
    404 		(void)printf(" %8.2f", kbps);
    405 
    406 					/* average read transfers
    407 					   (per second) */
    408 		(void)printf(" %6.0f", cur.rxfer[dn] / etime);
    409 
    410 					/* time read busy in drive activity */
    411 		atime = (double)cur.time[dn].tv_sec +
    412 		    ((double)cur.time[dn].tv_usec / (double)1000000);
    413 		(void)printf(" %6.2f", atime / etime);
    414 
    415 					/* average read megabytes
    416 					   (per second) */
    417 		(void)printf(" %8.2f",
    418 		    cur.rbytes[dn] / (1024.0 * 1024) / etime);
    419 
    420 
    421 					/* average write Kbytes per transfer */
    422 		if (cur.wxfer[dn])
    423 			kbps = (cur.wbytes[dn] / 1024.0) / cur.wxfer[dn];
    424 		else
    425 			kbps = 0.0;
    426 		(void)printf("   %8.2f", kbps);
    427 
    428 					/* average write transfers
    429 					   (per second) */
    430 		(void)printf(" %6.0f", cur.wxfer[dn] / etime);
    431 
    432 					/* time write busy in drive activity */
    433 		atime = (double)cur.time[dn].tv_sec +
    434 		    ((double)cur.time[dn].tv_usec / (double)1000000);
    435 		(void)printf(" %6.2f", atime / etime);
    436 
    437 					/* average write megabytes
    438 					   (per second) */
    439 		(void)printf(" %8.2f\n",
    440 		    cur.wbytes[dn] / (1024.0 * 1024) / etime);
    441 	}
    442 }
    443 
    444 static void
    445 drive_statsy_io(double elapsed, double count, double volume)
    446 {
    447 	double kbps;
    448 
    449 	/* average Kbytes per transfer */
    450 	if (count)
    451 		kbps = (volume / 1024.0) / count;
    452 	else
    453 		kbps = 0.0;
    454 	(void)printf(" %8.2f", kbps);
    455 
    456 	/* average transfers (per second) */
    457 	(void)printf(" %6.0f", count / elapsed);
    458 
    459 	/* average megabytes (per second) */
    460 	(void)printf(" %8.2f", volume / (1024.0 * 1024) / elapsed);
    461 }
    462 
    463 static void
    464 drive_statsy_q(double elapsed, double busy, double wait, double busysum, double waitsum, double count)
    465 {
    466 	/* average wait queue length */
    467 	(void)printf(" %6.1f", waitsum / elapsed);
    468 
    469 	/* average busy queue length */
    470 	(void)printf(" %6.1f", busysum / elapsed);
    471 
    472 	/* average wait time */
    473 	(void)printf(" %7.2f", count > 0 ? waitsum / count * 1000.0 : 0.0);
    474 
    475 	/* average service time */
    476 	(void)printf(" %7.2f", count > 0 ? busysum / count * 1000.0 : 0.0);
    477 
    478 	/* time waiting for drive activity */
    479 	(void)printf(" %6.2f", wait / elapsed);
    480 
    481 	/* time busy in drive activity */
    482 	(void)printf(" %6.2f", busy / elapsed);
    483 }
    484 
    485 static void
    486 drive_statsy(double etime)
    487 {
    488 	size_t dn;
    489 	double atime, await, abusysum, awaitsum;
    490 
    491 	for (dn = 0; dn < ndrive; ++dn) {
    492 		if (!cur.select[dn])
    493 			continue;
    494 
    495 		(void)printf("%-8.8s", cur.name[dn]);
    496 
    497 		atime = (double)cur.time[dn].tv_sec +
    498 		    ((double)cur.time[dn].tv_usec / (double)1000000);
    499 		await = (double)cur.wait[dn].tv_sec +
    500 		    ((double)cur.wait[dn].tv_usec / (double)1000000);
    501 		abusysum = (double)cur.busysum[dn].tv_sec +
    502 		    ((double)cur.busysum[dn].tv_usec / (double)1000000);
    503 		awaitsum = (double)cur.waitsum[dn].tv_sec +
    504 		    ((double)cur.waitsum[dn].tv_usec / (double)1000000);
    505 
    506 		drive_statsy_io(etime, cur.rxfer[dn], cur.rbytes[dn]);
    507 		(void)printf("  ");
    508 		drive_statsy_io(etime, cur.wxfer[dn], cur.wbytes[dn]);
    509 		drive_statsy_q(etime, atime, await, abusysum, awaitsum, cur.rxfer[dn]+cur.wxfer[dn]);
    510 
    511 		(void)printf("\n");
    512 	}
    513 }
    514 
    515 static void
    516 cpustats(void)
    517 {
    518 	int state;
    519 	double ttime;
    520 
    521 	ttime = 0;
    522 	for (state = 0; state < CPUSTATES; ++state)
    523 		ttime += cur.cp_time[state];
    524 	if (!ttime)
    525 		ttime = 1.0;
    526 			/* States are generally never 100% and can use %3.0f. */
    527 	for (state = 0; state < CPUSTATES; ++state)
    528 		printf(" %2.0f", 100. * cur.cp_time[state] / ttime);
    529 }
    530 
    531 static void
    532 usage(void)
    533 {
    534 
    535 	(void)fprintf(stderr, "usage: iostat [-CdDITxy] [-c count] "
    536 	    "[-w wait] [drives]\n");
    537 	exit(1);
    538 }
    539 
    540 static void
    541 display(void)
    542 {
    543 	double	etime;
    544 
    545 	/* Sum up the elapsed ticks. */
    546 	etime = cur.cp_etime;
    547 
    548 	/*
    549 	 * If we're showing totals only, then don't divide by the
    550 	 * system time.
    551 	 */
    552 	if (ISSET(todo, SHOW_TOTALS))
    553 		etime = 1.0;
    554 
    555 	if (ISSET(todo, SHOW_STATS_X)) {
    556 		drive_statsx(etime);
    557 		goto out;
    558 	}
    559 
    560 	if (ISSET(todo, SHOW_STATS_Y)) {
    561 		drive_statsy(etime);
    562 		goto out;
    563 	}
    564 
    565 	if (ISSET(todo, SHOW_TTY))
    566 		printf("%4.0f %5.0f", cur.tk_nin / etime, cur.tk_nout / etime);
    567 
    568 	if (ISSET(todo, SHOW_STATS_1)) {
    569 		drive_stats(etime);
    570 	}
    571 
    572 
    573 	if (ISSET(todo, SHOW_STATS_2)) {
    574 		drive_stats2(etime);
    575 	}
    576 
    577 
    578 	if (ISSET(todo, SHOW_CPU))
    579 		cpustats();
    580 
    581 	(void)printf("\n");
    582 
    583 out:
    584 	(void)fflush(stdout);
    585 }
    586 
    587 static int
    588 selectdrives(int argc, char *argv[])
    589 {
    590 	int	i, maxdrives, ndrives, tried;
    591 
    592 	/*
    593 	 * Choose drives to be displayed.  Priority goes to (in order) drives
    594 	 * supplied as arguments and default drives.  If everything isn't
    595 	 * filled in and there are drives not taken care of, display the first
    596 	 * few that fit.
    597 	 *
    598 	 * The backward compatibility #ifdefs permit the syntax:
    599 	 *	iostat [ drives ] [ interval [ count ] ]
    600 	 */
    601 
    602 #define	BACKWARD_COMPATIBILITY
    603 	for (tried = ndrives = 0; *argv; ++argv) {
    604 #ifdef BACKWARD_COMPATIBILITY
    605 		if (isdigit((unsigned char)**argv))
    606 			break;
    607 #endif
    608 		tried++;
    609 		for (i = 0; i < (int)ndrive; i++) {
    610 			if (fnmatch(*argv, cur.name[i], 0))
    611 				continue;
    612 			cur.select[i] = 1;
    613 			++ndrives;
    614 		}
    615 
    616 	}
    617 
    618 	if (ndrives == 0 && tried == 0) {
    619 		/*
    620 		 * Pick up to defdrives (or all if -x is given) drives
    621 		 * if none specified.
    622 		 */
    623 		maxdrives = (ISSET(todo, SHOW_STATS_X | SHOW_STATS_Y) ||
    624 			     (int)ndrive < defdrives)
    625 			? (int)(ndrive) : defdrives;
    626 		for (i = 0; i < maxdrives; i++) {
    627 			cur.select[i] = 1;
    628 
    629 			++ndrives;
    630 			if (!ISSET(todo, SHOW_STATS_X | SHOW_STATS_Y) &&
    631 			    ndrives == defdrives)
    632 				break;
    633 		}
    634 	}
    635 
    636 #ifdef BACKWARD_COMPATIBILITY
    637 	if (*argv) {
    638 		interval = atoi(*argv);
    639 		if (*++argv)
    640 			reps = atoi(*argv);
    641 	}
    642 #endif
    643 
    644 	if (interval) {
    645 		if (!reps)
    646 			reps = -1;
    647 	} else
    648 		if (reps)
    649 			interval = 1;
    650 
    651 	return (ndrives);
    652 }
    653