Commit e86ae9ba authored by Tom Zanussi's avatar Tom Zanussi Committed by Steven Rostedt

tracing: Add hist trigger support for clearing a trace

Allow users to append 'clear' to an existing trigger in order to have
the hash table cleared.

This expands the hist trigger syntax from this:
    # echo hist:keys=xxx:vals=yyy:sort=zzz.descending:pause/cont \
           [ if filter] >> event/trigger

to this:

    # echo hist:keys=xxx:vals=yyy:sort=zzz.descending:pause/cont/clear \
          [ if filter] >> event/trigger

Link: http://lkml.kernel.org/r/ae15dd0d9b2f7af07a37c1ff682063e2dbcdf160.1457029949.git.tom.zanussi@linux.intel.comSigned-off-by: default avatarTom Zanussi <tom.zanussi@linux.intel.com>
Tested-by: default avatarMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Reviewed-by: default avatarNamhyung Kim <namhyung@kernel.org>
Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent 83e99914
...@@ -3837,7 +3837,7 @@ static const char readme_msg[] = ...@@ -3837,7 +3837,7 @@ static const char readme_msg[] =
"\t [:values=<field1[,field2,...]>]\n" "\t [:values=<field1[,field2,...]>]\n"
"\t [:sort=<field1[,field2,...]>]\n" "\t [:sort=<field1[,field2,...]>]\n"
"\t [:size=#entries]\n" "\t [:size=#entries]\n"
"\t [:pause][:continue]\n" "\t [:pause][:continue][:clear]\n"
"\t [if <filter>]\n\n" "\t [if <filter>]\n\n"
"\t When a matching event is hit, an entry is added to a hash\n" "\t When a matching event is hit, an entry is added to a hash\n"
"\t table using the key(s) and value(s) named, and the value of a\n" "\t table using the key(s) and value(s) named, and the value of a\n"
...@@ -3857,6 +3857,9 @@ static const char readme_msg[] = ...@@ -3857,6 +3857,9 @@ static const char readme_msg[] =
"\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"
"\t restart a paused hist trigger.\n\n" "\t restart a paused hist trigger.\n\n"
"\t The 'clear' parameter will clear the contents of a running\n"
"\t hist trigger and leave its current paused/active state\n"
"\t unchanged.\n\n"
#endif #endif
; ;
......
...@@ -88,6 +88,7 @@ struct hist_trigger_attrs { ...@@ -88,6 +88,7 @@ struct hist_trigger_attrs {
char *sort_key_str; char *sort_key_str;
bool pause; bool pause;
bool cont; bool cont;
bool clear;
unsigned int map_bits; unsigned int map_bits;
}; };
...@@ -200,6 +201,8 @@ static struct hist_trigger_attrs *parse_hist_trigger_attrs(char *trigger_str) ...@@ -200,6 +201,8 @@ static struct hist_trigger_attrs *parse_hist_trigger_attrs(char *trigger_str)
else if ((strcmp(str, "cont") == 0) || else if ((strcmp(str, "cont") == 0) ||
(strcmp(str, "continue") == 0)) (strcmp(str, "continue") == 0))
attrs->cont = true; attrs->cont = true;
else if (strcmp(str, "clear") == 0)
attrs->clear = true;
else if (strncmp(str, "size=", strlen("size=")) == 0) { else if (strncmp(str, "size=", strlen("size=")) == 0) {
int map_bits = parse_map_size(str); int map_bits = parse_map_size(str);
...@@ -916,6 +919,21 @@ static struct event_trigger_ops *event_hist_get_trigger_ops(char *cmd, ...@@ -916,6 +919,21 @@ static struct event_trigger_ops *event_hist_get_trigger_ops(char *cmd,
return &event_hist_trigger_ops; return &event_hist_trigger_ops;
} }
static void hist_clear(struct event_trigger_data *data)
{
struct hist_trigger_data *hist_data = data->private_data;
bool paused;
paused = data->paused;
data->paused = true;
synchronize_sched();
tracing_map_clear(hist_data->map);
data->paused = paused;
}
static int hist_register_trigger(char *glob, struct event_trigger_ops *ops, static int hist_register_trigger(char *glob, struct event_trigger_ops *ops,
struct event_trigger_data *data, struct event_trigger_data *data,
struct trace_event_file *file) struct trace_event_file *file)
...@@ -930,13 +948,15 @@ static int hist_register_trigger(char *glob, struct event_trigger_ops *ops, ...@@ -930,13 +948,15 @@ static int hist_register_trigger(char *glob, struct event_trigger_ops *ops,
test->paused = true; test->paused = true;
else if (hist_data->attrs->cont) else if (hist_data->attrs->cont)
test->paused = false; test->paused = false;
else if (hist_data->attrs->clear)
hist_clear(test);
else else
ret = -EEXIST; ret = -EEXIST;
goto out; goto out;
} }
} }
if (hist_data->attrs->cont) { if (hist_data->attrs->cont || hist_data->attrs->clear) {
ret = -ENOENT; ret = -ENOENT;
goto out; goto out;
} }
...@@ -1035,7 +1055,7 @@ static int event_hist_trigger_func(struct event_command *cmd_ops, ...@@ -1035,7 +1055,7 @@ static int event_hist_trigger_func(struct event_command *cmd_ops,
* triggers registered a failure too. * triggers registered a failure too.
*/ */
if (!ret) { if (!ret) {
if (!(attrs->pause || attrs->cont)) if (!(attrs->pause || attrs->cont || attrs->clear))
ret = -ENOENT; ret = -ENOENT;
goto out_free; goto out_free;
} else if (ret < 0) } else if (ret < 0)
......
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