aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2010-04-18 13:08:41 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2010-04-21 17:11:42 -0400
commitcecbca96da387428e220e307a9c945e37e2f4d9e (patch)
tree2edefda983658c19a8f2b38ff951a3046597a4f7
parentb15c7b1cee119999e9eafcd602d24a595e77adac (diff)
tracing: Dump either the oops's cpu source or all cpus buffers
The ftrace_dump_on_oops kernel parameter, sysctl and sysrq let one dump every cpu buffers when an oops or panic happens. It's nice when you have few cpus but it may take ages if have many, plus you miss the real origin of the problem in all the cpu traces. Sometimes, all you need is to dump the cpu buffer that triggered the opps, most of the time it is our main interest. This patch modifies ftrace_dump_on_oops to handle this choice. The ftrace_dump_on_oops kernel parameter, when it comes alone, has the same behaviour than before. But ftrace_dump_on_oops=orig_cpu will only dump the buffer of the cpu that oops'ed. Similarly, sysctl kernel.ftrace_dump_on_oops=1 and echo 1 > /proc/sys/kernel/ftrace_dump_on_oops keep their previous behaviour. But setting 2 jumps into cpu origin dump mode. v2: Fix double setup v3: Fix spelling issues reported by Randy Dunlap v4: Also update __ftrace_dump in the selftests Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Acked-by: David S. Miller <davem@davemloft.net> Acked-by: Steven Rostedt <rostedt@goodmis.org> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: Lai Jiangshan <laijs@cn.fujitsu.com>
-rw-r--r--Documentation/kernel-parameters.txt6
-rw-r--r--Documentation/trace/ftrace.txt6
-rw-r--r--drivers/char/sysrq.c2
-rw-r--r--include/linux/ftrace.h4
-rw-r--r--include/linux/kernel.h11
-rw-r--r--kernel/trace/trace.c51
-rw-r--r--kernel/trace/trace_selftest.c5
7 files changed, 64 insertions, 21 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index e4cbca58536c..ab67b33300fb 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -789,8 +789,12 @@ and is between 256 and 4096 characters. It is defined in the file
789 as early as possible in order to facilitate early 789 as early as possible in order to facilitate early
790 boot debugging. 790 boot debugging.
791 791
792 ftrace_dump_on_oops 792 ftrace_dump_on_oops[=orig_cpu]
793 [FTRACE] will dump the trace buffers on oops. 793 [FTRACE] will dump the trace buffers on oops.
794 If no parameter is passed, ftrace will dump
795 buffers of all CPUs, but if you pass orig_cpu, it will
796 dump only the buffer of the CPU that triggered the
797 oops.
794 798
795 ftrace_filter=[function-list] 799 ftrace_filter=[function-list]
796 [FTRACE] Limit the functions traced by the function 800 [FTRACE] Limit the functions traced by the function
diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt
index 03485bfbd797..52011815c905 100644
--- a/Documentation/trace/ftrace.txt
+++ b/Documentation/trace/ftrace.txt
@@ -1337,12 +1337,14 @@ ftrace_dump_on_oops must be set. To set ftrace_dump_on_oops, one
1337can either use the sysctl function or set it via the proc system 1337can either use the sysctl function or set it via the proc system
1338interface. 1338interface.
1339 1339
1340 sysctl kernel.ftrace_dump_on_oops=1 1340 sysctl kernel.ftrace_dump_on_oops=n
1341 1341
1342or 1342or
1343 1343
1344 echo 1 > /proc/sys/kernel/ftrace_dump_on_oops 1344 echo n > /proc/sys/kernel/ftrace_dump_on_oops
1345 1345
1346If n = 1, ftrace will dump buffers of all CPUs, if n = 2 ftrace will
1347only dump the buffer of the CPU that triggered the oops.
1346 1348
1347Here's an example of such a dump after a null pointer 1349Here's an example of such a dump after a null pointer
1348dereference in a kernel module: 1350dereference in a kernel module:
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 59de2525d303..d4e8b213a462 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -289,7 +289,7 @@ static struct sysrq_key_op sysrq_showstate_blocked_op = {
289 289
290static void sysrq_ftrace_dump(int key, struct tty_struct *tty) 290static void sysrq_ftrace_dump(int key, struct tty_struct *tty)
291{ 291{
292 ftrace_dump(); 292 ftrace_dump(DUMP_ALL);
293} 293}
294static struct sysrq_key_op sysrq_ftrace_dump_op = { 294static struct sysrq_key_op sysrq_ftrace_dump_op = {
295 .handler = sysrq_ftrace_dump, 295 .handler = sysrq_ftrace_dump,
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 01e6adea07ec..ea5b1aae0e8b 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -492,7 +492,9 @@ static inline int test_tsk_trace_graph(struct task_struct *tsk)
492 return tsk->trace & TSK_TRACE_FL_GRAPH; 492 return tsk->trace & TSK_TRACE_FL_GRAPH;
493} 493}
494 494
495extern int ftrace_dump_on_oops; 495enum ftrace_dump_mode;
496
497extern enum ftrace_dump_mode ftrace_dump_on_oops;
496 498
497#ifdef CONFIG_PREEMPT 499#ifdef CONFIG_PREEMPT
498#define INIT_TRACE_RECURSION .trace_recursion = 0, 500#define INIT_TRACE_RECURSION .trace_recursion = 0,
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 9365227dbaf6..9fb1c1299032 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -490,6 +490,13 @@ static inline void tracing_off(void) { }
490static inline void tracing_off_permanent(void) { } 490static inline void tracing_off_permanent(void) { }
491static inline int tracing_is_on(void) { return 0; } 491static inline int tracing_is_on(void) { return 0; }
492#endif 492#endif
493
494enum ftrace_dump_mode {
495 DUMP_NONE,
496 DUMP_ALL,
497 DUMP_ORIG,
498};
499
493#ifdef CONFIG_TRACING 500#ifdef CONFIG_TRACING
494extern void tracing_start(void); 501extern void tracing_start(void);
495extern void tracing_stop(void); 502extern void tracing_stop(void);
@@ -571,7 +578,7 @@ __ftrace_vbprintk(unsigned long ip, const char *fmt, va_list ap);
571extern int 578extern int
572__ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap); 579__ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap);
573 580
574extern void ftrace_dump(void); 581extern void ftrace_dump(enum ftrace_dump_mode oops_dump_mode);
575#else 582#else
576static inline void 583static inline void
577ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3) { } 584ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3) { }
@@ -592,7 +599,7 @@ ftrace_vprintk(const char *fmt, va_list ap)
592{ 599{
593 return 0; 600 return 0;
594} 601}
595static inline void ftrace_dump(void) { } 602static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
596#endif /* CONFIG_TRACING */ 603#endif /* CONFIG_TRACING */
597 604
598/* 605/*
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index bed83cab6da2..7b516c7ef9a0 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -117,9 +117,12 @@ static cpumask_var_t __read_mostly tracing_buffer_mask;
117 * 117 *
118 * It is default off, but you can enable it with either specifying 118 * It is default off, but you can enable it with either specifying
119 * "ftrace_dump_on_oops" in the kernel command line, or setting 119 * "ftrace_dump_on_oops" in the kernel command line, or setting
120 * /proc/sys/kernel/ftrace_dump_on_oops to true. 120 * /proc/sys/kernel/ftrace_dump_on_oops
121 * Set 1 if you want to dump buffers of all CPUs
122 * Set 2 if you want to dump the buffer of the CPU that triggered oops
121 */ 123 */
122int ftrace_dump_on_oops; 124
125enum ftrace_dump_mode ftrace_dump_on_oops;
123 126
124static int tracing_set_tracer(const char *buf); 127static int tracing_set_tracer(const char *buf);
125 128
@@ -139,8 +142,17 @@ __setup("ftrace=", set_cmdline_ftrace);
139 142
140static int __init set_ftrace_dump_on_oops(char *str) 143static int __init set_ftrace_dump_on_oops(char *str)
141{ 144{
142 ftrace_dump_on_oops = 1; 145 if (*str++ != '=' || !*str) {
143 return 1; 146 ftrace_dump_on_oops = DUMP_ALL;
147 return 1;
148 }
149
150 if (!strcmp("orig_cpu", str)) {
151 ftrace_dump_on_oops = DUMP_ORIG;
152 return 1;
153 }
154
155 return 0;
144} 156}
145__setup("ftrace_dump_on_oops", set_ftrace_dump_on_oops); 157__setup("ftrace_dump_on_oops", set_ftrace_dump_on_oops);
146 158
@@ -4338,7 +4350,7 @@ static int trace_panic_handler(struct notifier_block *this,
4338 unsigned long event, void *unused) 4350 unsigned long event, void *unused)
4339{ 4351{
4340 if (ftrace_dump_on_oops) 4352 if (ftrace_dump_on_oops)
4341 ftrace_dump(); 4353 ftrace_dump(ftrace_dump_on_oops);
4342 return NOTIFY_OK; 4354 return NOTIFY_OK;
4343} 4355}
4344 4356
@@ -4355,7 +4367,7 @@ static int trace_die_handler(struct notifier_block *self,
4355 switch (val) { 4367 switch (val) {
4356 case DIE_OOPS: 4368 case DIE_OOPS:
4357 if (ftrace_dump_on_oops) 4369 if (ftrace_dump_on_oops)
4358 ftrace_dump(); 4370 ftrace_dump(ftrace_dump_on_oops);
4359 break; 4371 break;
4360 default: 4372 default:
4361 break; 4373 break;
@@ -4396,7 +4408,8 @@ trace_printk_seq(struct trace_seq *s)
4396 trace_seq_init(s); 4408 trace_seq_init(s);
4397} 4409}
4398 4410
4399static void __ftrace_dump(bool disable_tracing) 4411static void
4412__ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode)
4400{ 4413{