From dffedcd5b5708cc4d2733c209667acee0f96fa93 Mon Sep 17 00:00:00 2001 From: Konrad Sztyber Date: Wed, 1 Sep 2021 14:16:22 +0200 Subject: [PATCH] lib/trace_parser: reconstruct tracepoint arguments Tracepoint arguments are now reconstructed when retrieving next trace entry (possible from multiple buffers). Similarly to previous patches, the code is directly copied from the spdk_trace app. Signed-off-by: Konrad Sztyber Change-Id: Ie7594d381660ef31c286b5e124d2a6df3835111e Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9434 Tested-by: SPDK CI Jenkins Community-CI: Broadcom CI Reviewed-by: Krzysztof Karas Reviewed-by: Aleksey Marchuk Reviewed-by: Jim Harris --- lib/trace_parser/trace.cpp | 93 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 4 deletions(-) diff --git a/lib/trace_parser/trace.cpp b/lib/trace_parser/trace.cpp index 918d0da49..3c63f02f5 100644 --- a/lib/trace_parser/trace.cpp +++ b/lib/trace_parser/trace.cpp @@ -32,6 +32,7 @@ */ #include "spdk/stdinc.h" +#include "spdk/likely.h" #include "spdk/log.h" #include "spdk/trace_parser.h" #include "spdk/util.h" @@ -61,6 +62,25 @@ public: typedef std::map entry_map; +struct argument_context { + spdk_trace_entry *entry; + spdk_trace_entry_buffer *buffer; + uint16_t lcore; + size_t offset; + + argument_context(spdk_trace_entry *entry, uint16_t lcore) : + entry(entry), lcore(lcore) + { + buffer = reinterpret_cast(entry); + + /* The first argument resides within the spdk_trace_entry structure, so the initial + * offset needs to be adjusted to the start of the spdk_trace_entry.args array + */ + offset = offsetof(spdk_trace_entry, args) - + offsetof(spdk_trace_entry_buffer, data); + } +}; + struct spdk_trace_parser { spdk_trace_parser(const spdk_trace_parser_opts *opts); ~spdk_trace_parser(); @@ -70,6 +90,9 @@ struct spdk_trace_parser { uint64_t tsc_offset() const { return _tsc_offset; } bool next_entry(spdk_trace_parser_entry *entry); private: + spdk_trace_entry_buffer *get_next_buffer(spdk_trace_entry_buffer *buf, uint16_t lcore); + bool build_arg(argument_context *argctx, const spdk_trace_argument *arg, int argid, + spdk_trace_parser_entry *pe); void populate_events(spdk_trace_history *history, int num_entries); bool init(const spdk_trace_parser_opts *opts); void cleanup(); @@ -82,15 +105,77 @@ private: entry_map::iterator _iter; }; -bool -spdk_trace_parser::next_entry(spdk_trace_parser_entry *entry) +spdk_trace_entry_buffer * +spdk_trace_parser::get_next_buffer(spdk_trace_entry_buffer *buf, uint16_t lcore) { + spdk_trace_history *history; + + history = spdk_get_per_lcore_history(_histories, lcore); + assert(history); + + if (spdk_unlikely(static_cast(buf) == + static_cast(&history->entries[history->num_entries - 1]))) { + return reinterpret_cast(&history->entries[0]); + } else { + return buf + 1; + } +} + +bool +spdk_trace_parser::build_arg(argument_context *argctx, const spdk_trace_argument *arg, int argid, + spdk_trace_parser_entry *pe) +{ + spdk_trace_entry *entry = argctx->entry; + spdk_trace_entry_buffer *buffer = argctx->buffer; + size_t curlen, argoff; + + argoff = 0; + while (argoff < arg->size) { + if (argctx->offset == sizeof(buffer->data)) { + buffer = get_next_buffer(buffer, argctx->lcore); + if (spdk_unlikely(buffer->tpoint_id != SPDK_TRACE_MAX_TPOINT_ID || + buffer->tsc != entry->tsc)) { + return false; + } + + argctx->offset = 0; + argctx->buffer = buffer; + } + + curlen = spdk_min(sizeof(buffer->data) - argctx->offset, arg->size - argoff); + if (argoff < sizeof(pe->args[0])) { + memcpy(&pe->args[argid].string[argoff], &buffer->data[argctx->offset], + spdk_min(curlen, sizeof(pe->args[0]) - argoff)); + } + + argctx->offset += curlen; + argoff += curlen; + } + + return true; +} + +bool +spdk_trace_parser::next_entry(spdk_trace_parser_entry *pe) +{ + spdk_trace_tpoint *tpoint; + spdk_trace_entry *entry; + if (_iter == _entries.end()) { return false; } - entry->entry = _iter->second; - entry->lcore = _iter->first.lcore; + pe->entry = entry = _iter->second; + pe->lcore = _iter->first.lcore; + tpoint = &_histories->flags.tpoint[entry->tpoint_id]; + + argument_context argctx(entry, pe->lcore); + for (uint8_t i = 0; i < tpoint->num_args; ++i) { + if (!build_arg(&argctx, &tpoint->args[i], i, pe)) { + SPDK_ERRLOG("Failed to parse tracepoint argument\n"); + return false; + } + } _iter++; return true;