diff options
-rw-r--r-- | kernel/trace/trace_events.c | 96 |
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; } |