[PATCH v2 09/11] iowatcher: natively parse blk_io_trace2
Johannes Thumshirn <[email protected]> Mon, 20 Jul 2026 13:14:15 +0200
| Newsgroups | org.kernel.vger.linux-btrace,org.kernel.vger.linux-block |
|---|---|
| Message-ID | <[email protected]> |
Natively parse 'struct blk_io_trace2' from a blktrace binary. Reviewed-by: Damien Le Moal <[email protected]> Signed-off-by: Johannes Thumshirn <[email protected]> --- iowatcher/blkparse.c | 69 +++++++++++++++++++++++++++++++++++++++++++- iowatcher/blkparse.h | 1 + 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/iowatcher/blkparse.c b/iowatcher/blkparse.c index ee1c2c511de6..92ee1cc8ec31 100644 --- a/iowatcher/blkparse.c +++ b/iowatcher/blkparse.c @@ -288,11 +288,75 @@ static void handle_notify(struct trace *trace) } } +/* + * Count how many consecutive well-formed traces the input holds when parsed + * with the given trace version. + */ +static int count_traces(struct trace *trace, int version) +{ + size_t hdr = (version == BLK_IO_TRACE2_VERSION) ? + sizeof(struct blk_io_trace2) : sizeof(struct blk_io_trace); + char *p = trace->start; + char *end = trace->start + trace->len; + int n = 0; + + while (n < 16) { + struct blk_io_trace *io = (struct blk_io_trace *)p; + int pdu_len; + + if (p == end) /* traces tile up to the end */ + break; + if (p + hdr > end) + break; + if (!CHECK_MAGIC(io)) + break; + + if (version == BLK_IO_TRACE2_VERSION) + pdu_len = ((struct blk_io_trace2 *)p)->pdu_len; + else + pdu_len = io->pdu_len; + + p += hdr + pdu_len; + n++; + } + + return n; +} + +/* + * A recent blkparse always emits 'struct blk_io_trace2', while an old blkparse + * emits 'struct blk_io_trace'. As both share the same magic for version 1 + * traces, the on-disk layout cannot be told apart by the version alone. Pick + * the layout that parses the input cleanly. + */ +static int detect_trace_version(struct trace *trace) +{ + struct blk_io_trace *io = (struct blk_io_trace *)trace->start; + + if ((io->magic & 0xff) == BLK_IO_TRACE2_VERSION) + return BLK_IO_TRACE2_VERSION; + + if (count_traces(trace, BLK_IO_TRACE2_VERSION) >= + count_traces(trace, BLK_IO_TRACE_VERSION)) + return BLK_IO_TRACE2_VERSION; + + return BLK_IO_TRACE_VERSION; +} + static void trace_convert_io(struct trace *trace) { struct blk_io_trace *old = (struct blk_io_trace *)trace->cur; struct blk_io_trace2 *io; + if (trace->version == BLK_IO_TRACE2_VERSION) { + struct blk_io_trace2 *new = (struct blk_io_trace2 *)trace->cur; + + io = realloc(trace->io, sizeof(*new) + new->pdu_len); + memcpy(io, new, sizeof(*new) + new->pdu_len); + trace->io = io; + return; + } + io = realloc(trace->io, sizeof(struct blk_io_trace2) + old->pdu_len); io->magic = old->magic; @@ -316,10 +380,12 @@ static void trace_convert_io(struct trace *trace) int next_record(struct trace *trace) { + int hdr = (trace->version == BLK_IO_TRACE2_VERSION) ? + sizeof(struct blk_io_trace2) : sizeof(struct blk_io_trace); int skip = trace->io->pdu_len; u64 offset; - trace->cur += sizeof(struct blk_io_trace) + skip; + trace->cur += hdr + skip; offset = trace->cur - trace->start; if (offset >= trace->len) return 1; @@ -857,6 +923,7 @@ struct trace *open_trace(char *filename) trace->len = st.st_size; trace->start = p; trace->cur = p; + trace->version = detect_trace_version(trace); trace_convert_io(trace); return trace; diff --git a/iowatcher/blkparse.h b/iowatcher/blkparse.h index 304431e0f0d9..c59bcf7b5277 100644 --- a/iowatcher/blkparse.h +++ b/iowatcher/blkparse.h @@ -39,6 +39,7 @@ struct trace { u64 len; char *start; char *cur; + int version; struct blk_io_trace2 *io; u64 start_timestamp; struct timespec abs_start_time; -- 2.54.0