diff options
-rw-r--r-- | kernel/trace/trace_events_trigger.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c index 4b47cfa3fd93..d8e2b27bca6b 100644 --- a/kernel/trace/trace_events_trigger.c +++ b/kernel/trace/trace_events_trigger.c @@ -1216,6 +1216,87 @@ static struct event_command trigger_traceoff_cmd = { .set_filter = set_trigger_filter, }; +static void +snapshot_trigger(void **_data) +{ + struct event_trigger_data **p = (struct event_trigger_data **)_data; + struct event_trigger_data *data = *p; + + if (!data) + return; + + tracing_snapshot(); +} + +static void +snapshot_count_trigger(void **_data) +{ + struct event_trigger_data **p = (struct event_trigger_data **)_data; + struct event_trigger_data *data = *p; + + if (!data) + return; + + if (!data->count) + return; + + if (data->count != -1) + (data->count)--; + + snapshot_trigger(_data); +} + +static int +register_snapshot_trigger(char *glob, struct event_trigger_ops *ops, + void *data, void *cmd_data) +{ + int ret = register_trigger(glob, ops, data, cmd_data); + + if (ret > 0) + ftrace_alloc_snapshot(); + + return ret; +} + +static int +snapshot_trigger_print(struct seq_file *m, struct event_trigger_ops *ops, + void *_data) +{ + struct event_trigger_data *data = _data; + + return event_trigger_print("snapshot", m, (void *)data->count, + data->filter_str); +} + +static struct event_trigger_ops snapshot_trigger_ops = { + .func = snapshot_trigger, + .print = snapshot_trigger_print, + .init = event_trigger_init, + .free = event_trigger_free, +}; + +static struct event_trigger_ops snapshot_count_trigger_ops = { + .func = snapshot_count_trigger, + .print = snapshot_trigger_print, + .init = event_trigger_init, + .free = event_trigger_free, +}; + +static struct event_trigger_ops * +snapshot_get_trigger_ops(char *cmd, char *param) +{ + return param ? &snapshot_count_trigger_ops : &snapshot_trigger_ops; +} + +static struct event_command trigger_snapshot_cmd = { + .name = "snapshot", + .func = event_trigger_callback, + .reg = register_snapshot_trigger, + .unreg = unregister_trigger, + .get_trigger_ops = snapshot_get_trigger_ops, + .set_filter = set_trigger_filter, +}; + static __init void unregister_trigger_traceon_traceoff_cmds(void) { unregister_event_command(&trigger_traceon_cmd, @@ -1290,6 +1371,18 @@ __init int register_trigger_cmds(void) unregister_event_command(&trigger_stacktrace_cmd, &trigger_commands, &trigger_cmd_mutex); + return ret; + } + + ret = register_event_command(&trigger_snapshot_cmd, + &trigger_commands, + &trigger_cmd_mutex); + if (WARN_ON(ret < 0)) { + unregister_trigger_enable_disable_cmds(); + unregister_event_command(&trigger_stacktrace_cmd, + &trigger_commands, + &trigger_cmd_mutex); + unregister_trigger_traceon_traceoff_cmds(); } return ret; |