diff options
author | Steven Rostedt (Red Hat) <rostedt@goodmis.org> | 2014-12-12 22:27:10 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2014-12-15 10:17:38 -0500 |
commit | 0daa2302968c13b657118d6ac92471f8fd2f3f28 (patch) | |
tree | 8bea68f7bbeab6521c11c01f55b5660082eeedf6 /kernel | |
parent | 5f893b2639b21ffe6834b1aebba392c37d2b83f9 (diff) |
tracing: Add tp_printk cmdline to have tracepoints go to printk()
Add the kernel command line tp_printk option that will have tracepoints
that are active sent to printk() as well as to the trace buffer.
Passing "tp_printk" will activate this. To turn it off, the sysctl
/proc/sys/kernel/tracepoint_printk can have '0' echoed into it. Note,
this only works if the cmdline option is used. Echoing 1 into the sysctl
file without the cmdline option will have no affect.
Note, this is a dangerous option. Having high frequency tracepoints send
their data to printk() can possibly cause a live lock. This is another
reason why this is only active if the command line option is used.
Link: http://lkml.kernel.org/r/alpine.DEB.2.11.1412121539300.16494@nanos
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/sysctl.c | 7 | ||||
-rw-r--r-- | kernel/trace/trace.c | 17 | ||||
-rw-r--r-- | kernel/trace/trace.h | 1 | ||||
-rw-r--r-- | kernel/trace/trace_events.c | 32 |
4 files changed, 57 insertions, 0 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 4aada6d9fe74..bb50c2187194 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -622,6 +622,13 @@ static struct ctl_table kern_table[] = { | |||
622 | .mode = 0644, | 622 | .mode = 0644, |
623 | .proc_handler = proc_dointvec, | 623 | .proc_handler = proc_dointvec, |
624 | }, | 624 | }, |
625 | { | ||
626 | .procname = "tracepoint_printk", | ||
627 | .data = &tracepoint_printk, | ||
628 | .maxlen = sizeof(tracepoint_printk), | ||
629 | .mode = 0644, | ||
630 | .proc_handler = proc_dointvec, | ||
631 | }, | ||
625 | #endif | 632 | #endif |
626 | #ifdef CONFIG_KEXEC | 633 | #ifdef CONFIG_KEXEC |
627 | { | 634 | { |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index ec3ca694665f..e890d2d4ec89 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -63,6 +63,10 @@ static bool __read_mostly tracing_selftest_running; | |||
63 | */ | 63 | */ |
64 | bool __read_mostly tracing_selftest_disabled; | 64 | bool __read_mostly tracing_selftest_disabled; |
65 | 65 | ||
66 | /* Pipe tracepoints to printk */ | ||
67 | struct trace_iterator *tracepoint_print_iter; | ||
68 | int tracepoint_printk; | ||
69 | |||
66 | /* For tracers that don't implement custom flags */ | 70 | /* For tracers that don't implement custom flags */ |
67 | static struct tracer_opt dummy_tracer_opt[] = { | 71 | static struct tracer_opt dummy_tracer_opt[] = { |
68 | { } | 72 | { } |
@@ -193,6 +197,13 @@ static int __init set_trace_boot_clock(char *str) | |||
193 | } | 197 | } |
194 | __setup("trace_clock=", set_trace_boot_clock); | 198 | __setup("trace_clock=", set_trace_boot_clock); |
195 | 199 | ||
200 | static int __init set_tracepoint_printk(char *str) | ||
201 | { | ||
202 | if ((strcmp(str, "=0") != 0 && strcmp(str, "=off") != 0)) | ||
203 | tracepoint_printk = 1; | ||
204 | return 1; | ||
205 | } | ||
206 | __setup("tp_printk", set_tracepoint_printk); | ||
196 | 207 | ||
197 | unsigned long long ns2usecs(cycle_t nsec) | 208 | unsigned long long ns2usecs(cycle_t nsec) |
198 | { | 209 | { |
@@ -6878,6 +6889,12 @@ out: | |||
6878 | 6889 | ||
6879 | void __init trace_init(void) | 6890 | void __init trace_init(void) |
6880 | { | 6891 | { |
6892 | if (tracepoint_printk) { | ||
6893 | tracepoint_print_iter = | ||
6894 | kmalloc(sizeof(*tracepoint_print_iter), GFP_KERNEL); | ||
6895 | if (WARN_ON(!tracepoint_print_iter)) | ||
6896 | tracepoint_printk = 0; | ||
6897 | } | ||
6881 | tracer_alloc_buffers(); | 6898 | tracer_alloc_buffers(); |
6882 | init_ftrace_syscalls(); | 6899 | init_ftrace_syscalls(); |
6883 | trace_event_init(); | 6900 | trace_event_init(); |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index c138c149d6ef..8de48bac1ce2 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -1313,5 +1313,6 @@ void trace_event_init(void); | |||
1313 | static inline void __init trace_event_init(void) { } | 1313 | static inline void __init trace_event_init(void) { } |
1314 | #endif | 1314 | #endif |
1315 | 1315 | ||
1316 | extern struct trace_iterator *tracepoint_print_iter; | ||
1316 | 1317 | ||
1317 | #endif /* _LINUX_KERNEL_TRACE_H */ | 1318 | #endif /* _LINUX_KERNEL_TRACE_H */ |
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index fd9deb0e03f0..9f7175a3df71 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -212,8 +212,40 @@ void *ftrace_event_buffer_reserve(struct ftrace_event_buffer *fbuffer, | |||
212 | } | 212 | } |
213 | EXPORT_SYMBOL_GPL(ftrace_event_buffer_reserve); | 213 | EXPORT_SYMBOL_GPL(ftrace_event_buffer_reserve); |
214 | 214 | ||
215 | static DEFINE_SPINLOCK(tracepoint_iter_lock); | ||
216 | |||
217 | static void output_printk(struct ftrace_event_buffer *fbuffer) | ||
218 | { | ||
219 | struct ftrace_event_call *event_call; | ||
220 | struct trace_event *event; | ||
221 | unsigned long flags; | ||
222 | struct trace_iterator *iter = tracepoint_print_iter; | ||
223 | |||
224 | if (!iter) | ||
225 | return; | ||
226 | |||
227 | event_call = fbuffer->ftrace_file->event_call; | ||
228 | if (!event_call || !event_call->event.funcs || | ||
229 | !event_call->event.funcs->trace) | ||
230 | return; | ||
231 | |||
232 | event = &fbuffer->ftrace_file->event_call->event; | ||
233 | |||
234 | spin_lock_irqsave(&tracepoint_iter_lock, flags); | ||
235 | trace_seq_init(&iter->seq); | ||
236 | iter->ent = fbuffer->entry; | ||
237 | event_call->event.funcs->trace(iter, 0, event); | ||
238 | trace_seq_putc(&iter->seq, 0); | ||
239 | printk("%s", iter->seq.buffer); | ||
240 | |||
241 | spin_unlock_irqrestore(&tracepoint_iter_lock, flags); | ||
242 | } | ||
243 | |||
215 | void ftrace_event_buffer_commit(struct ftrace_event_buffer *fbuffer) | 244 | void ftrace_event_buffer_commit(struct ftrace_event_buffer *fbuffer) |
216 | { | 245 | { |
246 | if (tracepoint_printk) | ||
247 | output_printk(fbuffer); | ||
248 | |||
217 | event_trigger_unlock_commit(fbuffer->ftrace_file, fbuffer->buffer, | 249 | event_trigger_unlock_commit(fbuffer->ftrace_file, fbuffer->buffer, |
218 | fbuffer->event, fbuffer->entry, | 250 | fbuffer->event, fbuffer->entry, |
219 | fbuffer->flags, fbuffer->pc); | 251 | fbuffer->flags, fbuffer->pc); |