Commit e91eefd7 authored by Tom Zanussi's avatar Tom Zanussi Committed by Steven Rostedt (VMware)

tracing: Add alternative synthetic event trace action syntax

Add a 'trace(synthetic_event_name, params)' alternative to
synthetic_event_name(params).

Currently, the syntax used for generating synthetic events is to
invoke synthetic_event_name(params) i.e. use the synthetic event name
as a function call.

Users requested a new form that more explicitly shows that the
synthetic event is in effect being traced.  In this version, a new
'trace()' keyword is used, and the synthetic event name is passed in
as the first argument.

In addition, for the sake of consistency with other actions, change
the documention to emphasize the trace() form over the function-call
form, which remains documented as equivalent.

Link: http://lkml.kernel.org/r/d082773e50232a001480cf837679a1e01c1a2eb7.1550100284.git.tom.zanussi@linux.intel.comSigned-off-by: default avatarTom Zanussi <tom.zanussi@linux.intel.com>
Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
parent ff0d35e2
...@@ -1873,31 +1873,45 @@ The available handlers are: ...@@ -1873,31 +1873,45 @@ The available handlers are:
The available actions are: The available actions are:
- <synthetic_event_name>(param list) - generate synthetic event - trace(<synthetic_event_name>,param list) - generate synthetic event
- save(field,...) - save current event fields - save(field,...) - save current event fields
- snapshot() - snapshot the trace buffer - snapshot() - snapshot the trace buffer
The following commonly-used handler.action pairs are available: The following commonly-used handler.action pairs are available:
- onmatch(matching.event).<synthetic_event_name>(param list) - onmatch(matching.event).trace(<synthetic_event_name>,param list)
The 'onmatch(matching.event).<synthetic_event_name>(params)' hist The 'onmatch(matching.event).trace(<synthetic_event_name>,param
trigger action is invoked whenever an event matches and the list)' hist trigger action is invoked whenever an event matches
histogram entry would be added or updated. It causes the named and the histogram entry would be added or updated. It causes the
synthetic event to be generated with the values given in the named synthetic event to be generated with the values given in the
'param list'. The result is the generation of a synthetic event 'param list'. The result is the generation of a synthetic event
that consists of the values contained in those variables at the that consists of the values contained in those variables at the
time the invoking event was hit. time the invoking event was hit. For example, if the synthetic
event name is 'wakeup_latency', a wakeup_latency event is
The 'param list' consists of one or more parameters which may be generated using onmatch(event).trace(wakeup_latency,arg1,arg2).
either variables or fields defined on either the 'matching.event'
or the target event. The variables or fields specified in the There is also an equivalent alternative form available for
param list may be either fully-qualified or unqualified. If a generating synthetic events. In this form, the synthetic event
variable is specified as unqualified, it must be unique between name is used as if it were a function name. For example, using
the two events. A field name used as a param can be unqualified the 'wakeup_latency' synthetic event name again, the
if it refers to the target event, but must be fully qualified if wakeup_latency event would be generated by invoking it as if it
it refers to the matching event. A fully-qualified name is of the were a function call, with the event field values passed in as
form 'system.event_name.$var_name' or 'system.event_name.field'. arguments: onmatch(event).wakeup_latency(arg1,arg2). The syntax
for this form is:
onmatch(matching.event).<synthetic_event_name>(param list)
In either case, the 'param list' consists of one or more
parameters which may be either variables or fields defined on
either the 'matching.event' or the target event. The variables or
fields specified in the param list may be either fully-qualified
or unqualified. If a variable is specified as unqualified, it
must be unique between the two events. A field name used as a
param can be unqualified if it refers to the target event, but
must be fully qualified if it refers to the matching event. A
fully-qualified name is of the form 'system.event_name.$var_name'
or 'system.event_name.field'.
The 'matching.event' specification is simply the fully qualified The 'matching.event' specification is simply the fully qualified
event name of the event that matches the target event for the event name of the event that matches the target event for the
...@@ -1928,6 +1942,12 @@ The following commonly-used handler.action pairs are available: ...@@ -1928,6 +1942,12 @@ The following commonly-used handler.action pairs are available:
wakeup_new_test($testpid) if comm=="cyclictest"' >> \ wakeup_new_test($testpid) if comm=="cyclictest"' >> \
/sys/kernel/debug/tracing/events/sched/sched_wakeup_new/trigger /sys/kernel/debug/tracing/events/sched/sched_wakeup_new/trigger
Or, equivalently, using the 'trace' keyword syntax:
# echo 'hist:keys=$testpid:testpid=pid:onmatch(sched.sched_wakeup_new).\
trace(wakeup_new_test,$testpid) if comm=="cyclictest"' >> \
/sys/kernel/debug/tracing/events/sched/sched_wakeup_new/trigger
Creating and displaying a histogram based on those events is now Creating and displaying a histogram based on those events is now
just a matter of using the fields and new synthetic event in the just a matter of using the fields and new synthetic event in the
tracing/events/synthetic directory, as usual:: tracing/events/synthetic directory, as usual::
......
...@@ -4918,7 +4918,7 @@ static const char readme_msg[] = ...@@ -4918,7 +4918,7 @@ static const char readme_msg[] =
"\t onmax(var) - invoke if var exceeds current max\n" "\t onmax(var) - invoke if var exceeds current max\n"
"\t onchange(var) - invoke action if var changes\n\n" "\t onchange(var) - invoke action if var changes\n\n"
"\t The available actions are:\n\n" "\t The available actions are:\n\n"
"\t <synthetic_event>(param list) - generate synthetic event\n" "\t trace(<synthetic_event>,param list) - generate synthetic event\n"
"\t save(field,...) - save current event fields\n" "\t save(field,...) - save current event fields\n"
#ifdef CONFIG_TRACER_SNAPSHOT #ifdef CONFIG_TRACER_SNAPSHOT
"\t snapshot() - snapshot the trace buffer\n" "\t snapshot() - snapshot the trace buffer\n"
......
...@@ -419,6 +419,8 @@ struct action_data { ...@@ -419,6 +419,8 @@ struct action_data {
*/ */
unsigned int var_ref_idx; unsigned int var_ref_idx;
struct synth_event *synth_event; struct synth_event *synth_event;
bool use_trace_keyword;
char *synth_event_name;
union { union {
struct { struct {
...@@ -3700,6 +3702,8 @@ static void action_data_destroy(struct action_data *data) ...@@ -3700,6 +3702,8 @@ static void action_data_destroy(struct action_data *data)
if (data->synth_event) if (data->synth_event)
data->synth_event->ref--; data->synth_event->ref--;
kfree(data->synth_event_name);
kfree(data); kfree(data);
} }
...@@ -3781,6 +3785,7 @@ static int track_data_create(struct hist_trigger_data *hist_data, ...@@ -3781,6 +3785,7 @@ static int track_data_create(struct hist_trigger_data *hist_data,
static int parse_action_params(char *params, struct action_data *data) static int parse_action_params(char *params, struct action_data *data)
{ {
char *param, *saved_param; char *param, *saved_param;
bool first_param = true;
int ret = 0; int ret = 0;
while (params) { while (params) {
...@@ -3809,6 +3814,13 @@ static int parse_action_params(char *params, struct action_data *data) ...@@ -3809,6 +3814,13 @@ static int parse_action_params(char *params, struct action_data *data)
goto out; goto out;
} }
if (first_param && data->use_trace_keyword) {
data->synth_event_name = saved_param;
first_param = false;
continue;
}
first_param = false;
data->params[data->n_params++] = saved_param; data->params[data->n_params++] = saved_param;
} }
out: out:
...@@ -3886,6 +3898,9 @@ static int action_parse(char *str, struct action_data *data, ...@@ -3886,6 +3898,9 @@ static int action_parse(char *str, struct action_data *data,
} else { } else {
char *params = strsep(&str, ")"); char *params = strsep(&str, ")");
if (str_has_prefix(action_name, "trace"))
data->use_trace_keyword = true;
if (params) { if (params) {
ret = parse_action_params(params, data); ret = parse_action_params(params, data);
if (ret) if (ret)
...@@ -4088,13 +4103,19 @@ static int trace_action_create(struct hist_trigger_data *hist_data, ...@@ -4088,13 +4103,19 @@ static int trace_action_create(struct hist_trigger_data *hist_data,
unsigned int i, var_ref_idx; unsigned int i, var_ref_idx;
unsigned int field_pos = 0; unsigned int field_pos = 0;
struct synth_event *event; struct synth_event *event;
char *synth_event_name;
int ret = 0; int ret = 0;
lockdep_assert_held(&event_mutex); lockdep_assert_held(&event_mutex);
event = find_synth_event(data->action_name); if (data->use_trace_keyword)
synth_event_name = data->synth_event_name;
else
synth_event_name = data->action_name;
event = find_synth_event(synth_event_name);
if (!event) { if (!event) {
hist_err("trace action: Couldn't find synthetic event: ", data->action_name); hist_err("trace action: Couldn't find synthetic event: ", synth_event_name);
return -EINVAL; return -EINVAL;
} }
...@@ -4841,8 +4862,10 @@ static void print_action_spec(struct seq_file *m, ...@@ -4841,8 +4862,10 @@ static void print_action_spec(struct seq_file *m,
seq_puts(m, ","); seq_puts(m, ",");
} }
} else if (data->action == ACTION_TRACE) { } else if (data->action == ACTION_TRACE) {
if (data->use_trace_keyword)
seq_printf(m, "%s", data->synth_event_name);
for (i = 0; i < data->n_params; i++) { for (i = 0; i < data->n_params; i++) {
if (i) if (i || data->use_trace_keyword)
seq_puts(m, ","); seq_puts(m, ",");
seq_printf(m, "%s", data->params[i]); seq_printf(m, "%s", data->params[i]);
} }
...@@ -4890,6 +4913,7 @@ static bool actions_match(struct hist_trigger_data *hist_data, ...@@ -4890,6 +4913,7 @@ static bool actions_match(struct hist_trigger_data *hist_data,
for (i = 0; i < hist_data->n_actions; i++) { for (i = 0; i < hist_data->n_actions; i++) {
struct action_data *data = hist_data->actions[i]; struct action_data *data = hist_data->actions[i];
struct action_data *data_test = hist_data_test->actions[i]; struct action_data *data_test = hist_data_test->actions[i];
char *action_name, *action_name_test;
if (data->handler != data_test->handler) if (data->handler != data_test->handler)
return false; return false;
...@@ -4904,7 +4928,17 @@ static bool actions_match(struct hist_trigger_data *hist_data, ...@@ -4904,7 +4928,17 @@ static bool actions_match(struct hist_trigger_data *hist_data,
return false; return false;
} }
if (strcmp(data->action_name, data_test->action_name) != 0) if (data->use_trace_keyword)
action_name = data->synth_event_name;
else
action_name = data->action_name;
if (data_test->use_trace_keyword)
action_name_test = data_test->synth_event_name;
else
action_name_test = data_test->action_name;
if (strcmp(action_name, action_name_test) != 0)
return false; return false;
if (data->handler == HANDLER_ONMATCH) { if (data->handler == HANDLER_ONMATCH) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment