tracing: Add hist trigger 'hex' modifier for displaying numeric fields

Allow users to have numeric fields displayed as hex values in the
output by appending '.hex' to field names:

   # echo hist:keys=aaa,bbb.hex:vals=ccc.hex ... \
              [ if filter] > event/trigger

Link: http://lkml.kernel.org/r/67bd431edda2af5798d7694818f7e8d71b6b3463.1457029949.git.tom.zanussi@linux.intel.com

Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com>
Tested-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
Tom Zanussi 2016-03-03 12:54:48 -06:00 committed by Steven Rostedt
parent e86ae9baac
commit 0c4a6b4666
2 changed files with 60 additions and 7 deletions

View File

@ -3852,7 +3852,10 @@ static const char readme_msg[] =
"\t used to specify more or fewer than the default 2048 entries\n"
"\t for the hashtable size.\n\n"
"\t Reading the 'hist' file for the event will dump the hash\n"
"\t table in its entirety to stdout.\n\n"
"\t table in its entirety to stdout. The default format used to\n"
"\t display a given field can be modified by appending any of the\n"
"\t following modifiers to the field name, as applicable:\n\n"
"\t .hex display a number as a hex value\n\n"
"\t The 'pause' parameter can be used to pause an existing hist\n"
"\t trigger or to start a hist trigger but not log any events\n"
"\t until told to do so. 'continue' can be used to start or\n"

View File

@ -80,6 +80,7 @@ enum hist_field_flags {
HIST_FIELD_FL_HITCOUNT = 1,
HIST_FIELD_FL_KEY = 2,
HIST_FIELD_FL_STRING = 4,
HIST_FIELD_FL_HEX = 8,
};
struct hist_trigger_attrs {
@ -303,11 +304,23 @@ static int create_val_field(struct hist_trigger_data *hist_data,
{
struct ftrace_event_field *field = NULL;
unsigned long flags = 0;
char *field_name;
int ret = 0;
if (WARN_ON(val_idx >= TRACING_MAP_VALS_MAX))
return -EINVAL;
field = trace_find_event_field(file->event_call, field_str);
field_name = strsep(&field_str, ".");
if (field_str) {
if (strcmp(field_str, "hex") == 0)
flags |= HIST_FIELD_FL_HEX;
else {
ret = -EINVAL;
goto out;
}
}
field = trace_find_event_field(file->event_call, field_name);
if (!field) {
ret = -EINVAL;
goto out;
@ -372,6 +385,7 @@ static int create_key_field(struct hist_trigger_data *hist_data,
struct ftrace_event_field *field = NULL;
unsigned long flags = 0;
unsigned int key_size;
char *field_name;
int ret = 0;
if (WARN_ON(key_idx >= TRACING_MAP_FIELDS_MAX))
@ -379,7 +393,17 @@ static int create_key_field(struct hist_trigger_data *hist_data,
flags |= HIST_FIELD_FL_KEY;
field = trace_find_event_field(file->event_call, field_str);
field_name = strsep(&field_str, ".");
if (field_str) {
if (strcmp(field_str, "hex") == 0)
flags |= HIST_FIELD_FL_HEX;
else {
ret = -EINVAL;
goto out;
}
}
field = trace_find_event_field(file->event_call, field_name);
if (!field) {
ret = -EINVAL;
goto out;
@ -713,7 +737,11 @@ hist_trigger_entry_print(struct seq_file *m,
if (i > hist_data->n_vals)
seq_puts(m, ", ");
if (key_field->flags & HIST_FIELD_FL_STRING) {
if (key_field->flags & HIST_FIELD_FL_HEX) {
uval = *(u64 *)(key + key_field->offset);
seq_printf(m, "%s: %llx",
key_field->field->name, uval);
} else if (key_field->flags & HIST_FIELD_FL_STRING) {
seq_printf(m, "%s: %-50s", key_field->field->name,
(char *)(key + key_field->offset));
} else {
@ -729,10 +757,16 @@ hist_trigger_entry_print(struct seq_file *m,
tracing_map_read_sum(elt, HITCOUNT_IDX));
for (i = 1; i < hist_data->n_vals; i++) {
if (hist_data->fields[i]->flags & HIST_FIELD_FL_HEX) {
seq_printf(m, " %s: %10llx",
hist_data->fields[i]->field->name,
tracing_map_read_sum(elt, i));
} else {
seq_printf(m, " %s: %10llu",
hist_data->fields[i]->field->name,
tracing_map_read_sum(elt, i));
}
}
seq_puts(m, "\n");
}
@ -816,9 +850,25 @@ const struct file_operations event_hist_fops = {
.release = single_release,
};
static const char *get_hist_field_flags(struct hist_field *hist_field)
{
const char *flags_str = NULL;
if (hist_field->flags & HIST_FIELD_FL_HEX)
flags_str = "hex";
return flags_str;
}
static void hist_field_print(struct seq_file *m, struct hist_field *hist_field)
{
seq_printf(m, "%s", hist_field->field->name);
if (hist_field->flags) {
const char *flags_str = get_hist_field_flags(hist_field);
if (flags_str)
seq_printf(m, ".%s", flags_str);
}
}
static int event_hist_trigger_print(struct seq_file *m,