[PATCH] blkparse: add core-based binary file output option to blkparse

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: luye <luye.yelu@xxxxxxxxxxxxx>

Add a new option -c to support core-based binary file output.
One binary output file would be generated for each CPU core if enabled.

Signed-off-by: luye <luye.yelu@xxxxxxxxxxxxx>
---
 README     |  1 +
 blkparse.c | 72 ++++++++++++++++++++++++++++++++++++++++++++----------
 blktrace.h |  1 +
 3 files changed, 61 insertions(+), 13 deletions(-)

diff --git a/README b/README
index d7d1fbf..2c0f09b 100644
--- a/README
+++ b/README
@@ -86,6 +86,7 @@ $ blkparse -i <input> [ -o <output> ] [ -b rb_batch ] [ -s ] [ -t ] [ -q ]
 	-w Only parse data between the given time interval in seconds. If
 	   'start' isn't given, blkparse defaults the start time to 0.
 	-d Dump sorted data in binary format
+	-c Dump sorted data in binary format, one binary file for each CPU core
 	-f Output format. Customize the output format. The format field
 	   identifiers are:
 
diff --git a/blkparse.c b/blkparse.c
index 33dd023..17d9e14 100644
--- a/blkparse.c
+++ b/blkparse.c
@@ -233,6 +233,12 @@ static struct option l_opts[] = {
 		.flag = NULL,
 		.val = 'V'
 	},
+    {
+ 	    .name = "cpu-based-output",
+ 	    .has_arg = no_argument,
+ 	    .flag = NULL,
+ 	    .val = 'c'
+    },
 	{
 		.name = NULL,
 	}
@@ -301,6 +307,7 @@ static int verbose;
 static unsigned int act_mask = -1U;
 static int stats_printed;
 static int bin_output_msgs = 1;
+static int dump_binary_cpu_based = 0;
 int data_is_native = -1;
 
 static FILE *dump_fp;
@@ -346,13 +353,13 @@ static void io_warn_unless(struct blk_io_trace *t, int condition,
 	va_end(ap);
 }
 
-static void output_binary(void *buf, int len)
+static void output_binary(void *buf, int len, FILE *fp)
 {
-	if (dump_binary) {
-		size_t n = fwrite(buf, len, 1, dump_fp);
+	if (dump_binary || dump_binary_cpu_based) {
+		size_t n = fwrite(buf, len, 1, fp);
 		if (n != 1) {
 			perror(dump_binary);
-			fclose(dump_fp);
+			fclose(fp);
 			dump_binary = NULL;
 		}
 	}
@@ -1759,9 +1766,13 @@ static void dump_trace(struct blk_io_trace *t, struct per_cpu_info *pci,
 	pdi->events++;
 
 	if (bin_output_msgs ||
-			    !(t->action & BLK_TC_ACT(BLK_TC_NOTIFY) &&
-			      (t->action & ~__BLK_TN_CGROUP) == BLK_TN_MESSAGE))
-		output_binary(t, sizeof(*t) + t->pdu_len);
+		!(t->action & BLK_TC_ACT(BLK_TC_NOTIFY) &&
+		(t->action & ~__BLK_TN_CGROUP) == BLK_TN_MESSAGE)) {
+			if (dump_binary_cpu_based)
+				output_binary(t, sizeof(*t) + t->pdu_len, pci->out_bin);
+			else
+				output_binary(t, sizeof(*t) + t->pdu_len, dump_fp);
+	}
 }
 
 /*
@@ -2484,7 +2495,7 @@ static int read_events(int fd, int always_block, int *fdblock)
 		 */
 		if (bit->action & BLK_TC_ACT(BLK_TC_NOTIFY) && (bit->action & ~__BLK_TN_CGROUP) != BLK_TN_MESSAGE) {
 			handle_notify(bit);
-			output_binary(bit, sizeof(*bit) + bit->pdu_len);
+			output_binary(bit, sizeof(*bit) + bit->pdu_len, dump_fp);
 			continue;
 		}
 
@@ -2633,7 +2644,7 @@ static int ms_prime(struct ms_stream *msp)
 
 		if (bit->action & BLK_TC_ACT(BLK_TC_NOTIFY) && (bit->action & ~__BLK_TN_CGROUP) != BLK_TN_MESSAGE) {
 			handle_notify(bit);
-			output_binary(bit, sizeof(*bit) + bit->pdu_len);
+			output_binary(bit, sizeof(*bit) + bit->pdu_len, pci->out_bin);
 			bit_free(bit);
 
 			i -= 1;
@@ -2719,6 +2730,25 @@ static int setup_file(struct per_dev_info *pdi, int cpu)
 		return 0;
 	}
 
+	/*
+	 * Prepare for cpu-based binary output file
+	 */
+	if (dump_binary_cpu_based) {
+		char fname[PATH_MAX];
+		if (input_dir)
+			sprintf(fname, "%s/", input_dir);
+
+		snprintf(fname + len, sizeof(pci->fname)-1-len,
+			"%s.blkparse.%d.bin", pdi->name, pci->cpu);
+
+		pci->out_bin = fopen(fname, "w");
+		if (!pci->out_bin) {
+			perror(fname);
+			pci->out_bin = NULL;
+			return 0;
+		}
+	}
+
 	printf("Input file %s added\n", pci->fname);
 	cpu_mark_online(pdi, pci->cpu);
 
@@ -2825,6 +2855,18 @@ static int do_file(void)
 	while (!is_done() && ms_head && handle(ms_head))
 		;
 
+	/*
+	 * Flush cpu based binary output files in the end
+	 */
+	if (pdi && dump_binary_cpu_based) {
+		struct per_cpu_info *pci;
+		for (cpu = 0; cpu < pdi->ncpus; cpu++) {
+			pci = get_cpu_info(pdi, cpu);
+			fflush(pci->out_bin);
+			printf("CPU%d binary file flushed\n", cpu);
+		}
+	}
+
 	return 0;
 }
 
@@ -2837,7 +2879,7 @@ static void do_pipe(int fd)
 	fdblock = -1;
 	while ((events = read_events(fd, 0, &fdblock)) > 0) {
 		read_sequence++;
-	
+
 #if 0
 		smallest_seq_read = -1U;
 #endif
@@ -2986,7 +3028,7 @@ static int get_program_sort_event(const char *str)
 	return 0;
 }
 
-#define S_OPTS  "a:A:b:D:d:f:F:hi:o:OqsS:tw:vVM"
+#define S_OPTS  "a:A:b:D:d:f:F:hi:o:OqsS:tw:vVMc"
 static char usage_str[] =    "\n\n" \
 	"-i <file>           | --input=<file>\n" \
 	"[ -a <action field> | --act-mask=<action field> ]\n" \
@@ -3010,7 +3052,8 @@ static char usage_str[] =    "\n\n" \
 	"\t-a Only trace specified actions. See documentation\n" \
 	"\t-A Give trace mask as a single value. See documentation\n" \
 	"\t-b stdin read batching\n" \
-	"\t-d Output file. If specified, binary data is written to file\n" \
+	"\t-c Output file. If specified, binary data is written to multiple files, one for each CPU core"
+	"\t-d Output file. If specified, binary data is written to one single file\n" \
 	"\t-D Directory to prepend to input file names\n" \
 	"\t-f Output format. Customize the output format. The format field\n" \
 	"\t   identifies can be found in the documentation\n" \
@@ -3059,7 +3102,7 @@ int main(int argc, char *argv[])
 			break;
 
 		case 'A':
-			if ((sscanf(optarg, "%x", &i) != 1) || 
+			if ((sscanf(optarg, "%x", &i) != 1) ||
 							!valid_act_opt(i)) {
 				fprintf(stderr,
 					"Invalid set action mask %s/0x%x\n",
@@ -3129,6 +3172,9 @@ int main(int argc, char *argv[])
 		case 'M':
 			bin_output_msgs = 0;
 			break;
+		case 'c':
+			dump_binary_cpu_based = 1;
+			break;
 		default:
 			usage(argv[0]);
 			return 1;
diff --git a/blktrace.h b/blktrace.h
index 944fc08..15fddaf 100644
--- a/blktrace.h
+++ b/blktrace.h
@@ -51,6 +51,7 @@ struct per_cpu_info {
 	int fd;
 	int fdblock;
 	char fname[PATH_MAX];
+	FILE *out_bin;
 
 	struct io_stats io_stats;
 
-- 
2.20.1




[Index of Archives]     [Netdev]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux