trace: enable adding relations between traces

Currently we do not have any way to connect traces from different
modules in SPDK. This change modifies our trace library
and app/trace to handle adding relations between trace points
and a trace object.

Additionally this patch adds classes and fields to structs
inside trace.py to prepare it for future patches implementing
printing relation information.

Change-Id: Ia09d01244d923957d589fd37e6d4c98f9f7bbd07
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9620
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Konrad Sztyber <konrad.sztyber@gmail.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
This commit is contained in:
Krzysztof Karas 2021-10-19 10:02:46 +00:00 committed by Jim Harris
parent 84ab68c1a3
commit 70c171602a
8 changed files with 102 additions and 6 deletions

View File

@ -123,9 +123,21 @@ print_size(uint32_t size)
}
static void
print_object_id(uint8_t type, uint64_t id)
print_object_id(const struct spdk_trace_tpoint *d, struct spdk_trace_parser_entry *entry)
{
printf("id: %c%-15jd ", g_flags->object[type].id_prefix, id);
/* Set size to 128 and 256 bytes to make sure we can fit all the characters we need */
char related_id[128] = {'\0'};
char ids[256] = {'\0'};
if (entry->related_type != OBJECT_NONE) {
snprintf(related_id, sizeof(related_id), " (%c%jd)",
g_flags->object[entry->related_type].id_prefix,
entry->related_index);
}
snprintf(ids, sizeof(ids), "%c%jd%s", g_flags->object[d->object_type].id_prefix,
entry->object_index, related_id);
printf("id: %-17s", ids);
}
static void
@ -159,11 +171,11 @@ print_event(struct spdk_trace_parser_entry *entry, uint64_t tsc_rate, uint64_t t
print_size(e->size);
if (d->new_object) {
print_object_id(d->object_type, entry->object_index);
print_object_id(d, entry);
} else if (d->object_type != OBJECT_NONE) {
if (entry->object_index != UINT64_MAX) {
us = get_us_from_tsc(e->tsc - entry->object_start, tsc_rate);
print_object_id(d->object_type, entry->object_index);
print_object_id(d, entry);
print_float("time", us);
} else {
printf("id: N/A");

View File

@ -91,6 +91,7 @@ struct spdk_trace_object {
#define SPDK_TRACE_ARG_TYPE_STR 2
#define SPDK_TRACE_MAX_ARGS_COUNT 5
#define SPDK_TRACE_MAX_RELATIONS 16
struct spdk_trace_argument {
char name[14];
@ -106,6 +107,11 @@ struct spdk_trace_tpoint {
uint8_t new_object;
uint8_t num_args;
struct spdk_trace_argument args[SPDK_TRACE_MAX_ARGS_COUNT];
/** Relations between tracepoint and trace object */
struct {
uint8_t object_type;
uint8_t arg_index;
} related_objects[SPDK_TRACE_MAX_RELATIONS];
};
struct spdk_trace_history {
@ -375,6 +381,17 @@ struct spdk_trace_register_fn *spdk_trace_get_first_register_fn(void);
struct spdk_trace_register_fn *spdk_trace_get_next_register_fn(struct spdk_trace_register_fn
*register_fn);
/**
* Bind trace type to a given trace object. This allows for matching traces
* with the same parent trace object.
*
* \param tpoint_id Type of trace to be bound
* \param object_type Tracepoint object type to bind to
* \param arg_index Index of argument containing context information
*/
void spdk_trace_tpoint_register_relation(uint16_t tpoint_id, uint8_t object_type,
uint8_t arg_index);
/**
* Enable trace on specific tpoint group
*

View File

@ -115,6 +115,10 @@ struct spdk_trace_parser_entry {
uint64_t object_start;
/** Logical core number */
uint16_t lcore;
/** Related object index */
uint64_t related_index;
/** Related object type */
uint8_t related_type;
/** Tracepoint arguments */
union {
uint64_t integer;

View File

@ -34,7 +34,7 @@
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
SO_VER := 4
SO_VER := 5
SO_MINOR := 0
C_SRCS = trace.c trace_flags.c trace_rpc.c

View File

@ -22,6 +22,7 @@
spdk_trace_disable_tpoint_group;
spdk_trace_mask_usage;
spdk_trace_add_register_fn;
spdk_trace_tpoint_register_relation;
# public variables
g_trace_histories;

View File

@ -36,6 +36,7 @@
#include "spdk/env.h"
#include "spdk/trace.h"
#include "spdk/log.h"
#include "spdk/util.h"
struct spdk_trace_flags *g_trace_flags = NULL;
static struct spdk_trace_register_fn *g_reg_fn_head = NULL;
@ -370,6 +371,36 @@ spdk_trace_register_description(const char *name, uint16_t tpoint_id, uint8_t ow
spdk_trace_register_description_ext(&opts, 1);
}
void
spdk_trace_tpoint_register_relation(uint16_t tpoint_id, uint8_t object_type, uint8_t arg_index)
{
struct spdk_trace_tpoint *tpoint;
uint16_t i;
assert(object_type != OBJECT_NONE);
assert(tpoint_id != OBJECT_NONE);
if (g_trace_flags == NULL) {
SPDK_ERRLOG("trace is not initialized\n");
return;
}
/* We do not check whether a tpoint_id exists here, because
* there is no order in which trace definitions are registered.
* This way we can create relations between tpoint and objects
* that will be declared later. */
tpoint = &g_trace_flags->tpoint[tpoint_id];
for (i = 0; i < SPDK_COUNTOF(tpoint->related_objects); ++i) {
if (tpoint->related_objects[i].object_type == OBJECT_NONE) {
tpoint->related_objects[i].object_type = object_type;
tpoint->related_objects[i].arg_index = arg_index;
return;
}
}
SPDK_ERRLOG("Unable to register new relation for tpoint %" PRIu16 ", object %" PRIu8 "\n",
tpoint_id, object_type);
}
void
spdk_trace_add_register_fn(struct spdk_trace_register_fn *reg_fn)
{

View File

@ -186,6 +186,7 @@ spdk_trace_parser::next_entry(spdk_trace_parser_entry *pe)
spdk_trace_tpoint *tpoint;
spdk_trace_entry *entry;
object_stats *stats;
std::map<uint64_t, uint64_t>::iterator related_kv;
if (_iter == _entries.end()) {
return false;
@ -193,6 +194,9 @@ spdk_trace_parser::next_entry(spdk_trace_parser_entry *pe)
pe->entry = entry = _iter->second;
pe->lcore = _iter->first.lcore;
/* Set related index to the max value to indicate "empty" state */
pe->related_index = UINT64_MAX;
pe->related_type = OBJECT_NONE;
tpoint = &_histories->flags.tpoint[entry->tpoint_id];
stats = &_stats[tpoint->object_type];
@ -219,6 +223,24 @@ spdk_trace_parser::next_entry(spdk_trace_parser_entry *pe)
}
}
for (uint8_t i = 0; i < SPDK_TRACE_MAX_RELATIONS; ++i) {
/* The relations are stored inside a tpoint, which means there might be
* multiple objects bound to a single tpoint. */
if (tpoint->related_objects[i].object_type == OBJECT_NONE) {
break;
}
stats = &_stats[tpoint->related_objects[i].object_type];
related_kv = stats->index.find(reinterpret_cast<uint64_t>
(pe->args[tpoint->related_objects[i].arg_index].pointer));
/* To avoid parsing the whole array, object index and type are stored
* directly inside spdk_trace_parser_entry. */
if (related_kv != stats->index.end()) {
pe->related_index = related_kv->second;
pe->related_type = tpoint->related_objects[i].object_type;
break;
}
}
_iter++;
return true;
}

View File

@ -19,6 +19,7 @@ TRACE_MAX_LCORE = 128
TRACE_MAX_GROUP_ID = 16
TRACE_MAX_TPOINT_ID = TRACE_MAX_GROUP_ID * 64
TRACE_MAX_ARGS_COUNT = 5
TRACE_MAX_RELATIONS = 16
TRACE_INVALID_OBJECT = (1 << 64) - 1
OBJECT_NONE = 0
OWNER_NONE = 0
@ -278,6 +279,11 @@ class CTpointArgument(ct.Structure):
('size', ct.c_uint8)]
class CTpointRelatedObject(ct.Structure):
_fields_ = [('object_type', ct.c_uint8),
('arg_index', ct.c_uint8)]
class CTracepoint(ct.Structure):
_fields_ = [('name', ct.c_char * 24),
('tpoint_id', ct.c_uint16),
@ -285,7 +291,8 @@ class CTracepoint(ct.Structure):
('object_type', ct.c_uint8),
('new_object', ct.c_uint8),
('num_args', ct.c_uint8),
('args', CTpointArgument * TRACE_MAX_ARGS_COUNT)]
('args', CTpointArgument * TRACE_MAX_ARGS_COUNT),
('related_objects', CTpointRelatedObject * TRACE_MAX_RELATIONS)]
class CTraceFlags(ct.Structure):
@ -315,6 +322,8 @@ class CTraceParserEntry(ct.Structure):
('object_index', ct.c_uint64),
('object_start', ct.c_uint64),
('lcore', ct.c_uint16),
('related_index', ct.c_uint64),
('related_type', ct.c_uint8),
('args', CTraceParserArgument * TRACE_MAX_ARGS_COUNT)]