As the merge window is still open, and this code was not as complex

as I thought it might be. I'm pushing this in now.
 
 This will allow Thomas to debug his irq work for 3.20.
 
 This adds two new features:
 
 1) Allow traceopoints to be enabled right after mm_init(). By passing
 in the trace_event= kernel command line parameter, tracepoints can be
 enabled at boot up. For debugging things like the initialization of
 interrupts, it is needed to have tracepoints enabled very early. People
 have asked about this before and this has been on my todo list. As it
 can be helpful for Thomas to debug his upcoming 3.20 IRQ work, I'm
 pushing this now. This way he can add tracepoints into the IRQ set up
 and have users enable them when things go wrong.
 
 2) Have the tracepoints printed via printk() (the console) when they
 are triggered. If the irq code locks up or reboots the box, having the
 tracepoint output go into the kernel ring buffer is useless for
 debugging. But being able to add the tp_printk kernel command line
 option along with the trace_event= option will have these tracepoints
 printed as they occur, and that can be really useful for debugging
 early lock up or reboot problems.
 
 This code is not that intrusive and it passed all my tests. Thomas tried
 them out too and it works for his needs.
 
  Link: http://lkml.kernel.org/r/20141214201609.126831471@goodmis.org
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJUjv3kAAoJEEjnJuOKh9ldLNsIANAe5EmDCBw0WjR72n+G3qOH
 NC8calXfkjqHU0bv8Q3dRv20KH4MHOy6l4+EiV9/ovt71LOF3NEyUJ3HuShf9a8b
 sWcUhYbX3D1hViQe5sOzv9AWhBCFlKQGoNmQnydX9xa8ivRsBaTGJIGktWlHcwBE
 jF1i3fj3l3vRQSS8qZFXp3bzreunlGyPoSHcT6eWQeos+utj4sKwQWTLXTLQeM+6
 oQtFKRx7E5yX04qO1qFczS8qIEC6JH2C2jIRYEKUGepaELlnGkb8O7jQV/RaLF4/
 6P8VhZFG9YLS7fn7vWu0SnAN+Zwz5LzgjXAZt0FhGtIhLc18Oj8ouHH1UORsdQM=
 =Z4Un
 -----END PGP SIGNATURE-----

Merge tag 'trace-3.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull tracing updates from Steven Rostedt:
 "As the merge window is still open, and this code was not as complex as
  I thought it might be.  I'm pushing this in now.

  This will allow Thomas to debug his irq work for 3.20.

  This adds two new features:

  1) Allow traceopoints to be enabled right after mm_init().

     By passing in the trace_event= kernel command line parameter,
     tracepoints can be enabled at boot up.  For debugging things like
     the initialization of interrupts, it is needed to have tracepoints
     enabled very early.  People have asked about this before and this
     has been on my todo list.  As it can be helpful for Thomas to debug
     his upcoming 3.20 IRQ work, I'm pushing this now.  This way he can
     add tracepoints into the IRQ set up and have users enable them when
     things go wrong.

  2) Have the tracepoints printed via printk() (the console) when they
     are triggered.

     If the irq code locks up or reboots the box, having the tracepoint
     output go into the kernel ring buffer is useless for debugging.
     But being able to add the tp_printk kernel command line option
     along with the trace_event= option will have these tracepoints
     printed as they occur, and that can be really useful for debugging
     early lock up or reboot problems.

  This code is not that intrusive and it passed all my tests.  Thomas
  tried them out too and it works for his needs.

   Link: http://lkml.kernel.org/r/20141214201609.126831471@goodmis.org"

* tag 'trace-3.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
  tracing: Add tp_printk cmdline to have tracepoints go to printk()
  tracing: Move enabling tracepoints to just after rcu_init()
This commit is contained in:
Linus Torvalds 2014-12-16 12:53:59 -08:00
commit a7c180aa7e
8 changed files with 116 additions and 8 deletions

View File

@ -3570,6 +3570,24 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
See also Documentation/trace/ftrace.txt "trace options" See also Documentation/trace/ftrace.txt "trace options"
section. 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 traceoff_on_warning
[FTRACE] enable this option to disable tracing when a [FTRACE] enable this option to disable tracing when a
warning is hit. This turns off "tracing_on". Tracing can warning is hit. This turns off "tracing_on". Tracing can

View File

@ -39,6 +39,12 @@
# define FTRACE_FORCE_LIST_FUNC 0 # define FTRACE_FORCE_LIST_FUNC 0
#endif #endif
/* Main tracing buffer and events set up */
#ifdef CONFIG_TRACING
void trace_init(void);
#else
static inline void trace_init(void) { }
#endif
struct module; struct module;
struct ftrace_hash; struct ftrace_hash;
@ -873,6 +879,7 @@ static inline int test_tsk_trace_graph(struct task_struct *tsk)
enum ftrace_dump_mode; enum ftrace_dump_mode;
extern enum ftrace_dump_mode ftrace_dump_on_oops; extern enum ftrace_dump_mode ftrace_dump_on_oops;
extern int tracepoint_printk;
extern void disable_trace_on_warning(void); extern void disable_trace_on_warning(void);
extern int __disable_trace_on_warning; extern int __disable_trace_on_warning;

View File

@ -578,6 +578,10 @@ asmlinkage __visible void __init start_kernel(void)
local_irq_disable(); local_irq_disable();
idr_init_cache(); idr_init_cache();
rcu_init(); rcu_init();
/* trace_printk() and trace points may be used after this */
trace_init();
context_tracking_init(); context_tracking_init();
radix_tree_init(); radix_tree_init();
/* init some links before init_ISA_irqs() */ /* init some links before init_ISA_irqs() */

View File

@ -623,6 +623,13 @@ static struct ctl_table kern_table[] = {
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec, .proc_handler = proc_dointvec,
}, },
{
.procname = "tracepoint_printk",
.data = &tracepoint_printk,
.maxlen = sizeof(tracepoint_printk),
.mode = 0644,
.proc_handler = proc_dointvec,
},
#endif #endif
#ifdef CONFIG_KEXEC #ifdef CONFIG_KEXEC
{ {

View File

@ -63,6 +63,10 @@ static bool __read_mostly tracing_selftest_running;
*/ */
bool __read_mostly tracing_selftest_disabled; 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 */ /* For tracers that don't implement custom flags */
static struct tracer_opt dummy_tracer_opt[] = { 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); __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) unsigned long long ns2usecs(cycle_t nsec)
{ {
@ -6898,6 +6909,19 @@ __init static int tracer_alloc_buffers(void)
return ret; return ret;
} }
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();
}
__init static int clear_boot_tracer(void) __init static int clear_boot_tracer(void)
{ {
/* /*
@ -6917,6 +6941,5 @@ __init static int clear_boot_tracer(void)
return 0; return 0;
} }
early_initcall(tracer_alloc_buffers);
fs_initcall(tracer_init_debugfs); fs_initcall(tracer_init_debugfs);
late_initcall(clear_boot_tracer); late_initcall(clear_boot_tracer);

View File

@ -1301,4 +1301,18 @@ int perf_ftrace_event_register(struct ftrace_event_call *call,
#define perf_ftrace_event_register NULL #define perf_ftrace_event_register NULL
#endif #endif
#ifdef CONFIG_FTRACE_SYSCALLS
void init_ftrace_syscalls(void);
#else
static inline void init_ftrace_syscalls(void) { }
#endif
#ifdef CONFIG_EVENT_TRACING
void trace_event_init(void);
#else
static inline void __init trace_event_init(void) { }
#endif
extern struct trace_iterator *tracepoint_print_iter;
#endif /* _LINUX_KERNEL_TRACE_H */ #endif /* _LINUX_KERNEL_TRACE_H */

View File

@ -212,8 +212,40 @@ void *ftrace_event_buffer_reserve(struct ftrace_event_buffer *fbuffer,
} }
EXPORT_SYMBOL_GPL(ftrace_event_buffer_reserve); 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) 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, event_trigger_unlock_commit(fbuffer->ftrace_file, fbuffer->buffer,
fbuffer->event, fbuffer->entry, fbuffer->event, fbuffer->entry,
fbuffer->flags, fbuffer->pc); fbuffer->flags, fbuffer->pc);
@ -2480,8 +2512,14 @@ static __init int event_trace_init(void)
#endif #endif
return 0; return 0;
} }
early_initcall(event_trace_memsetup);
core_initcall(event_trace_enable); void __init trace_event_init(void)
{
event_trace_memsetup();
init_ftrace_syscalls();
event_trace_enable();
}
fs_initcall(event_trace_init); fs_initcall(event_trace_init);
#ifdef CONFIG_FTRACE_STARTUP_TEST #ifdef CONFIG_FTRACE_STARTUP_TEST

View File

@ -514,7 +514,7 @@ unsigned long __init __weak arch_syscall_addr(int nr)
return (unsigned long)sys_call_table[nr]; return (unsigned long)sys_call_table[nr];
} }
static int __init init_ftrace_syscalls(void) void __init init_ftrace_syscalls(void)
{ {
struct syscall_metadata *meta; struct syscall_metadata *meta;
unsigned long addr; unsigned long addr;
@ -524,7 +524,7 @@ static int __init init_ftrace_syscalls(void)
GFP_KERNEL); GFP_KERNEL);
if (!syscalls_metadata) { if (!syscalls_metadata) {
WARN_ON(1); WARN_ON(1);
return -ENOMEM; return;
} }
for (i = 0; i < NR_syscalls; i++) { for (i = 0; i < NR_syscalls; i++) {
@ -536,10 +536,7 @@ static int __init init_ftrace_syscalls(void)
meta->syscall_nr = i; meta->syscall_nr = i;
syscalls_metadata[i] = meta; syscalls_metadata[i] = meta;
} }
return 0;
} }
early_initcall(init_ftrace_syscalls);
#ifdef CONFIG_PERF_EVENTS #ifdef CONFIG_PERF_EVENTS