X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=blkparse.c;h=227cc444c280660eee4441c0d8e9f7ae80f36b17;hb=e63098f39398bde67be9b64a49deece1c60614df;hp=457e6e7d6c2734f1770d6fc6f8efa661fc350101;hpb=fb2ec7961d3cfc7fb8f84bcf6ae803ed1c7bd180;p=blktrace.git diff --git a/blkparse.c b/blkparse.c index 457e6e7..227cc44 100644 --- a/blkparse.c +++ b/blkparse.c @@ -36,7 +36,7 @@ #include "rbtree.h" #include "jhash.h" -static char blkparse_version[] = "0.99.2"; +static char blkparse_version[] = "1.2.0"; struct skip_info { unsigned long start, end; @@ -104,7 +104,6 @@ static struct per_process_info *ppi_hash_table[PPI_HASH_SIZE]; static struct per_process_info *ppi_list; static int ppi_list_entries; -#define S_OPTS "a:A:b:D:d:f:F:hi:o:Oqstw:vV" static struct option l_opts[] = { { .name = "act-mask", @@ -160,6 +159,12 @@ static struct option l_opts[] = { .flag = NULL, .val = 'i' }, + { + .name = "no-msgs", + .has_arg = no_argument, + .flag = NULL, + .val = 'M' + }, { .name = "output", .has_arg = required_argument, @@ -270,6 +275,7 @@ static int ppi_hash_by_pid = 1; static int verbose; static unsigned int act_mask = -1U; static int stats_printed; +static int bin_output_msgs = 1; int data_is_native = -1; static FILE *dump_fp; @@ -292,6 +298,8 @@ static volatile int done; struct timespec abs_start_time; static unsigned long long start_timestamp; +static int have_drv_data = 0; + #define JHASH_RANDOM (0x3af5f2ee) #define CPUS_PER_LONG (8 * sizeof(unsigned long)) @@ -544,7 +552,7 @@ static struct process_pid_map *find_ppm(pid_t pid) return NULL; } -static void add_ppm_hash(pid_t pid, const char *name) +static struct process_pid_map *add_ppm_hash(pid_t pid, const char *name) { const int hash_idx = ppm_hash_pid(pid); struct process_pid_map *ppm; @@ -554,10 +562,14 @@ static void add_ppm_hash(pid_t pid, const char *name) ppm = malloc(sizeof(*ppm)); memset(ppm, 0, sizeof(*ppm)); ppm->pid = pid; - strcpy(ppm->comm, name); + memset(ppm->comm, 0, sizeof(ppm->comm)); + strncpy(ppm->comm, name, sizeof(ppm->comm)); + ppm->comm[sizeof(ppm->comm) - 1] = '\0'; ppm->hash_next = ppm_hash_table[hash_idx]; ppm_hash_table[hash_idx] = ppm; } + + return ppm; } static void handle_notify(struct blk_io_trace *bit) @@ -588,6 +600,22 @@ static void handle_notify(struct blk_io_trace *bit) break; + case BLK_TN_MESSAGE: + if (bit->pdu_len > 0) { + char msg[bit->pdu_len+1]; + + memcpy(msg, (char *)payload, bit->pdu_len); + msg[bit->pdu_len] = '\0'; + + fprintf(ofp, + "%3d,%-3d %2d %8s %5d.%09lu %5u %2s %3s %s\n", + MAJOR(bit->device), MINOR(bit->device), + bit->cpu, "0", (int) SECONDS(bit->time), + (unsigned long) NANO_SECONDS(bit->time), + 0, "m", "N", msg); + } + break; + default: /* Ignore unknown notify events */ ; @@ -937,6 +965,8 @@ static struct io_track *find_track(struct per_dev_info *pdi, pid_t pid, if (!iot) { iot = malloc(sizeof(*iot)); iot->ppm = find_ppm(pid); + if (!iot->ppm) + iot->ppm = add_ppm_hash(pid, "unknown"); iot->sector = sector; track_rb_insert(pdi, iot); } @@ -1119,6 +1149,8 @@ static struct io_stats *find_process_io_stats(pid_t pid) ppi = malloc(sizeof(*ppi)); memset(ppi, 0, sizeof(*ppi)); ppi->ppm = find_ppm(pid); + if (!ppi->ppm) + ppi->ppm = add_ppm_hash(pid, "unknown"); add_ppi_to_hash(ppi); add_ppi_to_list(ppi); } @@ -1150,9 +1182,11 @@ static inline void __account_m(struct io_stats *ios, struct blk_io_trace *t, if (rw) { ios->mwrites++; ios->mwrite_kb += t_kb(t); + ios->mwrite_b += t_b(t); } else { ios->mreads++; ios->mread_kb += t_kb(t); + ios->mread_b += t_b(t); } } @@ -1168,15 +1202,115 @@ static inline void account_m(struct blk_io_trace *t, struct per_cpu_info *pci, } } +static inline void __account_pc_queue(struct io_stats *ios, + struct blk_io_trace *t, int rw) +{ + if (rw) { + ios->qwrites_pc++; + ios->qwrite_kb_pc += t_kb(t); + ios->qwrite_b_pc += t_b(t); + } else { + ios->qreads_pc++; + ios->qread_kb += t_kb(t); + ios->qread_b_pc += t_b(t); + } +} + +static inline void account_pc_queue(struct blk_io_trace *t, + struct per_cpu_info *pci, int rw) +{ + __account_pc_queue(&pci->io_stats, t, rw); + + if (per_process_stats) { + struct io_stats *ios = find_process_io_stats(t->pid); + + __account_pc_queue(ios, t, rw); + } +} + +static inline void __account_pc_issue(struct io_stats *ios, int rw, + unsigned int bytes) +{ + if (rw) { + ios->iwrites_pc++; + ios->iwrite_kb_pc += bytes >> 10; + ios->iwrite_b_pc += bytes & 1023; + } else { + ios->ireads_pc++; + ios->iread_kb_pc += bytes >> 10; + ios->iread_b_pc += bytes & 1023; + } +} + +static inline void account_pc_issue(struct blk_io_trace *t, + struct per_cpu_info *pci, int rw) +{ + __account_pc_issue(&pci->io_stats, rw, t->bytes); + + if (per_process_stats) { + struct io_stats *ios = find_process_io_stats(t->pid); + + __account_pc_issue(ios, rw, t->bytes); + } +} + +static inline void __account_pc_requeue(struct io_stats *ios, + struct blk_io_trace *t, int rw) +{ + if (rw) { + ios->wrqueue_pc++; + ios->iwrite_kb_pc -= t_kb(t); + ios->iwrite_b_pc -= t_b(t); + } else { + ios->rrqueue_pc++; + ios->iread_kb_pc -= t_kb(t); + ios->iread_b_pc -= t_b(t); + } +} + +static inline void account_pc_requeue(struct blk_io_trace *t, + struct per_cpu_info *pci, int rw) +{ + __account_pc_requeue(&pci->io_stats, t, rw); + + if (per_process_stats) { + struct io_stats *ios = find_process_io_stats(t->pid); + + __account_pc_requeue(ios, t, rw); + } +} + +static inline void __account_pc_c(struct io_stats *ios, int rw) +{ + if (rw) + ios->cwrites_pc++; + else + ios->creads_pc++; +} + +static inline void account_pc_c(struct blk_io_trace *t, + struct per_cpu_info *pci, int rw) +{ + __account_pc_c(&pci->io_stats, rw); + + if (per_process_stats) { + struct io_stats *ios = find_process_io_stats(t->pid); + + __account_pc_c(ios, rw); + } +} + static inline void __account_queue(struct io_stats *ios, struct blk_io_trace *t, int rw) { if (rw) { ios->qwrites++; ios->qwrite_kb += t_kb(t); + ios->qwrite_b += t_b(t); } else { ios->qreads++; ios->qread_kb += t_kb(t); + ios->qread_b += t_b(t); } } @@ -1197,9 +1331,11 @@ static inline void __account_c(struct io_stats *ios, int rw, int bytes) if (rw) { ios->cwrites++; ios->cwrite_kb += bytes >> 10; + ios->cwrite_b += bytes & 1023; } else { ios->creads++; ios->cread_kb += bytes >> 10; + ios->cread_b += bytes & 1023; } } @@ -1221,9 +1357,11 @@ static inline void __account_issue(struct io_stats *ios, int rw, if (rw) { ios->iwrites++; ios->iwrite_kb += bytes >> 10; + ios->iwrite_b += bytes & 1023; } else { ios->ireads++; ios->iread_kb += bytes >> 10; + ios->iread_b += bytes & 1023; } } @@ -1265,9 +1403,11 @@ static inline void __account_requeue(struct io_stats *ios, if (rw) { ios->wrqueue++; ios->iwrite_kb -= t_kb(t); + ios->iwrite_b -= t_b(t); } else { ios->rrqueue++; ios->iread_kb -= t_kb(t); + ios->iread_b -= t_b(t); } } @@ -1347,13 +1487,16 @@ static void log_pc(struct per_cpu_info *pci, struct blk_io_trace *t, char *act) process_fmt(act, pci, t, -1ULL, t->pdu_len, buf); } -static void dump_trace_pc(struct blk_io_trace *t, struct per_cpu_info *pci) +static void dump_trace_pc(struct blk_io_trace *t, struct per_dev_info *pdi, + struct per_cpu_info *pci) { + int w = (t->action & BLK_TC_ACT(BLK_TC_WRITE)) != 0; int act = t->action & 0xffff; switch (act) { case __BLK_TA_QUEUE: log_generic(pci, t, "Q"); + account_pc_queue(t, pci, w); break; case __BLK_TA_GETRQ: log_generic(pci, t, "G"); @@ -1362,13 +1505,27 @@ static void dump_trace_pc(struct blk_io_trace *t, struct per_cpu_info *pci) log_generic(pci, t, "S"); break; case __BLK_TA_REQUEUE: + /* + * can happen if we miss traces, don't let it go + * below zero + */ + if (pdi->cur_depth[w]) + pdi->cur_depth[w]--; + account_pc_requeue(t, pci, w); log_generic(pci, t, "R"); break; case __BLK_TA_ISSUE: + account_pc_issue(t, pci, w); + pdi->cur_depth[w]++; + if (pdi->cur_depth[w] > pdi->max_depth[w]) + pdi->max_depth[w] = pdi->cur_depth[w]; log_pc(pci, t, "D"); break; case __BLK_TA_COMPLETE: + if (pdi->cur_depth[w]) + pdi->cur_depth[w]--; log_pc(pci, t, "C"); + account_pc_c(t, pci, w); break; case __BLK_TA_INSERT: log_pc(pci, t, "I"); @@ -1452,6 +1609,10 @@ static void dump_trace_fs(struct blk_io_trace *t, struct per_dev_info *pdi, case __BLK_TA_REMAP: log_generic(pci, t, "A"); break; + case __BLK_TA_DRV_DATA: + have_drv_data = 1; + /* dump to binary file only */ + break; default: fprintf(stderr, "Bad fs action %x\n", t->action); break; @@ -1462,8 +1623,10 @@ static void dump_trace(struct blk_io_trace *t, struct per_cpu_info *pci, struct per_dev_info *pdi) { if (text_output) { - if (t->action & BLK_TC_ACT(BLK_TC_PC)) - dump_trace_pc(t, pci); + if (t->action == BLK_TN_MESSAGE) + handle_notify(t); + else if (t->action & BLK_TC_ACT(BLK_TC_PC)) + dump_trace_pc(t, pdi, pci); else dump_trace_fs(t, pdi, pci); } @@ -1473,7 +1636,10 @@ static void dump_trace(struct blk_io_trace *t, struct per_cpu_info *pci, pdi->events++; - output_binary(t, sizeof(*t) + t->pdu_len); + if (bin_output_msgs || + !(t->action & BLK_TC_ACT(BLK_TC_NOTIFY) && + t->action == BLK_TN_MESSAGE)) + output_binary(t, sizeof(*t) + t->pdu_len); } /* @@ -1504,20 +1670,60 @@ static void dump_io_stats(struct per_dev_info *pdi, struct io_stats *ios, fprintf(ofp, "%s\n", msg); - fprintf(ofp, " Reads Queued: %s, %siB\t", size_cnv(x, ios->qreads, 0), size_cnv(y, ios->qread_kb, 1)); - fprintf(ofp, " Writes Queued: %s, %siB\n", size_cnv(x, ios->qwrites, 0), size_cnv(y, ios->qwrite_kb, 1)); - fprintf(ofp, " Read Dispatches: %s, %siB\t", size_cnv(x, ios->ireads, 0), size_cnv(y, ios->iread_kb, 1)); - fprintf(ofp, " Write Dispatches: %s, %siB\n", size_cnv(x, ios->iwrites, 0), size_cnv(y, ios->iwrite_kb, 1)); + fprintf(ofp, " Reads Queued: %s, %siB\t", + size_cnv(x, ios->qreads, 0), + size_cnv(y, ios->qread_kb + (ios->qread_b>>10), 1)); + fprintf(ofp, " Writes Queued: %s, %siB\n", + size_cnv(x, ios->qwrites, 0), + size_cnv(y, ios->qwrite_kb + (ios->qwrite_b>>10), 1)); + fprintf(ofp, " Read Dispatches: %s, %siB\t", + size_cnv(x, ios->ireads, 0), + size_cnv(y, ios->iread_kb + (ios->iread_b>>10), 1)); + fprintf(ofp, " Write Dispatches: %s, %siB\n", + size_cnv(x, ios->iwrites, 0), + size_cnv(y, ios->iwrite_kb + (ios->iwrite_b>>10), 1)); fprintf(ofp, " Reads Requeued: %s\t\t", size_cnv(x, ios->rrqueue, 0)); fprintf(ofp, " Writes Requeued: %s\n", size_cnv(x, ios->wrqueue, 0)); - fprintf(ofp, " Reads Completed: %s, %siB\t", size_cnv(x, ios->creads, 0), size_cnv(y, ios->cread_kb, 1)); - fprintf(ofp, " Writes Completed: %s, %siB\n", size_cnv(x, ios->cwrites, 0), size_cnv(y, ios->cwrite_kb, 1)); - fprintf(ofp, " Read Merges: %s, %siB\t", size_cnv(x, ios->mreads, 0), size_cnv(y, ios->mread_kb, 1)); - fprintf(ofp, " Write Merges: %s, %siB\n", size_cnv(x, ios->mwrites, 0), size_cnv(y, ios->mwrite_kb, 1)); + fprintf(ofp, " Reads Completed: %s, %siB\t", + size_cnv(x, ios->creads, 0), + size_cnv(y, ios->cread_kb + (ios->cread_b>>10), 1)); + fprintf(ofp, " Writes Completed: %s, %siB\n", + size_cnv(x, ios->cwrites, 0), + size_cnv(y, ios->cwrite_kb + (ios->cwrite_b>>10), 1)); + fprintf(ofp, " Read Merges: %s, %siB\t", + size_cnv(x, ios->mreads, 0), + size_cnv(y, ios->mread_kb + (ios->mread_b>>10), 1)); + fprintf(ofp, " Write Merges: %s, %siB\n", + size_cnv(x, ios->mwrites, 0), + size_cnv(y, ios->mwrite_kb + (ios->mwrite_b>>10), 1)); if (pdi) { fprintf(ofp, " Read depth: %'8u%8c\t", pdi->max_depth[0], ' '); fprintf(ofp, " Write depth: %'8u\n", pdi->max_depth[1]); } + if (ios->qreads_pc || ios->qwrites_pc || ios->ireads_pc || ios->iwrites_pc || + ios->rrqueue_pc || ios->wrqueue_pc || ios->creads_pc || ios->cwrites_pc) { + fprintf(ofp, " PC Reads Queued: %s, %siB\t", + size_cnv(x, ios->qreads_pc, 0), + size_cnv(y, + ios->qread_kb_pc + (ios->qread_b_pc>>10), 1)); + fprintf(ofp, " PC Writes Queued: %s, %siB\n", + size_cnv(x, ios->qwrites_pc, 0), + size_cnv(y, + ios->qwrite_kb_pc + (ios->qwrite_b_pc>>10), 1)); + fprintf(ofp, " PC Read Disp.: %s, %siB\t", + size_cnv(x, ios->ireads_pc, 0), + size_cnv(y, + ios->iread_kb_pc + (ios->iread_b_pc>>10), 1)); + fprintf(ofp, " PC Write Disp.: %s, %siB\n", + size_cnv(x, ios->iwrites_pc, 0), + size_cnv(y, + ios->iwrite_kb_pc + (ios->iwrite_b_pc>>10), + 1)); + fprintf(ofp, " PC Reads Req.: %s\t\t", size_cnv(x, ios->rrqueue_pc, 0)); + fprintf(ofp, " PC Writes Req.: %s\n", size_cnv(x, ios->wrqueue_pc, 0)); + fprintf(ofp, " PC Reads Compl.: %s\t\t", size_cnv(x, ios->creads_pc, 0)); + fprintf(ofp, " PC Writes Compl.: %s\n", size_cnv(x, ios->cwrites_pc, 0)); + } fprintf(ofp, " IO unplugs: %'8lu%8c\t", ios->io_unplugs, ' '); fprintf(ofp, " Timer unplugs: %'8lu\n", ios->timer_unplugs); } @@ -1647,6 +1853,32 @@ static void show_device_and_cpu_stats(void) total.iwrite_kb += ios->iwrite_kb; total.mread_kb += ios->mread_kb; total.mwrite_kb += ios->mwrite_kb; + total.qread_b += ios->qread_b; + total.qwrite_b += ios->qwrite_b; + total.cread_b += ios->cread_b; + total.cwrite_b += ios->cwrite_b; + total.iread_b += ios->iread_b; + total.iwrite_b += ios->iwrite_b; + total.mread_b += ios->mread_b; + total.mwrite_b += ios->mwrite_b; + + total.qreads_pc += ios->qreads_pc; + total.qwrites_pc += ios->qwrites_pc; + total.creads_pc += ios->creads_pc; + total.cwrites_pc += ios->cwrites_pc; + total.ireads_pc += ios->ireads_pc; + total.iwrites_pc += ios->iwrites_pc; + total.rrqueue_pc += ios->rrqueue_pc; + total.wrqueue_pc += ios->wrqueue_pc; + total.qread_kb_pc += ios->qread_kb_pc; + total.qwrite_kb_pc += ios->qwrite_kb_pc; + total.iread_kb_pc += ios->iread_kb_pc; + total.iwrite_kb_pc += ios->iwrite_kb_pc; + total.qread_b_pc += ios->qread_b_pc; + total.qwrite_b_pc += ios->qwrite_b_pc; + total.iread_b_pc += ios->iread_b_pc; + total.iwrite_b_pc += ios->iwrite_b_pc; + total.timer_unplugs += ios->timer_unplugs; total.io_unplugs += ios->io_unplugs; @@ -1666,8 +1898,10 @@ static void show_device_and_cpu_stats(void) wrate = rrate = 0; msec = (pdi->last_reported_time - pdi->first_reported_time) / 1000000; if (msec) { - rrate = 1000 * total.cread_kb / msec; - wrate = 1000 * total.cwrite_kb / msec; + rrate = ((1000 * total.cread_kb) + total.cread_b) / + msec; + wrate = ((1000 * total.cwrite_kb) + total.cwrite_b) / + msec; } fprintf(ofp, "\nThroughput (R/W): %'LuKiB/s / %'LuKiB/s\n", @@ -1789,6 +2023,7 @@ static int check_cpu_map(struct per_dev_info *pdi) * create a map of the cpus we have traces for */ cpu_map = malloc(pdi->cpu_map_max / sizeof(long)); + memset(cpu_map, 0, sizeof(*cpu_map)); n = rb_first(&rb_sort_root); while (n) { __t = rb_entry(n, struct trace, rb_node); @@ -1892,7 +2127,8 @@ static void show_entries_rb(int force) break; } - if (check_sequence(pdi, t, force)) + if (!(bit->action == BLK_TN_MESSAGE) && + check_sequence(pdi, t, force)) break; if (!force && bit->time > last_allowed_time) @@ -1903,7 +2139,8 @@ static void show_entries_rb(int force) if (!pci || pci->cpu != bit->cpu) pci = get_cpu_info(pdi, bit->cpu); - pci->last_sequence = bit->sequence; + if (!(bit->action == BLK_TN_MESSAGE)) + pci->last_sequence = bit->sequence; pci->nelems++; @@ -2036,7 +2273,7 @@ static int read_events(int fd, int always_block, int *fdblock) /* * not a real trace, so grab and handle it here */ - if (bit->action & BLK_TC_ACT(BLK_TC_NOTIFY)) { + if (bit->action & BLK_TC_ACT(BLK_TC_NOTIFY) && bit->action != BLK_TN_MESSAGE) { handle_notify(bit); output_binary(bit, sizeof(*bit) + bit->pdu_len); continue; @@ -2179,7 +2416,13 @@ static int ms_prime(struct ms_stream *msp) if (verify_trace(bit)) goto err; - if (bit->action & BLK_TC_ACT(BLK_TC_NOTIFY)) { + if (bit->cpu != pci->cpu) { + fprintf(stderr, "cpu %d trace info has error cpu %d\n", + pci->cpu, bit->cpu); + continue; + } + + if (bit->action & BLK_TC_ACT(BLK_TC_NOTIFY) && bit->action != BLK_TN_MESSAGE) { handle_notify(bit); output_binary(bit, sizeof(*bit) + bit->pdu_len); bit_free(bit); @@ -2284,17 +2527,19 @@ static int handle(struct ms_stream *msp) struct blk_io_trace *bit; t = ms_peek(msp); - if (t->bit->time > stopwatch_end) - return 0; bit = t->bit; pdi = msp->pdi; pci = get_cpu_info(pdi, msp->cpu); pci->nelems++; - bit->time -= genesis_time; + + if (t->bit->time > stopwatch_end) + return 0; + pdi->last_reported_time = bit->time; - if (bit->action & (act_mask << BLK_TC_SHIFT)) + if ((bit->action & (act_mask << BLK_TC_SHIFT))&& + t->bit->time >= stopwatch_start) dump_trace(bit, pci, pdi); ms_deq(msp); @@ -2343,6 +2588,12 @@ static int do_file(void) for (cpu = 0; setup_file(pdi, cpu); cpu++) ; + + if (!cpu) { + fprintf(stderr,"No input files found for %s\n", + pdi->name); + return 1; + } } /* @@ -2479,7 +2730,7 @@ static int is_pipe(const char *str) return 0; } -#define S_OPTS "a:A:b:D:d:f:F:hi:o:Oqstw:vV" +#define S_OPTS "a:A:b:D:d:f:F:hi:o:Oqstw:vVM" static char usage_str[] = "\n\n" \ "-i | --input=\n" \ "[ -a | --act-mask= ]\n" \ @@ -2496,8 +2747,11 @@ static char usage_str[] = "\n\n" \ "[ -s | --per-program-stats ]\n" \ "[ -t | --track-ios ]\n" \ "[ -w