From 71d5d4c9156c5946e76fe9909b234e9da64a8341 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 25 Sep 2005 07:37:11 +0200 Subject: [PATCH] [PATCH] blkparse: split format parsing into seperate file --- Makefile | 2 +- blkparse.c | 345 +------------------------------------------------ blkparse_fmt.c | 328 ++++++++++++++++++++++++++++++++++++++++++++++ blktrace.h | 36 ++++++ 4 files changed, 366 insertions(+), 345 deletions(-) create mode 100644 blkparse_fmt.c diff --git a/Makefile b/Makefile index 9cec11b..67e1937 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ SCRIPTS = btrace all: $(PROGS) $(SCRIPTS) -blkparse: blkparse.o rbtree.o +blkparse: blkparse.o blkparse_fmt.o rbtree.o $(CC) $(CFLAGS) -o $@ $(filter %.o,$^) blktrace: blktrace.o $(LIBS) diff --git a/blkparse.c b/blkparse.c index 0e9e695..fca3162 100644 --- a/blkparse.c +++ b/blkparse.c @@ -30,44 +30,12 @@ #include #include #include -#include #include "blktrace.h" #include "rbtree.h" static char blkparse_version[] = "0.90"; -#define SECONDS(x) ((unsigned long long)(x) / 1000000000) -#define NANO_SECONDS(x) ((unsigned long long)(x) % 1000000000) -#define DOUBLE_TO_NANO_ULL(d) ((unsigned long long)((d) * 1000000000)) - -#define MINORBITS 20 -#define MINORMASK ((1U << MINORBITS) - 1) -#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS)) -#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK)) - -#define min(a, b) ((a) < (b) ? (a) : (b)) - -#define HEADER "%D %2c %8s %5T.%9t %5p %2a %3d " - -struct io_stats { - unsigned long qreads, qwrites, creads, cwrites, mreads, mwrites; - unsigned long ireads, iwrites; - unsigned long long qread_kb, qwrite_kb, cread_kb, cwrite_kb; - unsigned long long iread_kb, iwrite_kb; - unsigned long io_unplugs, timer_unplugs; -}; - -struct per_cpu_info { - int cpu; - int nelems; - - int fd; - char fname[128]; - - struct io_stats io_stats; -}; - struct per_dev_info { dev_t id; char *name; @@ -208,7 +176,7 @@ static int ndevices; static struct per_dev_info *devices; static char *get_dev_name(struct per_dev_info *, char *, int); -static FILE *ofp; +FILE *ofp = NULL; static char *output_name; static unsigned long long genesis_time; @@ -736,317 +704,6 @@ static inline void account_unplug(struct blk_io_trace *t, } } -#define VALID_SPECS "BCDFGMPQRSTU" -static char *override_format[256]; -static inline int valid_spec(int spec) -{ - return strchr(VALID_SPECS, spec) != NULL; -} - -static void set_all_format_specs(char *optarg) -{ - char *p; - - for (p = VALID_SPECS; *p; p++) - if (override_format[(int)(*p)] == NULL) - override_format[(int)(*p)] = strdup(optarg); -} - -static int add_format_spec(char *optarg) -{ - int spec = optarg[0]; - - if (!valid_spec(spec)) { - fprintf(stderr,"Bad format specifier %c\n", spec); - return 1; - } - if (optarg[1] != ',') { - fprintf(stderr,"Bad format specifier - need ',' %s\n", optarg); - return 1; - } - optarg += 2; - if (*optarg == '\0') { - fprintf(stderr,"Bad format specifier - need fmt %s\n", optarg); - return 1; - } - - /* - * Set both merges (front and back) - */ - if (spec == 'M') { - override_format['B'] = strdup(optarg); - override_format['M'] = strdup(optarg); - } else - override_format[spec] = strdup(optarg); - - return 0; -} - -static void print_field(char *act, struct per_cpu_info *pci, - struct blk_io_trace *t, unsigned long long elapsed, - int pdu_len, unsigned char *pdu_buf, char field, - int minus, int has_w, int width) -{ - char format[64]; - - if (has_w) { - if (minus) - sprintf(format, "%%-%d", width); - else - sprintf(format, "%%%d", width); - } else - sprintf(format, "%%"); - - switch (field) { - case 'a': - fprintf(ofp, strcat(format, "s"), act); - break; - case 'c': - fprintf(ofp, strcat(format, "d"), pci->cpu); - break; - case 'C': - fprintf(ofp, strcat(format, "s"), t->comm); - break; - case 'd': { - char rwbs[4]; - int i = 0; - int w = t->action & BLK_TC_ACT(BLK_TC_WRITE); - int b = t->action & BLK_TC_ACT(BLK_TC_BARRIER); - int s = t->action & BLK_TC_ACT(BLK_TC_SYNC); - if (w) - rwbs[i++] = 'W'; - else - rwbs[i++] = 'R'; - if (b) - rwbs[i++] = 'B'; - if (s) - rwbs[i++] = 'S'; - rwbs[i] = '\0'; - fprintf(ofp, strcat(format, "s"), rwbs); - break; - } - case 'D': /* format width ignored */ - fprintf(ofp,"%3d,%-3d", MAJOR(t->device), MINOR(t->device)); - break; - case 'e': - fprintf(ofp, strcat(format, "d"), t->error); - break; - case 'M': - fprintf(ofp, strcat(format, "d"), MAJOR(t->device)); - break; - case 'm': - fprintf(ofp, strcat(format, "d"), MINOR(t->device)); - break; - case 'n': - fprintf(ofp, strcat(format, "u"), t->bytes >> 9); - break; - case 'p': - fprintf(ofp, strcat(format, "u"), t->pid); - break; - case 'P': /* format width ignored */ - if ((pdu_len > 0) && (pdu_buf != NULL)) { - int i; - unsigned char *p = pdu_buf; - for (i = 0; i < pdu_len; i++) { - if (i) - fprintf(ofp, " "); - - fprintf(ofp, "%02x", *p++); - } - } - break; - case 's': - fprintf(ofp, strcat(format, "ld"), t->sequence); - break; - case 'S': - fprintf(ofp, strcat(format, "lu"), t->sector); - break; - case 't': - sprintf(format, "%%0%dlu", has_w ? width : 9); - fprintf(ofp, format, NANO_SECONDS(t->time)); - break; - case 'T': - fprintf(ofp, strcat(format, "d"), SECONDS(t->time)); - break; - case 'u': - if (elapsed == -1ULL) { - fprintf(stderr, "Expecting elapsed value\n"); - exit(1); - } - fprintf(ofp, strcat(format, "llu"), elapsed / 1000); - break; - case 'U': { - __u64 *depth = (__u64 *) ((char *) t + sizeof(*t)); - fprintf(ofp, strcat(format, "u"), - (unsigned int) be64_to_cpu(*depth)); - break; - } - default: - fprintf(ofp,strcat(format, "c"), field); - break; - } -} - -static char *parse_field(char *act, struct per_cpu_info *pci, - struct blk_io_trace *t, unsigned long long elapsed, - int pdu_len, unsigned char *pdu_buf, - char *master_format) -{ - int minus = 0; - int has_w = 0; - int width = 0; - char *p = master_format; - - if (*p == '-') { - minus = 1; - p++; - } - if (isdigit(*p)) { - has_w = 1; - do { - width = (width * 10) + (*p++ - '0'); - } while ((*p) && (isdigit(*p))); - } - if (*p) { - print_field(act, pci, t, elapsed, pdu_len, pdu_buf, *p++, - minus, has_w, width); - } - return p; -} - -static char *fmt_select(int fmt_spec, struct blk_io_trace *t, - unsigned long long elapsed) -{ - char *fmt; - static char scratch_format[1024]; - - if (override_format[fmt_spec] != NULL) - return override_format[fmt_spec]; - - switch (fmt_spec) { - case 'C': /* Complete */ - if (t->action & BLK_TC_ACT(BLK_TC_PC)) - strcpy(scratch_format, HEADER "(%P) [%e]\n"); - else { - if (elapsed != -1ULL) { - strcpy(scratch_format, - HEADER "%S +%n (%8u) [%e]\n"); - } else - strcpy(scratch_format, HEADER "%S + %n [%e]\n"); - } - fmt = scratch_format; - break; - - case 'D': /* Issue */ - if (t->action & BLK_TC_ACT(BLK_TC_PC)) - strcpy(scratch_format, HEADER "%n (%P) [%C]\n"); - else { - if (elapsed != -1ULL) { - strcpy(scratch_format, - HEADER "%S + %n (%8u) [%C]\n"); - } else - strcpy(scratch_format, HEADER "%S + %n [%C]\n"); - } - fmt = scratch_format; - break; - - case 'I': /* Insert */ - if (t->action & BLK_TC_ACT(BLK_TC_PC)) - strcpy(scratch_format, HEADER "%n (%P) [%C]\n"); - else { - if (elapsed != -1ULL) { - strcpy(scratch_format, - HEADER "%S + %n (%8u) [%C]\n"); - } else - strcpy(scratch_format, HEADER "%S + %n [%C]\n"); - } - fmt = scratch_format; - break; - - case 'Q': /* Queue */ - case 'W': /* Bounce */ - if (elapsed != -1ULL) { - strcpy(scratch_format, HEADER "%S + %n (%8u) [%C]\n"); - } else - strcpy(scratch_format, HEADER "%S + %n [%C]\n"); - fmt = scratch_format; - break; - - case 'B': /* Back merge */ - case 'F': /* Front merge */ - case 'M': /* Front or back merge */ - fmt = HEADER "%S + %n [%C]\n"; - break; - - case 'P': /* Plug */ - fmt = HEADER "[%C]\n"; - break; - - case 'G': /* Get request */ - case 'S': /* Sleep request */ - fmt = HEADER "%S + %n [%C]\n"; - break; - - case 'U': /* Unplug IO */ - case 'T': /* Unplug timer */ - fmt = HEADER "[%C] %U\n"; - break; - - case 'X': /* Split */ - strcpy(scratch_format, HEADER "%S / %U [%C]\n"); - fmt = scratch_format; - break; - - default: - fprintf(stderr,"FATAL: Invalid format spec %c\n", fmt_spec); - exit(1); - /*NOTREACHED*/ - } - - return fmt; -} - -static void process_fmt(char *act, struct per_cpu_info *pci, - struct blk_io_trace *t, unsigned long long elapsed, - int pdu_len, unsigned char *pdu_buf) -{ - char *p = fmt_select(act[0], t, elapsed); - - while (*p) { - switch (*p) { - case '%': /* Field specifier */ - p++; - if (*p == '%') - fprintf(ofp, "%c", *p++); - else if (!*p) - fprintf(ofp, "%c", '%'); - else - p = parse_field(act, pci, t, elapsed, - pdu_len, pdu_buf, p); - break; - case '\\': { /* escape */ - switch (p[1]) { - case 'b': fprintf(ofp, "\b"); break; - case 'n': fprintf(ofp, "\n"); break; - case 'r': fprintf(ofp, "\r"); break; - case 't': fprintf(ofp, "\t"); break; - default: - fprintf(stderr, - "Invalid escape char in format %c\n", - p[1]); - exit(1); - /*NOTREACHED*/ - } - p += 2; - break; - } - default: - fprintf(ofp, "%c", *p++); - break; - } - } -} - static void log_complete(struct per_cpu_info *pci, struct blk_io_trace *t, char *act) { diff --git a/blkparse_fmt.c b/blkparse_fmt.c new file mode 100644 index 0000000..d92ef43 --- /dev/null +++ b/blkparse_fmt.c @@ -0,0 +1,328 @@ +/* + * This file contains format parsing code for blkparse, allowing you to + * customize the individual action format and generel output format. + */ +#include +#include +#include +#include +#include + +#include "blktrace.h" + +#define VALID_SPECS "BCDFGMPQRSTU" + +#define HEADER "%D %2c %8s %5T.%9t %5p %2a %3d " + +static char *override_format[256]; + +static inline int valid_spec(int spec) +{ + return strchr(VALID_SPECS, spec) != NULL; +} + +void set_all_format_specs(char *optarg) +{ + char *p; + + for (p = VALID_SPECS; *p; p++) + if (override_format[(int)(*p)] == NULL) + override_format[(int)(*p)] = strdup(optarg); +} + +int add_format_spec(char *optarg) +{ + int spec = optarg[0]; + + if (!valid_spec(spec)) { + fprintf(stderr,"Bad format specifier %c\n", spec); + return 1; + } + if (optarg[1] != ',') { + fprintf(stderr,"Bad format specifier - need ',' %s\n", optarg); + return 1; + } + optarg += 2; + if (*optarg == '\0') { + fprintf(stderr,"Bad format specifier - need fmt %s\n", optarg); + return 1; + } + + /* + * Set both merges (front and back) + */ + if (spec == 'M') { + override_format['B'] = strdup(optarg); + override_format['M'] = strdup(optarg); + } else + override_format[spec] = strdup(optarg); + + return 0; +} + +static void print_field(char *act, struct per_cpu_info *pci, + struct blk_io_trace *t, unsigned long long elapsed, + int pdu_len, unsigned char *pdu_buf, char field, + int minus, int has_w, int width) +{ + char format[64]; + + if (has_w) { + if (minus) + sprintf(format, "%%-%d", width); + else + sprintf(format, "%%%d", width); + } else + sprintf(format, "%%"); + + switch (field) { + case 'a': + fprintf(ofp, strcat(format, "s"), act); + break; + case 'c': + fprintf(ofp, strcat(format, "d"), pci->cpu); + break; + case 'C': + fprintf(ofp, strcat(format, "s"), t->comm); + break; + case 'd': { + char rwbs[4]; + int i = 0; + int w = t->action & BLK_TC_ACT(BLK_TC_WRITE); + int b = t->action & BLK_TC_ACT(BLK_TC_BARRIER); + int s = t->action & BLK_TC_ACT(BLK_TC_SYNC); + if (w) + rwbs[i++] = 'W'; + else + rwbs[i++] = 'R'; + if (b) + rwbs[i++] = 'B'; + if (s) + rwbs[i++] = 'S'; + rwbs[i] = '\0'; + fprintf(ofp, strcat(format, "s"), rwbs); + break; + } + case 'D': /* format width ignored */ + fprintf(ofp,"%3d,%-3d", MAJOR(t->device), MINOR(t->device)); + break; + case 'e': + fprintf(ofp, strcat(format, "d"), t->error); + break; + case 'M': + fprintf(ofp, strcat(format, "d"), MAJOR(t->device)); + break; + case 'm': + fprintf(ofp, strcat(format, "d"), MINOR(t->device)); + break; + case 'n': + fprintf(ofp, strcat(format, "u"), t->bytes >> 9); + break; + case 'p': + fprintf(ofp, strcat(format, "u"), t->pid); + break; + case 'P': /* format width ignored */ + if ((pdu_len > 0) && (pdu_buf != NULL)) { + int i; + unsigned char *p = pdu_buf; + for (i = 0; i < pdu_len; i++) { + if (i) + fprintf(ofp, " "); + + fprintf(ofp, "%02x", *p++); + } + } + break; + case 's': + fprintf(ofp, strcat(format, "ld"), t->sequence); + break; + case 'S': + fprintf(ofp, strcat(format, "lu"), t->sector); + break; + case 't': + sprintf(format, "%%0%dlu", has_w ? width : 9); + fprintf(ofp, format, NANO_SECONDS(t->time)); + break; + case 'T': + fprintf(ofp, strcat(format, "d"), SECONDS(t->time)); + break; + case 'u': + if (elapsed == -1ULL) { + fprintf(stderr, "Expecting elapsed value\n"); + exit(1); + } + fprintf(ofp, strcat(format, "llu"), elapsed / 1000); + break; + case 'U': { + __u64 *depth = (__u64 *) ((char *) t + sizeof(*t)); + fprintf(ofp, strcat(format, "u"), + (unsigned int) be64_to_cpu(*depth)); + break; + } + default: + fprintf(ofp,strcat(format, "c"), field); + break; + } +} + +static char *parse_field(char *act, struct per_cpu_info *pci, + struct blk_io_trace *t, unsigned long long elapsed, + int pdu_len, unsigned char *pdu_buf, + char *master_format) +{ + int minus = 0; + int has_w = 0; + int width = 0; + char *p = master_format; + + if (*p == '-') { + minus = 1; + p++; + } + if (isdigit(*p)) { + has_w = 1; + do { + width = (width * 10) + (*p++ - '0'); + } while ((*p) && (isdigit(*p))); + } + if (*p) { + print_field(act, pci, t, elapsed, pdu_len, pdu_buf, *p++, + minus, has_w, width); + } + return p; +} + +static char *fmt_select(int fmt_spec, struct blk_io_trace *t, + unsigned long long elapsed) +{ + char *fmt; + static char scratch_format[1024]; + + if (override_format[fmt_spec] != NULL) + return override_format[fmt_spec]; + + switch (fmt_spec) { + case 'C': /* Complete */ + if (t->action & BLK_TC_ACT(BLK_TC_PC)) + strcpy(scratch_format, HEADER "(%P) [%e]\n"); + else { + if (elapsed != -1ULL) { + strcpy(scratch_format, + HEADER "%S +%n (%8u) [%e]\n"); + } else + strcpy(scratch_format, HEADER "%S + %n [%e]\n"); + } + fmt = scratch_format; + break; + + case 'D': /* Issue */ + if (t->action & BLK_TC_ACT(BLK_TC_PC)) + strcpy(scratch_format, HEADER "%n (%P) [%C]\n"); + else { + if (elapsed != -1ULL) { + strcpy(scratch_format, + HEADER "%S + %n (%8u) [%C]\n"); + } else + strcpy(scratch_format, HEADER "%S + %n [%C]\n"); + } + fmt = scratch_format; + break; + + case 'I': /* Insert */ + if (t->action & BLK_TC_ACT(BLK_TC_PC)) + strcpy(scratch_format, HEADER "%n (%P) [%C]\n"); + else { + if (elapsed != -1ULL) { + strcpy(scratch_format, + HEADER "%S + %n (%8u) [%C]\n"); + } else + strcpy(scratch_format, HEADER "%S + %n [%C]\n"); + } + fmt = scratch_format; + break; + + case 'Q': /* Queue */ + case 'W': /* Bounce */ + if (elapsed != -1ULL) { + strcpy(scratch_format, HEADER "%S + %n (%8u) [%C]\n"); + } else + strcpy(scratch_format, HEADER "%S + %n [%C]\n"); + fmt = scratch_format; + break; + + case 'B': /* Back merge */ + case 'F': /* Front merge */ + case 'M': /* Front or back merge */ + fmt = HEADER "%S + %n [%C]\n"; + break; + + case 'P': /* Plug */ + fmt = HEADER "[%C]\n"; + break; + + case 'G': /* Get request */ + case 'S': /* Sleep request */ + fmt = HEADER "%S + %n [%C]\n"; + break; + + case 'U': /* Unplug IO */ + case 'T': /* Unplug timer */ + fmt = HEADER "[%C] %U\n"; + break; + + case 'X': /* Split */ + strcpy(scratch_format, HEADER "%S / %U [%C]\n"); + fmt = scratch_format; + break; + + default: + fprintf(stderr,"FATAL: Invalid format spec %c\n", fmt_spec); + exit(1); + /*NOTREACHED*/ + } + + return fmt; +} + +void process_fmt(char *act, struct per_cpu_info *pci, struct blk_io_trace *t, + unsigned long long elapsed, int pdu_len, + unsigned char *pdu_buf) +{ + char *p = fmt_select(act[0], t, elapsed); + + while (*p) { + switch (*p) { + case '%': /* Field specifier */ + p++; + if (*p == '%') + fprintf(ofp, "%c", *p++); + else if (!*p) + fprintf(ofp, "%c", '%'); + else + p = parse_field(act, pci, t, elapsed, + pdu_len, pdu_buf, p); + break; + case '\\': { /* escape */ + switch (p[1]) { + case 'b': fprintf(ofp, "\b"); break; + case 'n': fprintf(ofp, "\n"); break; + case 'r': fprintf(ofp, "\r"); break; + case 't': fprintf(ofp, "\t"); break; + default: + fprintf(stderr, + "Invalid escape char in format %c\n", + p[1]); + exit(1); + /*NOTREACHED*/ + } + p += 2; + break; + } + default: + fprintf(ofp, "%c", *p++); + break; + } + } +} + + diff --git a/blktrace.h b/blktrace.h index 9855101..6ef5ab0 100644 --- a/blktrace.h +++ b/blktrace.h @@ -6,6 +6,37 @@ #include #include "blktrace_api.h" +#define MINORBITS 20 +#define MINORMASK ((1U << MINORBITS) - 1) +#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS)) +#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK)) + +#define SECONDS(x) ((unsigned long long)(x) / 1000000000) +#define NANO_SECONDS(x) ((unsigned long long)(x) % 1000000000) +#define DOUBLE_TO_NANO_ULL(d) ((unsigned long long)((d) * 1000000000)) + +#define min(a, b) ((a) < (b) ? (a) : (b)) + +struct io_stats { + unsigned long qreads, qwrites, creads, cwrites, mreads, mwrites; + unsigned long ireads, iwrites; + unsigned long long qread_kb, qwrite_kb, cread_kb, cwrite_kb; + unsigned long long iread_kb, iwrite_kb; + unsigned long io_unplugs, timer_unplugs; +}; + +struct per_cpu_info { + int cpu; + int nelems; + + int fd; + char fname[128]; + + struct io_stats io_stats; +}; + +extern FILE *ofp; + #define CHECK_MAGIC(t) (((t)->magic & 0xffffff00) == BLK_IO_TRACE_MAGIC) #define SUPPORTED_VERSION (0x05) @@ -74,4 +105,9 @@ static inline void trace_to_cpu(struct blk_io_trace *t) /* t->comm is a string (endian neutral) */ } +extern void set_all_format_specs(char *); +extern int add_format_spec(char *); +extern void process_fmt(char *, struct per_cpu_info *, struct blk_io_trace *, + unsigned long long, int, unsigned char *); + #endif -- 2.25.1