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:
parent
84ab68c1a3
commit
70c171602a
@ -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");
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)]
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user