diff options
author | Tom Zanussi <tom.zanussi@linux.intel.com> | 2013-10-24 09:59:27 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2013-12-21 22:02:15 -0500 |
commit | f21ecbb35f865a508073c0e73854da469a07f278 (patch) | |
tree | 75f014738b5bbe844abdf087b6897b14c6c29bd9 /kernel/trace | |
parent | 93e31ffbf417a84fbae518fb46b3ea3f0d8fa6e1 (diff) |
tracing: Add 'stacktrace' event trigger command
Add 'stacktrace' event_command. stacktrace event triggers are added
by the user via this command in a similar way and using practically
the same syntax as the analogous 'stacktrace' ftrace function command,
but instead of writing to the set_ftrace_filter file, the stacktrace
event trigger is written to the per-event 'trigger' files:
echo 'stacktrace' > .../tracing/events/somesys/someevent/trigger
The above command will turn on stacktraces for someevent i.e. whenever
someevent is hit, a stacktrace will be logged.
This also adds a 'count' version that limits the number of times the
command will be invoked:
echo 'stacktrace:N' > .../tracing/events/somesys/someevent/trigger
Where N is the number of times the command will be invoked.
The above command will log N stacktraces for someevent i.e. whenever
someevent is hit N times, a stacktrace will be logged.
Link: http://lkml.kernel.org/r/0c30c008a0828c660aa0e1bbd3255cf179ed5c30.1382622043.git.tom.zanussi@linux.intel.com
Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/trace_events_trigger.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c index d775c3da180f..a3bd1da90c56 100644 --- a/kernel/trace/trace_events_trigger.c +++ b/kernel/trace/trace_events_trigger.c | |||
@@ -780,6 +780,84 @@ static __init int register_trigger_snapshot_cmd(void) | |||
780 | static __init int register_trigger_snapshot_cmd(void) { return 0; } | 780 | static __init int register_trigger_snapshot_cmd(void) { return 0; } |
781 | #endif /* CONFIG_TRACER_SNAPSHOT */ | 781 | #endif /* CONFIG_TRACER_SNAPSHOT */ |
782 | 782 | ||
783 | #ifdef CONFIG_STACKTRACE | ||
784 | /* | ||
785 | * Skip 3: | ||
786 | * stacktrace_trigger() | ||
787 | * event_triggers_post_call() | ||
788 | * ftrace_raw_event_xxx() | ||
789 | */ | ||
790 | #define STACK_SKIP 3 | ||
791 | |||
792 | static void | ||
793 | stacktrace_trigger(struct event_trigger_data *data) | ||
794 | { | ||
795 | trace_dump_stack(STACK_SKIP); | ||
796 | } | ||
797 | |||
798 | static void | ||
799 | stacktrace_count_trigger(struct event_trigger_data *data) | ||
800 | { | ||
801 | if (!data->count) | ||
802 | return; | ||
803 | |||
804 | if (data->count != -1) | ||
805 | (data->count)--; | ||
806 | |||
807 | stacktrace_trigger(data); | ||
808 | } | ||
809 | |||
810 | static int | ||
811 | stacktrace_trigger_print(struct seq_file *m, struct event_trigger_ops *ops, | ||
812 | struct event_trigger_data *data) | ||
813 | { | ||
814 | return event_trigger_print("stacktrace", m, (void *)data->count, | ||
815 | data->filter_str); | ||
816 | } | ||
817 | |||
818 | static struct event_trigger_ops stacktrace_trigger_ops = { | ||
819 | .func = stacktrace_trigger, | ||
820 | .print = stacktrace_trigger_print, | ||
821 | .init = event_trigger_init, | ||
822 | .free = event_trigger_free, | ||
823 | }; | ||
824 | |||
825 | static struct event_trigger_ops stacktrace_count_trigger_ops = { | ||
826 | .func = stacktrace_count_trigger, | ||
827 | .print = stacktrace_trigger_print, | ||
828 | .init = event_trigger_init, | ||
829 | .free = event_trigger_free, | ||
830 | }; | ||
831 | |||
832 | static struct event_trigger_ops * | ||
833 | stacktrace_get_trigger_ops(char *cmd, char *param) | ||
834 | { | ||
835 | return param ? &stacktrace_count_trigger_ops : &stacktrace_trigger_ops; | ||
836 | } | ||
837 | |||
838 | static struct event_command trigger_stacktrace_cmd = { | ||
839 | .name = "stacktrace", | ||
840 | .trigger_type = ETT_STACKTRACE, | ||
841 | .post_trigger = true, | ||
842 | .func = event_trigger_callback, | ||
843 | .reg = register_trigger, | ||
844 | .unreg = unregister_trigger, | ||
845 | .get_trigger_ops = stacktrace_get_trigger_ops, | ||
846 | }; | ||
847 | |||
848 | static __init int register_trigger_stacktrace_cmd(void) | ||
849 | { | ||
850 | int ret; | ||
851 | |||
852 | ret = register_event_command(&trigger_stacktrace_cmd); | ||
853 | WARN_ON(ret < 0); | ||
854 | |||
855 | return ret; | ||
856 | } | ||
857 | #else | ||
858 | static __init int register_trigger_stacktrace_cmd(void) { return 0; } | ||
859 | #endif /* CONFIG_STACKTRACE */ | ||
860 | |||
783 | static __init void unregister_trigger_traceon_traceoff_cmds(void) | 861 | static __init void unregister_trigger_traceon_traceoff_cmds(void) |
784 | { | 862 | { |
785 | unregister_event_command(&trigger_traceon_cmd); | 863 | unregister_event_command(&trigger_traceon_cmd); |
@@ -804,6 +882,7 @@ __init int register_trigger_cmds(void) | |||
804 | { | 882 | { |
805 | register_trigger_traceon_traceoff_cmds(); | 883 | register_trigger_traceon_traceoff_cmds(); |
806 | register_trigger_snapshot_cmd(); | 884 | register_trigger_snapshot_cmd(); |
885 | register_trigger_stacktrace_cmd(); | ||
807 | 886 | ||
808 | return 0; | 887 | return 0; |
809 | } | 888 | } |