aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/trace/trace_events.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index c3d1bfe4544a..61cb7275de76 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -2887,6 +2887,91 @@ static struct ftrace_func_command trigger_traceoff_cmd = {
.get_probe_ops = event_trigger_onoff_get_probe_ops,
};
+static void
+event_trigger_snapshot_probe(unsigned long unused_ip,
+ unsigned long unused_parent_ip, void **_data)
+{
+ struct event_probe_data **pdata = (struct event_probe_data **)_data;
+ struct event_probe_data *data = *pdata;
+
+ if (!data)
+ return;
+
+ tracing_snapshot();
+}
+
+static void
+event_trigger_snapshot_count_probe(unsigned long unused_ip,
+ unsigned long unused_parent_ip,
+ void **_data)
+{
+ struct event_probe_data **pdata = (struct event_probe_data **)_data;
+ struct event_probe_data *data = *pdata;
+
+ if (!data)
+ return;
+
+ if (!data->count)
+ return;
+
+ if (data->count != -1)
+ (data->count)--;
+
+ event_trigger_snapshot_probe(0, 0, _data);
+}
+
+static int register_event_trigger_snapshot_probe(char *glob,
+ struct ftrace_probe_ops *ops,
+ void *data,
+ void *command_data)
+{
+ int ret = register_event_trigger_probe(glob, ops, data, command_data);
+
+ if (ret > 0)
+ ftrace_alloc_snapshot();
+
+ return ret;
+}
+
+static int
+event_trigger_snapshot_print(struct seq_file *m, unsigned long unused_ip,
+ struct ftrace_probe_ops *ops, void *_data)
+{
+ struct event_probe_data *data = _data;
+
+ return trace_probe_print("snapshot", m, (void *)data->count,
+ data->filter_str);
+}
+
+static struct ftrace_probe_ops event_trigger_snapshot_probe_ops = {
+ .func = event_trigger_snapshot_probe,
+ .print = event_trigger_snapshot_print,
+ .init = event_trigger_probe_init,
+ .free = event_trigger_probe_free,
+};
+
+static struct ftrace_probe_ops event_trigger_snapshot_count_probe_ops = {
+ .func = event_trigger_snapshot_count_probe,
+ .print = event_trigger_snapshot_print,
+ .init = event_trigger_probe_init,
+ .free = event_trigger_probe_free,
+};
+
+static struct ftrace_probe_ops *
+event_trigger_snapshot_get_probe_ops(char *cmd, char *param)
+{
+ return param ? &event_trigger_snapshot_count_probe_ops :
+ &event_trigger_snapshot_probe_ops;
+}
+
+static struct ftrace_func_command event_trigger_snapshot_cmd = {
+ .name = "snapshot",
+ .func = event_trigger_probe_callback,
+ .reg = register_event_trigger_snapshot_probe,
+ .unreg = unregister_event_trigger_probe,
+ .get_probe_ops = event_trigger_snapshot_get_probe_ops,
+};
+
static __init void unregister_trigger_traceon_traceoff_cmds(void)
{
unregister_ftrace_command(&trigger_traceon_cmd,
@@ -2961,6 +3046,17 @@ static __init int register_trigger_cmds(void)
&trigger_cmd_mutex);
}
+ ret = register_ftrace_command(&event_trigger_snapshot_cmd,
+ &trigger_commands,
+ &trigger_cmd_mutex);
+ if (WARN_ON(ret < 0)) {
+ unregister_trigger_enable_disable_cmds();
+ unregister_ftrace_command(&event_trigger_stacktrace_cmd,
+ &trigger_commands,
+ &trigger_cmd_mutex);
+ unregister_trigger_traceon_traceoff_cmds();
+ }
+
return ret;
}