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>
This commit is contained in:
parent
5f893b2639
commit
0daa230296
@ -3500,6 +3500,24 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
See also Documentation/trace/ftrace.txt "trace options"
|
||||
section.
|
||||
|
||||
tp_printk[FTRACE]
|
||||
Have the tracepoints sent to printk as well as the
|
||||
tracing ring buffer. This is useful for early boot up
|
||||
where the system hangs or reboots and does not give the
|
||||
option for reading the tracing buffer or performing a
|
||||
ftrace_dump_on_oops.
|
||||
|
||||
To turn off having tracepoints sent to printk,
|
||||
echo 0 > /proc/sys/kernel/tracepoint_printk
|
||||
Note, echoing 1 into this file without the
|
||||
tracepoint_printk kernel cmdline option has no effect.
|
||||
|
||||
** CAUTION **
|
||||
|
||||
Having tracepoints sent to printk() and activating high
|
||||
frequency tracepoints such as irq or sched, can cause
|
||||
the system to live lock.
|
||||
|
||||
traceoff_on_warning
|
||||
[FTRACE] enable this option to disable tracing when a
|
||||
warning is hit. This turns off "tracing_on". Tracing can
|
||||
|
@ -879,6 +879,7 @@ static inline int test_tsk_trace_graph(struct task_struct *tsk)
|
||||
enum ftrace_dump_mode;
|
||||
|
||||
extern enum ftrace_dump_mode ftrace_dump_on_oops;
|
||||
extern int tracepoint_printk;
|
||||
|
||||
extern void disable_trace_on_warning(void);
|
||||
extern int __disable_trace_on_warning;
|
||||
|
@ -622,6 +622,13 @@ static struct ctl_table kern_table[] = {
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.procname = "tracepoint_printk",
|
||||
.data = &tracepoint_printk,
|
||||
.maxlen = sizeof(tracepoint_printk),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_KEXEC
|
||||
{
|
||||
|
@ -63,6 +63,10 @@ static bool __read_mostly tracing_selftest_running;
|
||||
*/
|
||||
bool __read_mostly tracing_selftest_disabled;
|
||||
|
||||
/* Pipe tracepoints to printk */
|
||||
struct trace_iterator *tracepoint_print_iter;
|
||||
int tracepoint_printk;
|
||||
|
||||
/* For tracers that don't implement custom flags */
|
||||
static struct tracer_opt dummy_tracer_opt[] = {
|
||||
{ }
|
||||
@ -193,6 +197,13 @@ static int __init set_trace_boot_clock(char *str)
|
||||
}
|
||||
__setup("trace_clock=", set_trace_boot_clock);
|
||||
|
||||
static int __init set_tracepoint_printk(char *str)
|
||||
{
|
||||
if ((strcmp(str, "=0") != 0 && strcmp(str, "=off") != 0))
|
||||
tracepoint_printk = 1;
|
||||
return 1;
|
||||
}
|
||||
__setup("tp_printk", set_tracepoint_printk);
|
||||
|
||||
unsigned long long ns2usecs(cycle_t nsec)
|
||||
{
|
||||
@ -6878,6 +6889,12 @@ out:
|
||||
|
||||
void __init trace_init(void)
|
||||
{
|
||||
if (tracepoint_printk) {
|
||||
tracepoint_print_iter =
|
||||
kmalloc(sizeof(*tracepoint_print_iter), GFP_KERNEL);
|
||||
if (WARN_ON(!tracepoint_print_iter))
|
||||
tracepoint_printk = 0;
|
||||
}
|
||||
tracer_alloc_buffers();
|
||||
init_ftrace_syscalls();
|
||||
trace_event_init();
|
||||
|
@ -1313,5 +1313,6 @@ void trace_event_init(void);
|
||||
static inline void __init trace_event_init(void) { }
|
||||
#endif
|
||||
|
||||
extern struct trace_iterator *tracepoint_print_iter;
|
||||
|
||||
#endif /* _LINUX_KERNEL_TRACE_H */
|
||||
|
@ -212,8 +212,40 @@ void *ftrace_event_buffer_reserve(struct ftrace_event_buffer *fbuffer,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ftrace_event_buffer_reserve);
|
||||
|
||||
static DEFINE_SPINLOCK(tracepoint_iter_lock);
|
||||
|
||||
static void output_printk(struct ftrace_event_buffer *fbuffer)
|
||||
{
|
||||
struct ftrace_event_call *event_call;
|
||||
struct trace_event *event;
|
||||
unsigned long flags;
|
||||
struct trace_iterator *iter = tracepoint_print_iter;
|
||||
|
||||
if (!iter)
|
||||
return;
|
||||
|
||||
event_call = fbuffer->ftrace_file->event_call;
|
||||
if (!event_call || !event_call->event.funcs ||
|
||||
!event_call->event.funcs->trace)
|
||||
return;
|
||||
|
||||
event = &fbuffer->ftrace_file->event_call->event;
|
||||
|
||||
spin_lock_irqsave(&tracepoint_iter_lock, flags);
|
||||
trace_seq_init(&iter->seq);
|
||||
iter->ent = fbuffer->entry;
|
||||
event_call->event.funcs->trace(iter, 0, event);
|
||||
trace_seq_putc(&iter->seq, 0);
|
||||
printk("%s", iter->seq.buffer);
|
||||
|
||||
spin_unlock_irqrestore(&tracepoint_iter_lock, flags);
|
||||
}
|
||||
|
||||
void ftrace_event_buffer_commit(struct ftrace_event_buffer *fbuffer)
|
||||
{
|
||||
if (tracepoint_printk)
|
||||
output_printk(fbuffer);
|
||||
|
||||
event_trigger_unlock_commit(fbuffer->ftrace_file, fbuffer->buffer,
|
||||
fbuffer->event, fbuffer->entry,
|
||||
fbuffer->flags, fbuffer->pc);
|
||||
|
Loading…
Reference in New Issue
Block a user