tracing: Add hist trigger 'log2' modifier

Allow users to have numeric fields displayed as log2 values in case
value range is very wide by appending '.log2' to field names.

For example,

  # echo 'hist:key=bytes_req' > kmalloc/trigger
  # cat kmalloc/hist

  { bytes_req:        504 } hitcount:          1
  { bytes_req:         11 } hitcount:          1
  { bytes_req:        104 } hitcount:          1
  { bytes_req:         48 } hitcount:          1
  { bytes_req:       2048 } hitcount:          1
  { bytes_req:       4096 } hitcount:          1
  { bytes_req:        240 } hitcount:          1
  { bytes_req:        392 } hitcount:          1
  { bytes_req:         13 } hitcount:          1
  { bytes_req:         28 } hitcount:          1
  { bytes_req:         12 } hitcount:          1
  { bytes_req:         64 } hitcount:          2
  { bytes_req:        128 } hitcount:          2
  { bytes_req:         32 } hitcount:          2
  { bytes_req:          8 } hitcount:         11
  { bytes_req:         10 } hitcount:         13
  { bytes_req:         24 } hitcount:         25
  { bytes_req:        160 } hitcount:         29
  { bytes_req:         16 } hitcount:         33
  { bytes_req:         80 } hitcount:         36

When using '.log2' modifier, the output looks like:

  # echo 'hist:key=bytes_req.log2' > kmalloc/trigger
  # cat kmalloc/hist

  { bytes_req: ~ 2^12 } hitcount:          1
  { bytes_req: ~ 2^11 } hitcount:          1
  { bytes_req: ~ 2^9  } hitcount:          2
  { bytes_req: ~ 2^6  } hitcount:          3
  { bytes_req: ~ 2^3  } hitcount:         13
  { bytes_req: ~ 2^5  } hitcount:         19
  { bytes_req: ~ 2^8  } hitcount:         49
  { bytes_req: ~ 2^7  } hitcount:         57
  { bytes_req: ~ 2^4  } hitcount:         74

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

Cc: Tom Zanussi <tom.zanussi@linux.intel.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
Namhyung Kim 2016-03-03 12:55:02 -06:00 committed by Steven Rostedt
parent 76929ab51f
commit 4b94f5b7b4
2 changed files with 21 additions and 0 deletions

View File

@ -3872,6 +3872,7 @@ static const char readme_msg[] =
"\t .sym-offset display an address as a symbol and offset\n" "\t .sym-offset display an address as a symbol and offset\n"
"\t .execname display a common_pid as a program name\n" "\t .execname display a common_pid as a program name\n"
"\t .syscall display a syscall id as a syscall name\n\n" "\t .syscall display a syscall id as a syscall name\n\n"
"\t .log2 display log2 value rather than raw number\n\n"
"\t The 'pause' parameter can be used to pause an existing hist\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 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" "\t until told to do so. 'continue' can be used to start or\n"

View File

@ -68,6 +68,13 @@ static u64 hist_field_pstring(struct hist_field *hist_field, void *event)
return (u64)(unsigned long)*addr; return (u64)(unsigned long)*addr;
} }
static u64 hist_field_log2(struct hist_field *hist_field, void *event)
{
u64 val = *(u64 *)(event + hist_field->field->offset);
return (u64) ilog2(roundup_pow_of_two(val));
}
#define DEFINE_HIST_FIELD_FN(type) \ #define DEFINE_HIST_FIELD_FN(type) \
static u64 hist_field_##type(struct hist_field *hist_field, void *event)\ static u64 hist_field_##type(struct hist_field *hist_field, void *event)\
{ \ { \
@ -111,6 +118,7 @@ enum hist_field_flags {
HIST_FIELD_FL_EXECNAME = 64, HIST_FIELD_FL_EXECNAME = 64,
HIST_FIELD_FL_SYSCALL = 128, HIST_FIELD_FL_SYSCALL = 128,
HIST_FIELD_FL_STACKTRACE = 256, HIST_FIELD_FL_STACKTRACE = 256,
HIST_FIELD_FL_LOG2 = 512,
}; };
struct hist_trigger_attrs { struct hist_trigger_attrs {
@ -358,6 +366,11 @@ static struct hist_field *create_hist_field(struct ftrace_event_field *field,
goto out; goto out;
} }
if (flags & HIST_FIELD_FL_LOG2) {
hist_field->fn = hist_field_log2;
goto out;
}
if (is_string_field(field)) { if (is_string_field(field)) {
flags |= HIST_FIELD_FL_STRING; flags |= HIST_FIELD_FL_STRING;
@ -522,6 +535,8 @@ static int create_key_field(struct hist_trigger_data *hist_data,
flags |= HIST_FIELD_FL_EXECNAME; flags |= HIST_FIELD_FL_EXECNAME;
else if (strcmp(field_str, "syscall") == 0) else if (strcmp(field_str, "syscall") == 0)
flags |= HIST_FIELD_FL_SYSCALL; flags |= HIST_FIELD_FL_SYSCALL;
else if (strcmp(field_str, "log2") == 0)
flags |= HIST_FIELD_FL_LOG2;
else { else {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
@ -980,6 +995,9 @@ hist_trigger_entry_print(struct seq_file *m,
key + key_field->offset, key + key_field->offset,
HIST_STACKTRACE_DEPTH); HIST_STACKTRACE_DEPTH);
multiline = true; multiline = true;
} else if (key_field->flags & HIST_FIELD_FL_LOG2) {
seq_printf(m, "%s: ~ 2^%-2llu", key_field->field->name,
*(u64 *)(key + key_field->offset));
} else if (key_field->flags & HIST_FIELD_FL_STRING) { } else if (key_field->flags & HIST_FIELD_FL_STRING) {
seq_printf(m, "%s: %-50s", key_field->field->name, seq_printf(m, "%s: %-50s", key_field->field->name,
(char *)(key + key_field->offset)); (char *)(key + key_field->offset));
@ -1112,6 +1130,8 @@ static const char *get_hist_field_flags(struct hist_field *hist_field)
flags_str = "execname"; flags_str = "execname";
else if (hist_field->flags & HIST_FIELD_FL_SYSCALL) else if (hist_field->flags & HIST_FIELD_FL_SYSCALL)
flags_str = "syscall"; flags_str = "syscall";
else if (hist_field->flags & HIST_FIELD_FL_LOG2)
flags_str = "log2";
return flags_str; return flags_str;
} }