bin/73327: [PATCH] iostat - extended mode display

Peter Schuller peter.schuller at infidyne.com
Sat Oct 30 15:01:07 PDT 2004


>Number:         73327
>Category:       bin
>Synopsis:       [PATCH] iostat - extended mode display
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sat Oct 30 22:01:06 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     peter.schuller at infidyne.com
>Release:        FreeBSD 5.2.1-RELEASE-p9 i386
>Organization:
<org>
>Environment:
System: FreeBSD scode-whitestar.mine.nu 5.2.1-RELEASE-p9 FreeBSD 5.2.1-RELEASE-p9 #9: Sat Jul 3 17:14:56 CEST 2004 toor at scode-whitestar.mine.nu:/usr/obj/usr/src/sys/WHITESTAR i386


	FreeBSD 5.2.1
>Description:
	FreeBSD's iostat lacks "extended" output (ala NetBSD's -x and the default
	on newer GNU systems). A one-device-per-line mode is very useful on systems
	with many devices. On such systems it is currently difficult to get an
	overall view of I/O activity using iostat.OB
>How-To-Repeat:
>Fix:
	The attached patches add a -x option to iostat and updates the manpage
	accordingly. In addition to showing devices on individual lines, extended
	mode also displayes read/write (in addition to total) statistics. The layout
	was also adjusted to accommodate larger values that are common on modern
	systems.

--- patch-iostat.c begins here ---
--- iostat_53.c	Sat Oct 30 21:35:44 2004
+++ iostat.c	Sat Oct 30 23:03:04 2004
@@ -136,7 +136,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 dflag = 0, Iflag = 0, Cflag = 0, Tflag = 0, oflag = 0, Kflag = 0, xflag = 0;
 
 /* local function declarations */
 static void usage(void);
@@ -184,7 +184,7 @@
 	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:Txw:?")) != -1) {
 		switch(c) {
 			case 'c':
 				cflag++;
@@ -232,6 +232,10 @@
 			case 'T':
 				Tflag++;
 				break;
+			case 'x':
+				xflag++;
+				dflag++;
+				break;
 			case 'w':
 				wflag++;
 				waittime = atoi(optarg);
@@ -279,18 +283,22 @@
 	 * Figure out how many devices we should display.
 	 */
 	if (nflag == 0) {
-		if (oflag > 0) {
-			if ((dflag > 0) && (Cflag == 0) && (Tflag == 0))
-				maxshowdevs = 5;
-			else if ((dflag > 0) && (Tflag > 0) && (Cflag == 0))
-				maxshowdevs = 5;
-			else
-				maxshowdevs = 4;
+		if (xflag > 0) {
+			maxshowdevs = 20; /* Suitable for 25 line screens */
 		} else {
-			if ((dflag > 0) && (Cflag == 0))
-				maxshowdevs = 4;		
-			else
-				maxshowdevs = 3;
+			if (oflag > 0) {
+				if ((dflag > 0) && (Cflag == 0) && (Tflag == 0))
+					maxshowdevs = 5;
+				else if ((dflag > 0) && (Tflag > 0) && (Cflag == 0))
+					maxshowdevs = 5;
+				else
+					maxshowdevs = 4;
+			} else {
+				if ((dflag > 0) && (Cflag == 0))
+					maxshowdevs = 4;		
+				else
+					maxshowdevs = 3;
+			}
 		}
 	}
 
@@ -441,7 +449,7 @@
 			}
 		}
 
-		if (!--headercount) {
+		if (!--headercount || xflag > 0) {
 			phdr();
 			headercount = 20;
 		}
@@ -587,20 +595,22 @@
 
 	if (Tflag > 0)
 		(void)printf("      tty");
-	for (i = 0, printed=0;(i < num_devices) && (printed < maxshowdevs);i++){
-		int di;
-		if ((dev_select[i].selected != 0)
-		 && (dev_select[i].selected <= maxshowdevs)) {
-			di = dev_select[i].position;
-			if (oflag > 0)
-				(void)printf("%12.6s%d ", 
-					    cur.dinfo->devices[di].device_name,
-					    cur.dinfo->devices[di].unit_number);
-			else
-				printf("%15.6s%d ",
-					    cur.dinfo->devices[di].device_name,
-					    cur.dinfo->devices[di].unit_number);
-			printed++;
+	if (xflag == 0) {
+		for (i = 0, printed=0;(i < num_devices) && (printed < maxshowdevs);i++){
+			int di;
+			if ((dev_select[i].selected != 0)
+			 && (dev_select[i].selected <= maxshowdevs)) {
+				di = dev_select[i].position;
+				if (oflag > 0)
+					(void)printf("%12.6s%d ", 
+						    cur.dinfo->devices[di].device_name,
+						    cur.dinfo->devices[di].unit_number);
+				else
+					printf("%15.6s%d ",
+						    cur.dinfo->devices[di].device_name,
+						    cur.dinfo->devices[di].unit_number);
+				printed++;
+			}
 		}
 	}
 	if (Cflag > 0)
@@ -611,21 +621,35 @@
 	if (Tflag > 0)
 		(void)printf(" tin tout");
 
-	for (i=0, printed = 0;(i < num_devices) && (printed < maxshowdevs);i++){
-		if ((dev_select[i].selected != 0)
-		 && (dev_select[i].selected <= maxshowdevs)) {
-			if (oflag > 0) {
-				if (Iflag == 0)
-					(void)printf(" sps tps msps ");
-				else
-					(void)printf(" blk xfr msps ");
-			} else {
-				if (Iflag == 0)
-					printf("  KB/t tps  MB/s ");
-				else
-					printf("  KB/t xfrs   MB ");
+	if (xflag > 0) {
+		if (oflag > 0) {
+			if (Iflag == 0)
+				printf("          dev  sps   r   w  tps msps");
+			else
+				printf("          dev  blk   r   w  xfr msps");
+		} else {
+			if (Iflag == 0)
+				printf("          dev      KB/t      tps     MB/s    MBr/s    MRw/s");
+			else
+				printf("          dev      KB/t     xfrs       MB      MBr      MBw");
+		}
+	} else {
+		for (i=0, printed = 0;(i < num_devices) && (printed < maxshowdevs);i++){
+			if ((dev_select[i].selected != 0)
+			 && (dev_select[i].selected <= maxshowdevs)) {
+				if (oflag > 0) {
+					if (Iflag == 0)
+						(void)printf(" sps tps msps ");
+					else
+						(void)printf(" blk xfr msps ");
+				} else {
+					if (Iflag == 0)
+						printf("  KB/t tps  MB/s ");
+					else
+						printf("  KB/t xfrs   MB ");
+				}
+				printed++;
 			}
-			printed++;
 		}
 	}
 	if (Cflag > 0)
@@ -641,10 +665,16 @@
 	register int dn;
 	long double transfers_per_second;
 	long double kb_per_transfer, mb_per_second;
+	long double mb_per_second_read, mb_per_second_write;
 	u_int64_t total_bytes, total_transfers, total_blocks;
-	long double total_mb;
+	u_int64_t total_bytes_read;
+	u_int64_t total_blocks_read;
+	u_int64_t total_bytes_write;
+	u_int64_t total_blocks_write;
+	long double total_mb, total_mb_read, total_mb_write;
 	long double blocks_per_second, ms_per_transaction;
-	
+	long double blocks_per_second_read, blocks_per_second_write;
+
 	for (dn = 0; dn < num_devices; dn++) {
 		int di;
 
@@ -657,12 +687,20 @@
 		if (devstat_compute_statistics(&cur.dinfo->devices[di],
 		    havelast ? &last.dinfo->devices[di] : NULL, etime,
 		    DSM_TOTAL_BYTES, &total_bytes,
+		    DSM_TOTAL_BYTES_READ, &total_bytes_read,
+		    DSM_TOTAL_BYTES_WRITE, &total_bytes_write,
 		    DSM_TOTAL_TRANSFERS, &total_transfers,
 		    DSM_TOTAL_BLOCKS, &total_blocks,
+		    DSM_TOTAL_BLOCKS_READ, &total_blocks_read,
+		    DSM_TOTAL_BLOCKS_WRITE, &total_blocks_write,
 		    DSM_KB_PER_TRANSFER, &kb_per_transfer,
 		    DSM_TRANSFERS_PER_SECOND, &transfers_per_second,
-		    DSM_MB_PER_SECOND, &mb_per_second, 
+		    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_BLOCKS_PER_SECOND_READ, &blocks_per_second_read,
+		    DSM_BLOCKS_PER_SECOND_WRITE, &blocks_per_second_write,
 		    DSM_MS_PER_TRANSACTION, &ms_per_transaction,
 		    DSM_NONE) != 0)
 			errx(1, "%s", devstat_errbuf);
@@ -684,31 +722,82 @@
 			int msdig = (ms_per_transaction < 100.0) ? 1 : 0;
 
 			if (Iflag == 0)
-				printf("%4.0Lf%4.0Lf%5.*Lf ",
-				       blocks_per_second,
-				       transfers_per_second,
-				       msdig,
-				       ms_per_transaction);
-			else 
-				printf("%4.1qu%4.1qu%5.*Lf ",
-				       total_blocks,
-				       total_transfers,
-				       msdig,
-				       ms_per_transaction);
+				if (xflag == 0) {
+					printf("%4.0Lf%4.0Lf%5.*Lf ",
+					       blocks_per_second,
+					       transfers_per_second,
+					       msdig,
+					       ms_per_transaction);
+				} else {
+					printf("%12.6s%d %8.0Lf%8.0Lf%8.0Lf%8.0Lf%8.*Lf\n",
+					       dev_select[dn].device_name,
+					       dev_select[dn].unit_number,
+					       blocks_per_second,
+					       blocks_per_second_read,
+					       blocks_per_second_write,
+					       transfers_per_second,
+					       msdig,
+					       ms_per_transaction);
+				}
+			else {
+				if (xflag == 0) {
+					printf("%4.1qu%4.1qu%5.*Lf ",
+					       total_blocks,
+					       total_transfers,
+					       msdig,
+					       ms_per_transaction);
+				} else {
+					printf("%12.6s%d %8.1qu%8.1qu%8.1qu%8.1qu%8.*Lf\n",
+					       dev_select[dn].device_name,
+					       dev_select[dn].unit_number,
+					       total_blocks,
+					       total_blocks_read,
+					       total_blocks_write,
+					       total_transfers,
+					       msdig,
+					       ms_per_transaction);
+				}
+			}
 		} else {
 			if (Iflag == 0)
-				printf(" %5.2Lf %3.0Lf %5.2Lf ", 
-				       kb_per_transfer,
-				       transfers_per_second,
-				       mb_per_second);
+				if (xflag == 0) {
+					printf(" %5.2Lf %3.0Lf %5.2Lf ", 
+					       kb_per_transfer,
+				      	       transfers_per_second,
+				     	       mb_per_second);
+				} else {
+					printf("%12.6s%d  %8.2Lf %8.0Lf %8.2Lf %8.2Lf %8.2Lf\n",
+					       dev_select[dn].device_name,
+					       dev_select[dn].unit_number,
+					       kb_per_transfer,
+					       transfers_per_second,
+					       mb_per_second,
+					       mb_per_second_read,
+					       mb_per_second_write);
+				}
 			else {
 				total_mb = total_bytes;
 				total_mb /= 1024 * 1024;
-
-				printf(" %5.2Lf %3.1qu %5.2Lf ", 
-				       kb_per_transfer,
-				       total_transfers,
-				       total_mb);
+				
+				if (xflag == 0) {
+					printf(" %5.2Lf %3.1qu %5.2Lf ", 
+					       kb_per_transfer,
+					       total_transfers,
+					       total_mb);
+				} else {
+					total_mb_read = total_bytes_read;
+					total_mb_read /= 1024 * 1024;
+					total_mb_write = total_bytes_write;
+					total_mb_write /= 1024 * 1024;
+					printf("%12.6s%d  %8.2Lf %8.1qu %8.2Lf %8.2Lf %8.2Lf\n",
+					       dev_select[dn].device_name,
+					       dev_select[dn].unit_number,
+					       kb_per_transfer,
+					       total_transfers,
+					       total_mb,
+					       total_mb_read,
+					       total_mb_write);
+				}
 			}
 		}
 	}
--- patch-iostat.c ends here ---

--- patch-iostat.8 begins here ---
--- iostat_53.8	Sat Oct 30 21:52:01 2004
+++ iostat.8	Sat Oct 30 23:07:07 2004
@@ -107,10 +107,16 @@
 Display CPU statistics.
 This is on by default, unless
 .Fl d
-is specified.
+is specified. If
+.Fl x
+is specified, this option has no effect.
 .It Fl d
-Display only device statistics.
-If this flag is turned on, only device statistics will be displayed, unless
+Display only device statistics. Default if
+.Fl x
+is specified.
+If this flag is turned on, only device statistics will be displayed unless
+.Fl x
+is NOT specified and
 .Fl C
 or
 .Fl T
@@ -231,7 +237,15 @@
 Display TTY statistics.
 This is on by default, unless
 .Fl d
+or
+.Fl x
 is specified.
+.It Fl x
+Show extended statistics. Implies -d. By default up to 20 devices
+are shown. In this mode each device is displayed on a line of its
+own and the header is printed at each update. The layout is also
+slightly adjusted to accommodate larger values. Individual read
+and write statistics are printed in addition to the totals.
 .It Fl w
 Pause
 .Ar wait
--- patch-iostat.8 ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list