diff options
author | maxim <maxim@FreeBSD.org> | 2006-04-16 22:23:39 +0000 |
---|---|---|
committer | maxim <maxim@FreeBSD.org> | 2006-04-16 22:23:39 +0000 |
commit | c6cab9cc4821e37f776ac01cb7a920b0c3428238 (patch) | |
tree | 28fbbd400afef6293d7c8c9726d7b465d613fcf6 | |
parent | 4a3ab050f7810df3bf3af7566f7cf491870076ce (diff) | |
download | FreeBSD-src-c6cab9cc4821e37f776ac01cb7a920b0c3428238.zip FreeBSD-src-c6cab9cc4821e37f776ac01cb7a920b0c3428238.tar.gz |
o Implement Solaris-like -x flag: show extended disk statistics.
o Implement Solaris-like -z flag: omit lines for devices with no activity.
o iostat.8: describe -x and -z flags, Xr devstat(3), touch .Dd.
PR: mostly bin/68840, with style changes; bin/73327
Submitted by: Dan Nelson, Peter Schuller
Obtained from: NetBSD (a part of man page)
MFC after: 1 month
-rw-r--r-- | usr.sbin/iostat/iostat.8 | 35 | ||||
-rw-r--r-- | usr.sbin/iostat/iostat.c | 116 |
2 files changed, 136 insertions, 15 deletions
diff --git a/usr.sbin/iostat/iostat.8 b/usr.sbin/iostat/iostat.8 index be66c7c..8aeb833 100644 --- a/usr.sbin/iostat/iostat.8 +++ b/usr.sbin/iostat/iostat.8 @@ -60,7 +60,7 @@ .\" .\" @(#)iostat.8 8.1 (Berkeley) 6/6/93 .\" -.Dd December 22, 1997 +.Dd April 17, 2006 .Dt IOSTAT 8 .Os .Sh NAME @@ -70,7 +70,7 @@ statistics .Sh SYNOPSIS .Nm -.Op Fl CdhKIoT?\& +.Op Fl CdhKIoTxz?\& .Op Fl c Ar count .Op Fl M Ar core .Op Fl n Ar devs @@ -239,6 +239,13 @@ seconds between each display. If no repeat .Ar count is specified, the default is infinity. +.It Fl x +Show extended disk statistics. +Each disk is displayed on a line of its own with all available statistics. +.It Fl z +If +.Fl x +is specified, omit lines for devices with no activity. .It Fl ?\& Display a usage statement and exit. .El @@ -313,6 +320,29 @@ total number of transfers total number of megabytes transferred .El .Pp +The extended +.Nm +device display, with the +.Fl x +flag specified, shows the following statistics: +.Pp +.Bl -tag -width indent -compact +.It r/s +read operations per second +.It w/s +write operations per second +.It kr/s +kilobytes read per second +.It kw/s +kilobytes write per second +.It wait +transactions queue length +.It svc_t +average duration of transactions, in milliseconds +.It %b +% of time the device had one or more outstanding transactions +.El +.Pp The old-style .Nm display (using @@ -414,6 +444,7 @@ flags are given, the TTY and CPU displays will be displayed. .Xr nfsstat 1 , .Xr ps 1 , .Xr systat 1 , +.Xr devstat 3 , .Xr gstat 8 , .Xr pstat 8 , .Xr vmstat 8 diff --git a/usr.sbin/iostat/iostat.c b/usr.sbin/iostat/iostat.c index 724756e..3abf8cc 100644 --- a/usr.sbin/iostat/iostat.c +++ b/usr.sbin/iostat/iostat.c @@ -137,6 +137,7 @@ struct device_selection *dev_select; int maxshowdevs; volatile sig_atomic_t headercount; int dflag = 0, Iflag = 0, Cflag = 0, Tflag = 0, oflag = 0, Kflag = 0; +int xflag = 0, zflag = 0; /* local function declarations */ static void usage(void); @@ -156,7 +157,7 @@ usage(void) * This isn't mentioned in the man page, or the usage statement, * but it is supported. */ - fprintf(stderr, "usage: iostat [-CdhIKoT?] [-c count] [-M core]" + fprintf(stderr, "usage: iostat [-CdhIKoTxz?] [-c count] [-M core]" " [-n devs] [-N system]\n" "\t [-t type,if,pass] [-w wait] [drives]\n"); } @@ -184,7 +185,7 @@ main(int argc, char **argv) matches = NULL; maxshowdevs = 3; - while ((c = getopt(argc, argv, "c:CdhIKM:n:N:ot:Tw:?")) != -1) { + while ((c = getopt(argc, argv, "c:CdhIKM:n:N:ot:Tw:xz?")) != -1) { switch(c) { case 'c': cflag++; @@ -238,6 +239,12 @@ main(int argc, char **argv) if (waittime < 1) errx(1, "wait time is < 1"); break; + case 'x': + xflag++; + break; + case 'z': + zflag++; + break; default: usage(); exit(1); @@ -270,7 +277,7 @@ main(int argc, char **argv) * Make sure Tflag and/or Cflag are set if dflag == 0. If dflag is * greater than 0, they may be 0 or non-zero. */ - if (dflag == 0) { + if (dflag == 0 && xflag == 0) { Cflag = 1; Tflag = 1; } @@ -547,16 +554,18 @@ main(int argc, char **argv) last.cp_time[i] = tmp; } - if (Tflag > 0) - printf("%4.0Lf%5.0Lf", cur.tk_nin / etime, - cur.tk_nout/etime); + if (xflag == 0 && Tflag > 0) + printf("%4.0Lf%5.0Lf", cur.tk_nin / etime, + cur.tk_nout / etime); devstats(hflag, etime, havelast); - if (Cflag > 0) - cpustats(); + if (xflag == 0) { + if (Cflag > 0) + cpustats(); - printf("\n"); + printf("\n"); + } fflush(stdout); if (count >= 0 && --count <= 0) @@ -584,6 +593,13 @@ phdr(void) { register int i; int printed; + + /* + * If xflag is set, we need a per-loop header, not a page header, so + * just return. We'll print the header in devstats(). + */ + if (xflag > 0) + return; if (Tflag > 0) (void)printf(" tty"); @@ -639,11 +655,30 @@ static void devstats(int perf_select, long double etime, int havelast) { register int dn; - long double transfers_per_second; - long double kb_per_transfer, mb_per_second; + long double transfers_per_second, transfers_per_second_read, transfers_per_second_write; + long double kb_per_transfer, mb_per_second, mb_per_second_read, mb_per_second_write; u_int64_t total_bytes, total_transfers, total_blocks; + long double busy_pct; + u_int64_t queue_len; long double total_mb; long double blocks_per_second, ms_per_transaction; + int firstline = 1; + char *devname; + + if (xflag > 0) { + printf(" extended device statistics "); + if (Tflag > 0) + printf(" tty "); + if (Cflag > 0) + printf(" cpu "); + printf("\n"); + printf("device r/s w/s kr/s kw/s wait svc_t %%b "); + if (Tflag > 0) + printf("tin tout "); + if (Cflag > 0) + printf("us ni sy in id "); + printf("\n"); + } for (dn = 0; dn < num_devices; dn++) { int di; @@ -661,9 +696,15 @@ devstats(int perf_select, long double etime, int havelast) DSM_TOTAL_BLOCKS, &total_blocks, DSM_KB_PER_TRANSFER, &kb_per_transfer, DSM_TRANSFERS_PER_SECOND, &transfers_per_second, + DSM_TRANSFERS_PER_SECOND_READ, &transfers_per_second_read, + DSM_TRANSFERS_PER_SECOND_WRITE, &transfers_per_second_write, DSM_MB_PER_SECOND, &mb_per_second, + DSM_MB_PER_SECOND_READ, &mb_per_second_read, + DSM_MB_PER_SECOND_WRITE, &mb_per_second_write, DSM_BLOCKS_PER_SECOND, &blocks_per_second, DSM_MS_PER_TRANSACTION, &ms_per_transaction, + DSM_BUSY_PCT, &busy_pct, + DSM_QUEUE_LENGTH, &queue_len, DSM_NONE) != 0) errx(1, "%s", devstat_errbuf); @@ -674,13 +715,47 @@ devstats(int perf_select, long double etime, int havelast) continue; } - if (Kflag) { + if (Kflag > 0 || xflag > 0) { int block_size = cur.dinfo->devices[di].block_size; total_blocks = total_blocks * (block_size ? block_size : 512) / 1024; } - if (oflag > 0) { + if (xflag > 0) { + asprintf(&devname, "%s%d", + cur.dinfo->devices[di].device_name, + cur.dinfo->devices[di].unit_number); + /* + * If zflag is set, skip any devices with zero I/O. + */ + if (zflag == 0 || transfers_per_second_read > 0.05 || + transfers_per_second_write > 0.05 || + mb_per_second_read > ((long double).0005)/1024 || + mb_per_second_write > ((long double).0005)/1024 || + busy_pct > 0.5) { + printf("%-8.8s %5.1Lf %5.1Lf %7.1Lf %7.1Lf %4qu %5.1Lf %3.0Lf ", + devname, transfers_per_second_read, + transfers_per_second_write, + mb_per_second_read * 1024, + mb_per_second_write * 1024, queue_len, + ms_per_transaction, busy_pct); + if (firstline) { + /* + * If this is the first device + * we're printing, also print + * CPU or TTY stats if requested. + */ + firstline = 0; + if (Tflag > 0) + printf("%4.0Lf%5.0Lf", + cur.tk_nin / etime, + cur.tk_nout / etime); + if (Cflag > 0) + cpustats(); + } + printf("\n"); + } + } else if (oflag > 0) { int msdig = (ms_per_transaction < 100.0) ? 1 : 0; if (Iflag == 0) @@ -712,6 +787,21 @@ devstats(int perf_select, long double etime, int havelast) } } } + if (xflag > 0 && zflag > 0 && firstline == 1 && + (Tflag > 0 || Cflag > 0)) { + /* + * If zflag is set and we did not print any device + * lines I/O because they were all zero, + * print TTY/CPU stats. + */ + printf("%52s",""); + if (Tflag > 0) + printf("%4.0Lf%5.0Lf", cur.tk_nin / etime, + cur.tk_nout / etime); + if (Cflag > 0) + cpustats(); + printf("\n"); + } } static void |