Natively parse 'struct blk_io_trace2' from a blktrace binary. Signed-off-by: Johannes Thumshirn --- blkparse.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++ blktrace.h | 18 +++++++++ 2 files changed, 130 insertions(+) diff --git a/blkparse.c b/blkparse.c index 1237c02..e702356 100644 --- a/blkparse.c +++ b/blkparse.c @@ -2471,6 +2471,37 @@ static int read_one_bit(int fd, struct blk_io_trace2 **bit2, int block, return 0; } +static int read_one_bit2(int fd, struct blk_io_trace2 **bit2, int block, + int *fdblock) +{ + struct blk_io_trace2 *new = *bit2; + int ret; + int pdu_len; + void *p; + + p = (void *) ((u8 *)new + sizeof(__u32)); + + ret = read_data(fd, p, sizeof(*new) - sizeof(__u32), block, fdblock); + if (ret) + return ret; + + pdu_len = get_pdulen(new->pdu_len); + if (pdu_len) { + void *ptr = realloc(new, sizeof(*new) + pdu_len); + + ret = read_data(fd, ptr + sizeof(*new), pdu_len, 1, fdblock); + if (ret) { + free(ptr); + return ret; + } + new = ptr; + } + + bit2_trace_to_cpu(new); + *bit2 = new; + + return 0; +} static int read_events(int fd, int always_block, int *fdblock) { struct per_dev_info *pdi = NULL; @@ -2538,6 +2569,44 @@ static int read_events(int fd, int always_block, int *fdblock) t->next = trace_list; trace_list = t; + if (!pdi || pdi->dev != bit->device) + pdi = get_dev_info(bit->device); + + if (bit->time > pdi->last_read_time) + pdi->last_read_time = bit->time; + } else if (version == SUPPORTED_VERSION2) { + struct blk_io_trace2 *bit; + bit = bit_alloc(); + bit->magic = magic; + + ret = read_one_bit2(fd, &bit, 1, fdblock); + if (ret) + break; + + /* + * not a real trace, so grab and handle it here + */ + 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); + continue; + } + + if (verify_trace(bit->magic)) { + bit_free(bit); + bit = NULL; + continue; + } + + t = t_alloc(); + memset(t, 0, sizeof(*t)); + t->bit = bit; + t->read_sequence = read_sequence; + + t->next = trace_list; + trace_list = t; + if (!pdi || pdi->dev != bit->device) pdi = get_dev_info(bit->device); @@ -2698,6 +2767,49 @@ static int ms_prime(struct ms_stream *msp) msp->last->next = t; msp->last = t; } + } else if (version == SUPPORTED_VERSION2) { + bit = bit_alloc(); + bit->magic = magic; + + ret = read_one_bit2(pci->fd, &bit, 1, &pci->fdblock); + if (ret) + goto err; + + if (verify_trace(bit->magic)) + goto err; + + 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_CGROUP) != BLK_TN_MESSAGE) { + handle_notify(bit); + output_binary(bit, sizeof(*bit) + bit->pdu_len); + bit_free(bit); + bit = NULL; + + i -= 1; + continue; + } + + if (bit->time > pdi->last_read_time) + pdi->last_read_time = bit->time; + + t = t_alloc(); + memset(t, 0, sizeof(*t)); + t->bit = bit; + + if (msp->first == NULL) + msp->first = msp->last = t; + else { + msp->last->next = t; + msp->last = t; + } + } else { fprintf(stderr, "unsupported version %d\n", version); continue; diff --git a/blktrace.h b/blktrace.h index 196b3c9..ba06237 100644 --- a/blktrace.h +++ b/blktrace.h @@ -129,6 +129,24 @@ static inline void bit_to_bit2(struct blk_io_trace *old, old->pdu_len); } +static inline void bit2_trace_to_cpu(struct blk_io_trace2 *t) +{ + if (data_is_native) + return; + + t->magic = be32_to_cpu(t->magic); + t->sequence = be32_to_cpu(t->sequence); + t->time = be64_to_cpu(t->time); + t->sector = be64_to_cpu(t->sector); + t->bytes = be32_to_cpu(t->bytes); + t->action = be64_to_cpu(t->action); + t->pid = be32_to_cpu(t->pid); + t->device = be32_to_cpu(t->device); + t->cpu = be32_to_cpu(t->cpu); + t->error = be16_to_cpu(t->error); + t->pdu_len = be16_to_cpu(t->pdu_len); +} + static inline void bit_trace_to_cpu(struct blk_io_trace *t) { if (data_is_native) -- 2.51.0