Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 21 Sep 2015 09:37:50 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r288059 - head/usr.bin/ctlstat
Message-ID:  <201509210937.t8L9boLW029009@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Mon Sep 21 09:37:49 2015
New Revision: 288059
URL: https://svnweb.freebsd.org/changeset/base/288059

Log:
  Bunch of improvements to ctlstat.
  
  Add -p option to allow filtering by ports.
  Make -l and -p options work in all modes as filters.
  Improve output formatting to better fit columns.

Modified:
  head/usr.bin/ctlstat/ctlstat.8
  head/usr.bin/ctlstat/ctlstat.c

Modified: head/usr.bin/ctlstat/ctlstat.8
==============================================================================
--- head/usr.bin/ctlstat/ctlstat.8	Mon Sep 21 08:44:23 2015	(r288058)
+++ head/usr.bin/ctlstat/ctlstat.8	Mon Sep 21 09:37:49 2015	(r288059)
@@ -34,7 +34,7 @@
 .\" $Id: //depot/users/kenm/FreeBSD-test2/usr.bin/ctlstat/ctlstat.8#2 $
 .\" $FreeBSD$
 .\"
-.Dd May 22, 2015
+.Dd September 21, 2015
 .Dt CTLSTAT 8
 .Os
 .Sh NAME
@@ -50,6 +50,7 @@
 .Op Fl j
 .Op Fl l Ar lun
 .Op Fl n Ar numdevs
+.Op Fl p Ar port
 .Op Fl w Ar wait
 .Sh DESCRIPTION
 The
@@ -64,7 +65,7 @@ The options are as follows:
 .Bl -tag -width 10n
 .It Fl t
 Total mode.
-This displays separate columns with the total CTL read and write output,
+This displays separate columns with the total read and write output,
 and a combined total column that also includes non I/O operations.
 .It Fl c Ar count
 Display statistics this many times.
@@ -74,23 +75,20 @@ Disable CPU statistics display.
 Display DMA operation time (latency) instead of overall I/O time (latency).
 .It Fl D
 Text dump mode.
-Dump all available statistics every 30 seconds in a text format suitable
-for parsing.
+Dump statistics every 30 seconds in a text format suitable for parsing.
 No statistics are computed in this mode, only raw numbers are displayed.
 .It Fl h
 Suppress display of the header.
 .It Fl j
 JSON dump mode.
-Dump all available statistics every 30 seconds in JavaScript Object
-Notation (JSON) format.
+Dump statistics every 30 seconds in JavaScript Object Notation (JSON) format.
 No statistics are computed in this mode, only raw numbers are displayed.
 .It Fl l Ar lun
 Request statistics for the specified LUN.
-This option is incompatible with total
-.Fl ( t )
-mode.
 .It Fl n Ar numdevs
 Display statistics for this many devices.
+.It Fl p Ar port
+Request statistics for the specified port.
 .It Fl w Ar wait
 Wait this many seconds in between displays.
 If this option is not specified,

Modified: head/usr.bin/ctlstat/ctlstat.c
==============================================================================
--- head/usr.bin/ctlstat/ctlstat.c	Mon Sep 21 08:44:23 2015	(r288058)
+++ head/usr.bin/ctlstat/ctlstat.c	Mon Sep 21 09:37:49 2015	(r288059)
@@ -78,7 +78,7 @@ __FBSDID("$FreeBSD$");
  */
 #define	CTL_STAT_LUN_BITS	1024L
 
-static const char *ctlstat_opts = "Cc:Ddhjl:n:tw:";
+static const char *ctlstat_opts = "Cc:Ddhjl:n:p:tw:";
 static const char *ctlstat_usage = "Usage:  ctlstat [-CDdjht] [-l lunnum]"
 				   "[-c count] [-n numdevs] [-w wait]\n";
 
@@ -102,12 +102,16 @@ typedef enum {
 #define	CTLSTAT_FLAG_TOTALS		(1 << 3)
 #define	CTLSTAT_FLAG_DMA_TIME		(1 << 4)
 #define	CTLSTAT_FLAG_LUN_TIME_VALID	(1 << 5)
+#define	CTLSTAT_FLAG_LUN_MASK		(1 << 6)
+#define	CTLSTAT_FLAG_PORT_MASK		(1 << 7)
 #define	F_CPU(ctx) ((ctx)->flags & CTLSTAT_FLAG_CPU)
 #define	F_HDR(ctx) ((ctx)->flags & CTLSTAT_FLAG_HEADER)
 #define	F_FIRST(ctx) ((ctx)->flags & CTLSTAT_FLAG_FIRST_RUN)
 #define	F_TOTALS(ctx) ((ctx)->flags & CTLSTAT_FLAG_TOTALS)
 #define	F_DMA(ctx) ((ctx)->flags & CTLSTAT_FLAG_DMA_TIME)
 #define	F_LUNVAL(ctx) ((ctx)->flags & CTLSTAT_FLAG_LUN_TIME_VALID)
+#define	F_LUNMASK(ctx) ((ctx)->flags & CTLSTAT_FLAG_LUN_MASK)
+#define	F_PORTMASK(ctx) ((ctx)->flags & CTLSTAT_FLAG_PORT_MASK)
 
 struct ctlstat_context {
 	ctlstat_mode_types mode;
@@ -120,6 +124,7 @@ struct ctlstat_context {
 	uint64_t cur_total_jiffies, prev_total_jiffies;
 	uint64_t cur_idle, prev_idle;
 	bitstr_t bit_decl(lun_mask, CTL_STAT_LUN_BITS);
+	bitstr_t bit_decl(port_mask, CTL_MAX_PORTS);
 	int num_luns;
 	int numdevs;
 	int header_interval;
@@ -133,7 +138,8 @@ static void usage(int error);
 static int getstats(int fd, int *num_luns, struct ctl_lun_io_stats **xlun_stats,
 		    struct timespec *cur_time, int *lun_time_valid);
 static int getcpu(struct ctl_cpu_stats *cpu_stats);
-static void compute_stats(struct ctl_lun_io_stats *cur_stats,
+static void compute_stats(struct ctlstat_context *ctx,
+			  struct ctl_lun_io_stats *cur_stats,
 			  struct ctl_lun_io_stats *prev_stats,
 			  long double etime, long double *mbsec,
 			  long double *kb_per_transfer,
@@ -234,7 +240,7 @@ getcpu(struct ctl_cpu_stats *cpu_stats)
 }
 
 static void
-compute_stats(struct ctl_lun_io_stats *cur_stats,
+compute_stats(struct ctlstat_context *ctx, struct ctl_lun_io_stats *cur_stats,
 	      struct ctl_lun_io_stats *prev_stats, long double etime,
 	      long double *mbsec, long double *kb_per_transfer,
 	      long double *transfers_per_second, long double *ms_per_transfer,
@@ -251,6 +257,9 @@ compute_stats(struct ctl_lun_io_stats *c
 	bzero(&total_time_ts, sizeof(total_time_ts));
 	bzero(&total_dma_ts, sizeof(total_dma_ts));
 	for (port = 0; port < CTL_MAX_PORTS; port++) {
+		if (F_PORTMASK(ctx) &&
+		    bit_test(ctx->port_mask, port) == 0)
+			continue;
 		for (i = 0; i < CTL_STATS_NUM_TYPES; i++) {
 			total_bytes += cur_stats->ports[port].bytes[i];
 			total_operations +=
@@ -336,8 +345,13 @@ ctlstat_dump(struct ctlstat_context *ctx
 	struct ctl_lun_io_stats *stats = ctx->cur_lun_stats;
 
 	for (lun = 0; lun < ctx->num_luns;lun++) {
+		if (F_LUNMASK(ctx) && bit_test(ctx->lun_mask, lun) == 0)
+			continue;
 		printf("lun %d\n", lun);
 		for (port = 0; port < CTL_MAX_PORTS; port++) {
+			if (F_PORTMASK(ctx) &&
+			    bit_test(ctx->port_mask, port) == 0)
+				continue;
 			printf(" port %d\n",
 			    stats[lun].ports[port].targ_port);
 			for (iotype = 0; iotype < CTL_STATS_NUM_TYPES;
@@ -369,8 +383,13 @@ ctlstat_json(struct ctlstat_context *ctx
 
 	printf("{\"luns\":[");
 	for (lun = 0; lun < ctx->num_luns; lun++) {
+		if (F_LUNMASK(ctx) && bit_test(ctx->lun_mask, lun) == 0)
+			continue;
 		printf("{\"ports\":[");
 		for (port = 0; port < CTL_MAX_PORTS;port++) {
+			if (F_PORTMASK(ctx) &&
+			    bit_test(ctx->port_mask, port) == 0)
+				continue;
 			printf("{\"num\":%d,\"io\":[",
 			    stats[lun].ports[port].targ_port);
 			for (iotype = 0; iotype < CTL_STATS_NUM_TYPES;
@@ -441,17 +460,16 @@ ctlstat_standard(struct ctlstat_context 
 
 			hdr_devs = 0;
 
+			if (F_CPU(ctx))
+				fprintf(stdout, " CPU");
 			if (F_TOTALS(ctx)) {
-				fprintf(stdout, "%s     System Read     %s"
-					"System Write     %sSystem Total%s\n",
-					(F_LUNVAL(ctx) != 0) ? "     " : "",
-					(F_LUNVAL(ctx) != 0) ? "     " : "",
-					(F_LUNVAL(ctx) != 0) ? "     " : "",
-					(F_CPU(ctx))   ? "    CPU" : "");
+				fprintf(stdout, "%s     Read       %s"
+					"    Write       %s    Total\n",
+					(F_LUNVAL(ctx) != 0) ? "      " : "",
+					(F_LUNVAL(ctx) != 0) ? "      " : "",
+					(F_LUNVAL(ctx) != 0) ? "      " : "");
 				hdr_devs = 3;
 			} else {
-				if (F_CPU(ctx))
-					fprintf(stdout, "  CPU  ");
 				for (i = 0; i < min(CTL_STAT_LUN_BITS,
 				     ctx->num_luns); i++) {
 					int lun;
@@ -464,7 +482,8 @@ ctlstat_standard(struct ctlstat_context 
 					lun = (int)ctx->cur_lun_stats[i
 						].lun_number;
 
-					if (bit_test(ctx->lun_mask, lun) == 0)
+					if (F_LUNMASK(ctx) &&
+					    bit_test(ctx->lun_mask, lun) == 0)
 						continue;
 					fprintf(stdout, "%15.6s%d %s",
 					    "lun", lun,
@@ -473,17 +492,19 @@ ctlstat_standard(struct ctlstat_context 
 				}
 				fprintf(stdout, "\n");
 			}
+			if (F_CPU(ctx))
+				fprintf(stdout, "    ");
 			for (i = 0; i < hdr_devs; i++)
-				fprintf(stdout, "%s  %sKB/t %s  MB/s ",
-					((F_CPU(ctx) != 0) && (i == 0) &&
-					(F_TOTALS(ctx) == 0)) ?  "       " : "",
-					(F_LUNVAL(ctx) != 0) ? " ms  " : "",
+				fprintf(stdout, "%s KB/t   %s MB/s",
+					(F_LUNVAL(ctx) != 0) ? "    ms" : "",
 					(F_DMA(ctx) == 0) ? "tps" : "dps");
 			fprintf(stdout, "\n");
 			ctx->header_interval = 20;
 		}
 	}
 
+	if (F_CPU(ctx))
+		fprintf(stdout, "%3.0Lf%%", cpu_percentage);
 	if (F_TOTALS(ctx) != 0) {
 		long double mbsec[3];
 		long double kb_per_transfer[3];
@@ -515,7 +536,13 @@ ctlstat_standard(struct ctlstat_context 
 	    &ctx->cur_lun_stats[i].ports[p].dma_time[j])
 
 		for (i = 0; i < ctx->num_luns; i++) {
+			if (F_LUNMASK(ctx) && bit_test(ctx->lun_mask,
+			    (int)ctx->cur_lun_stats[i].lun_number) == 0)
+				continue;
 			for (port = 0; port < CTL_MAX_PORTS; port++) {
+				if (F_PORTMASK(ctx) &&
+				    bit_test(ctx->port_mask, port) == 0)
+					continue;
 				for (j = 0; j < CTL_STATS_NUM_TYPES; j++) {
 					ADD_STATS_BYTES(2, port, i, j);
 					ADD_STATS_OPERATIONS(2, port, i, j);
@@ -540,29 +567,24 @@ ctlstat_standard(struct ctlstat_context 
 		}
 
 		for (i = 0; i < 3; i++) {
-			compute_stats(&ctx->cur_total_stats[i],
+			compute_stats(ctx, &ctx->cur_total_stats[i],
 				F_FIRST(ctx) ? NULL : &ctx->prev_total_stats[i],
 				etime, &mbsec[i], &kb_per_transfer[i],
 				&transfers_per_sec[i],
 				&ms_per_transfer[i], &ms_per_dma[i],
 				&dmas_per_sec[i]);
 			if (F_DMA(ctx) != 0)
-				fprintf(stdout, " %2.2Lf",
+				fprintf(stdout, " %5.1Lf",
 					ms_per_dma[i]);
 			else if (F_LUNVAL(ctx) != 0)
-				fprintf(stdout, " %2.2Lf",
+				fprintf(stdout, " %5.1Lf",
 					ms_per_transfer[i]);
-			fprintf(stdout, " %5.2Lf %3.0Lf %5.2Lf ",
+			fprintf(stdout, " %4.0Lf %5.0Lf %4.0Lf",
 				kb_per_transfer[i],
 				(F_DMA(ctx) == 0) ? transfers_per_sec[i] :
 				dmas_per_sec[i], mbsec[i]);
 		}
-		if (F_CPU(ctx))
-			fprintf(stdout, " %5.1Lf%%", cpu_percentage);
 	} else {
-		if (F_CPU(ctx))
-			fprintf(stdout, "%5.1Lf%% ", cpu_percentage);
-
 		for (i = 0; i < min(CTL_STAT_LUN_BITS, ctx->num_luns); i++) {
 			long double mbsec, kb_per_transfer;
 			long double transfers_per_sec;
@@ -570,21 +592,21 @@ ctlstat_standard(struct ctlstat_context 
 			long double ms_per_dma;
 			long double dmas_per_sec;
 
-			if (bit_test(ctx->lun_mask,
+			if (F_LUNMASK(ctx) && bit_test(ctx->lun_mask,
 			    (int)ctx->cur_lun_stats[i].lun_number) == 0)
 				continue;
-			compute_stats(&ctx->cur_lun_stats[i], F_FIRST(ctx) ?
-				NULL : &ctx->prev_lun_stats[i], etime,
-				&mbsec, &kb_per_transfer,
-				&transfers_per_sec, &ms_per_transfer,
-				&ms_per_dma, &dmas_per_sec);
+			compute_stats(ctx, &ctx->cur_lun_stats[i],
+			    F_FIRST(ctx) ? NULL : &ctx->prev_lun_stats[i],
+			    etime, &mbsec, &kb_per_transfer,
+			    &transfers_per_sec, &ms_per_transfer,
+			    &ms_per_dma, &dmas_per_sec);
 			if (F_DMA(ctx))
-				fprintf(stdout, " %2.2Lf",
+				fprintf(stdout, " %5.1Lf",
 					ms_per_dma);
 			else if (F_LUNVAL(ctx) != 0)
-				fprintf(stdout, " %2.2Lf",
+				fprintf(stdout, " %5.1Lf",
 					ms_per_transfer);
-			fprintf(stdout, " %5.2Lf %3.0Lf %5.2Lf ",
+			fprintf(stdout, " %4.0Lf %5.0Lf %4.0Lf",
 				kb_per_transfer, (F_DMA(ctx) == 0) ?
 				transfers_per_sec : dmas_per_sec, mbsec);
 		}
@@ -596,7 +618,6 @@ main(int argc, char **argv)
 {
 	int c;
 	int count, waittime;
-	int set_lun;
 	int fd, retval;
 	struct ctlstat_context ctx;
 
@@ -640,20 +661,30 @@ main(int argc, char **argv)
 			if (cur_lun > CTL_STAT_LUN_BITS)
 				errx(1, "Invalid LUN number %d", cur_lun);
 
-			bit_ffs(ctx.lun_mask, CTL_STAT_LUN_BITS, &set_lun);
-			if (set_lun == -1)
+			if (!F_LUNMASK(&ctx))
 				ctx.numdevs = 1;
 			else
 				ctx.numdevs++;
 			bit_set(ctx.lun_mask, cur_lun);
+			ctx.flags |= CTLSTAT_FLAG_LUN_MASK;
 			break;
 		}
 		case 'n':
 			ctx.numdevs = atoi(optarg);
 			break;
+		case 'p': {
+			int cur_port;
+
+			cur_port = atoi(optarg);
+			if (cur_port > CTL_MAX_PORTS)
+				errx(1, "Invalid LUN number %d", cur_port);
+
+			bit_set(ctx.port_mask, cur_port);
+			ctx.flags |= CTLSTAT_FLAG_PORT_MASK;
+			break;
+		}
 		case 't':
 			ctx.flags |= CTLSTAT_FLAG_TOTALS;
-			ctx.numdevs = 3;
 			break;
 		case 'w':
 			waittime = atoi(optarg);
@@ -666,13 +697,7 @@ main(int argc, char **argv)
 		}
 	}
 
-	bit_ffs(ctx.lun_mask, CTL_STAT_LUN_BITS, &set_lun);
-
-	if ((F_TOTALS(&ctx))
-	 && (set_lun != -1)) {
-		errx(1, "Total Mode (-t) is incompatible with individual "
-		     "LUN mode (-l)");
-	} else if (set_lun == -1) {
+	if (!F_TOTALS(&ctx) && !F_LUNMASK(&ctx)) {
 		/*
 		 * Note that this just selects the first N LUNs to display,
 		 * but at this point we have no knoweledge of which LUN
@@ -681,6 +706,7 @@ main(int argc, char **argv)
 		 */
 		bit_nset(ctx.lun_mask, 0, min(ctx.numdevs - 1,
 			 CTL_STAT_LUN_BITS - 1));
+		ctx.flags |= CTLSTAT_FLAG_LUN_MASK;
 	}
 
 	if ((fd = open(CTL_DEFAULT_DEV, O_RDWR)) == -1)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201509210937.t8L9boLW029009>