Skip to content

Commit 79e577c

Browse files
namhyungrostedt
authored andcommitted
tracing: Support string type key properly
The string in a trace event is usually recorded as dynamic array which is variable length. But current hist code only support fixed length array so it cannot support most strings. This patch fixes it by checking filter_type of the field and get proper pointer with it. With this, it can get a histogram of exec() based on filenames like below: # cd /sys/kernel/tracing/events/sched/sched_process_exec # cat 'hist:key=filename' > trigger # ps PID TTY TIME CMD 1 ? 00:00:00 init 29 ? 00:00:00 sh 38 ? 00:00:00 ps # ls enable filter format hist id trigger # cat hist # trigger info: hist:keys=filename:vals=hitcount:sort=hitcount:size=2048 [active] { filename: /usr/bin/ps } hitcount: 1 { filename: /usr/bin/ls } hitcount: 1 { filename: /usr/bin/cat } hitcount: 1 Totals: Hits: 3 Entries: 3 Dropped: 0 Link: http://lkml.kernel.org/r/610180d6df0cfdf11ee205452f3b241dea657233.1457029949.git.tom.zanussi@linux.intel.com Cc: Tom Zanussi <[email protected]> Cc: Masami Hiramatsu <[email protected]> Signed-off-by: Namhyung Kim <[email protected]> Tested-by: Masami Hiramatsu <[email protected]> [ Added (unsigned long) typecast to fix compile warning ] Signed-off-by: Steven Rostedt <[email protected]>
1 parent 69a0200 commit 79e577c

File tree

1 file changed

+45
-4
lines changed

1 file changed

+45
-4
lines changed

kernel/trace/trace_events_hist.c

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,28 @@ static u64 hist_field_string(struct hist_field *hist_field, void *event)
5252
return (u64)(unsigned long)addr;
5353
}
5454

55+
static u64 hist_field_dynstring(struct hist_field *hist_field, void *event)
56+
{
57+
u32 str_item = *(u32 *)(event + hist_field->field->offset);
58+
int str_loc = str_item & 0xffff;
59+
char *addr = (char *)(event + str_loc);
60+
61+
return (u64)(unsigned long)addr;
62+
}
63+
64+
static u64 hist_field_pstring(struct hist_field *hist_field, void *event)
65+
{
66+
char **addr = (char **)(event + hist_field->field->offset);
67+
68+
return (u64)(unsigned long)*addr;
69+
}
70+
5571
#define DEFINE_HIST_FIELD_FN(type) \
5672
static u64 hist_field_##type(struct hist_field *hist_field, void *event)\
5773
{ \
5874
type *addr = (type *)(event + hist_field->field->offset); \
5975
\
60-
return (u64)*addr; \
76+
return (u64)(unsigned long)*addr; \
6177
}
6278

6379
DEFINE_HIST_FIELD_FN(s64);
@@ -340,7 +356,13 @@ static struct hist_field *create_hist_field(struct ftrace_event_field *field,
340356

341357
if (is_string_field(field)) {
342358
flags |= HIST_FIELD_FL_STRING;
343-
hist_field->fn = hist_field_string;
359+
360+
if (field->filter_type == FILTER_STATIC_STRING)
361+
hist_field->fn = hist_field_string;
362+
else if (field->filter_type == FILTER_DYN_STRING)
363+
hist_field->fn = hist_field_dynstring;
364+
else
365+
hist_field->fn = hist_field_pstring;
344366
} else {
345367
hist_field->fn = select_value_fn(field->size,
346368
field->is_signed);
@@ -508,7 +530,10 @@ static int create_key_field(struct hist_trigger_data *hist_data,
508530
goto out;
509531
}
510532

511-
key_size = field->size;
533+
if (is_string_field(field)) /* should be last key field */
534+
key_size = HIST_KEY_SIZE_MAX - key_offset;
535+
else
536+
key_size = field->size;
512537
}
513538

514539
hist_data->fields[key_idx] = create_hist_field(field, flags);
@@ -841,8 +866,24 @@ static void event_hist_trigger(struct event_trigger_data *data, void *rec)
841866
key = (void *)&field_contents;
842867

843868
if (hist_data->n_keys > 1) {
869+
/* ensure NULL-termination */
870+
size_t size = key_field->size - 1;
871+
872+
if (key_field->flags & HIST_FIELD_FL_STRING) {
873+
struct ftrace_event_field *field;
874+
875+
field = key_field->field;
876+
if (field->filter_type == FILTER_DYN_STRING)
877+
size = *(u32 *)(rec + field->offset) >> 16;
878+
else if (field->filter_type == FILTER_PTR_STRING)
879+
size = strlen(key);
880+
881+
if (size > key_field->size - 1)
882+
size = key_field->size - 1;
883+
}
884+
844885
memcpy(compound_key + key_field->offset, key,
845-
key_field->size);
886+
size);
846887
}
847888
}
848889
}

0 commit comments

Comments
 (0)