aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt18
-rw-r--r--include/linux/ftrace.h1
-rw-r--r--kernel/sysctl.c7
-rw-r--r--kernel/trace/trace.c17
-rw-r--r--kernel/trace/trace.h1
-rw-r--r--kernel/trace/trace_events.c32
6 files changed, 76 insertions, 0 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 1d09eb37c562..ae41f1181e9a 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -3500,6 +3500,24 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
3500 See also Documentation/trace/ftrace.txt "trace options" 3500 See also Documentation/trace/ftrace.txt "trace options"
3501 section. 3501 section.
3502 3502
3503 tp_printk[FTRACE]
3504 Have the tracepoints sent to printk as well as the
3505 tracing ring buffer. This is useful for early boot up
3506 where the system hangs or reboots and does not give the
3507 option for reading the tracing buffer or performing a
3508 ftrace_dump_on_oops.
3509
3510 To turn off having tracepoints sent to printk,
3511 echo 0 > /proc/sys/kernel/tracepoint_printk
3512 Note, echoing 1 into this file without the
3513 tracepoint_printk kernel cmdline option has no effect.
3514
3515 ** CAUTION **
3516
3517 Having tracepoints sent to printk() and activating high
3518 frequency tracepoints such as irq or sched, can cause
3519 the system to live lock.
3520
3503 traceoff_on_warning 3521 traceoff_on_warning
3504 [FTRACE] enable this option to disable tracing when a 3522 [FTRACE] enable this option to disable tracing when a
3505 warning is hit. This turns off "tracing_on". Tracing can 3523 warning is hit. This turns off "tracing_on". Tracing can
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index f4bc14b7d444..1da602982cf9 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -879,6 +879,7 @@ static inline int test_tsk_trace_graph(struct task_struct *tsk)
879enum ftrace_dump_mode; 879enum ftrace_dump_mode;
880 880
881extern enum ftrace_dump_mode ftrace_dump_on_oops; 881extern enum ftrace_dump_mode ftrace_dump_on_oops;
882extern int tracepoint_printk;
882 883
883extern void disable_trace_on_warning(void); 884extern void disable_trace_on_warning(void);
884extern int __disable_trace_on_warning; 885extern int __disable_trace_on_warning;
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 */
64bool __read_mostly tracing_selftest_disabled; 64bool __read_mostly tracing_selftest_disabled;
65 65
66/* Pipe tracepoints to printk */
67struct trace_iterator *tracepoint_print_iter;
68int tracepoint_printk;
69
66/* For tracers that don't implement custom flags */ 70/* For tracers that don't implement custom flags */
67static struct tracer_opt dummy_tracer_opt[] = { 71static 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
200static 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
197unsigned long long ns2usecs(cycle_t nsec) 208unsigned long long ns2usecs(cycle_t nsec)
198{ 209{
@@ -6878,6 +6889,12 @@ out:
6878 6889
6879void __init trace_init(void) 6890void __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);
1313static inline void __init trace_event_init(void) { } 1313static inline void __init trace_event_init(void) { }
1314#endif 1314#endif
1315 1315
1316extern 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}
213EXPORT_SYMBOL_GPL(ftrace_event_buffer_reserve); 213EXPORT_SYMBOL_GPL(ftrace_event_buffer_reserve);
214 214
215static DEFINE_SPINLOCK(tracepoint_iter_lock);
216
217static 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
215void ftrace_event_buffer_commit(struct ftrace_event_buffer *fbuffer) 244void 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);