Skip to content

Commit f5914b3

Browse files
Tom Zanussirostedt
authored andcommitted
tracing/histogram: Fix stacktrace key
The current code will always use the current stacktrace as a key even if a stacktrace contained in a specific event field was specified. For example, we expect to use the 'unsigned long[] stack' field in the below event in the histogram: # echo 's:block_lat pid_t pid; u64 delta; unsigned long[] stack;' > /sys/kernel/debug/tracing/dynamic_events # echo 'hist:keys=delta.buckets=100,stack.stacktrace:sort=delta' > /sys/kernel/debug/tracing/events/synthetic/block_lat/trigger But in fact, when we type out the trigger, we see that it's using the plain old global 'stacktrace' as the key, which is just the stacktrace when the event was hit and not the stacktrace contained in the event, which is what we want: # cat /sys/kernel/debug/tracing/events/synthetic/block_lat/trigger hist:keys=delta.buckets=100,stacktrace:vals=hitcount:sort=delta.buckets=100:size=2048 [active] And in fact, there's no code to actually retrieve it from the event, so we need to add HIST_FIELD_FN_STACK and hist_field_stack() to get it and hook it into the trigger code. For now, since the stack is just using dynamic strings, this could just use the dynamic string function, but it seems cleaner to have a dedicated function an be able to tweak independently as necessary. Link: https://lkml.kernel.org/r/11aa614c82976adbfa4ea763dbe885b5fb01d59c.1676063532.git.zanussi@kernel.org Signed-off-by: Tom Zanussi <[email protected]> [ Fixed 32bit build warning reported by kernel test robot <[email protected]> ] Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent 2bacfd9 commit f5914b3

File tree

1 file changed

+31
-3
lines changed

1 file changed

+31
-3
lines changed

kernel/trace/trace_events_hist.c

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ enum hist_field_fn {
135135
HIST_FIELD_FN_DIV_NOT_POWER2,
136136
HIST_FIELD_FN_DIV_MULT_SHIFT,
137137
HIST_FIELD_FN_EXECNAME,
138+
HIST_FIELD_FN_STACK,
138139
};
139140

140141
/*
@@ -1982,7 +1983,10 @@ static struct hist_field *create_hist_field(struct hist_trigger_data *hist_data,
19821983
}
19831984

19841985
if (flags & HIST_FIELD_FL_STACKTRACE) {
1985-
hist_field->fn_num = HIST_FIELD_FN_NOP;
1986+
if (field)
1987+
hist_field->fn_num = HIST_FIELD_FN_STACK;
1988+
else
1989+
hist_field->fn_num = HIST_FIELD_FN_NOP;
19861990
hist_field->size = HIST_STACKTRACE_SIZE;
19871991
hist_field->type = kstrdup_const("unsigned long[]", GFP_KERNEL);
19881992
if (!hist_field->type)
@@ -4274,6 +4278,19 @@ static u64 hist_field_execname(struct hist_field *hist_field,
42744278
return (u64)(unsigned long)(elt_data->comm);
42754279
}
42764280

4281+
static u64 hist_field_stack(struct hist_field *hist_field,
4282+
struct tracing_map_elt *elt,
4283+
struct trace_buffer *buffer,
4284+
struct ring_buffer_event *rbe,
4285+
void *event)
4286+
{
4287+
u32 str_item = *(u32 *)(event + hist_field->field->offset);
4288+
int str_loc = str_item & 0xffff;
4289+
char *addr = (char *)(event + str_loc);
4290+
4291+
return (u64)(unsigned long)addr;
4292+
}
4293+
42774294
static u64 hist_fn_call(struct hist_field *hist_field,
42784295
struct tracing_map_elt *elt,
42794296
struct trace_buffer *buffer,
@@ -4337,6 +4354,8 @@ static u64 hist_fn_call(struct hist_field *hist_field,
43374354
return div_by_mult_and_shift(hist_field, elt, buffer, rbe, event);
43384355
case HIST_FIELD_FN_EXECNAME:
43394356
return hist_field_execname(hist_field, elt, buffer, rbe, event);
4357+
case HIST_FIELD_FN_STACK:
4358+
return hist_field_stack(hist_field, elt, buffer, rbe, event);
43404359
default:
43414360
return 0;
43424361
}
@@ -5238,8 +5257,17 @@ static void event_hist_trigger(struct event_trigger_data *data,
52385257

52395258
if (key_field->flags & HIST_FIELD_FL_STACKTRACE) {
52405259
memset(entries, 0, HIST_STACKTRACE_SIZE);
5241-
stack_trace_save(entries, HIST_STACKTRACE_DEPTH,
5242-
HIST_STACKTRACE_SKIP);
5260+
if (key_field->field) {
5261+
unsigned long *stack, n_entries;
5262+
5263+
field_contents = hist_fn_call(key_field, elt, buffer, rbe, rec);
5264+
stack = (unsigned long *)(long)field_contents;
5265+
n_entries = *stack;
5266+
memcpy(entries, ++stack, n_entries * sizeof(unsigned long));
5267+
} else {
5268+
stack_trace_save(entries, HIST_STACKTRACE_DEPTH,
5269+
HIST_STACKTRACE_SKIP);
5270+
}
52435271
key = entries;
52445272
} else {
52455273
field_contents = hist_fn_call(key_field, elt, buffer, rbe, rec);

0 commit comments

Comments
 (0)