summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2013-06-14 22:21:43 +0200
committerSteven Rostedt <rostedt@goodmis.org>2013-06-20 05:32:07 +0200
commitde7edd31457b626e54a0b2a7e8ff4d65492f01ad (patch)
treefc98cad3155f6cded6192709c4cb496dd17282db /kernel
parenttracing: Update documentation on tracepoint glob matching (diff)
downloadlinux-de7edd31457b626e54a0b2a7e8ff4d65492f01ad.tar.xz
linux-de7edd31457b626e54a0b2a7e8ff4d65492f01ad.zip
tracing: Disable tracing on warning
Add a traceoff_on_warning option in both the kernel command line as well as a sysctl option. When set, any WARN*() function that is hit will cause the tracing_on variable to be cleared, which disables writing to the ring buffer. This is useful especially when tracing a bug with function tracing. When a warning is hit, the print caused by the warning can flood the trace with the functions that producing the output for the warning. This can make the resulting trace useless by either hiding where the bug happened, or worse, by overflowing the buffer and losing the trace of the bug totally. Acked-by: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/panic.c3
-rw-r--r--kernel/sysctl.c7
-rw-r--r--kernel/trace/trace.c17
3 files changed, 27 insertions, 0 deletions
diff --git a/kernel/panic.c b/kernel/panic.c
index 167ec097ce8b..4cea6cc628ab 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -15,6 +15,7 @@
#include <linux/notifier.h>
#include <linux/module.h>
#include <linux/random.h>
+#include <linux/ftrace.h>
#include <linux/reboot.h>
#include <linux/delay.h>
#include <linux/kexec.h>
@@ -399,6 +400,8 @@ struct slowpath_args {
static void warn_slowpath_common(const char *file, int line, void *caller,
unsigned taint, struct slowpath_args *args)
{
+ disable_trace_on_warning();
+
printk(KERN_WARNING "------------[ cut here ]------------\n");
printk(KERN_WARNING "WARNING: at %s:%d %pS()\n", file, line, caller);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 9edcf456e0fc..5b0f18c12800 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -600,6 +600,13 @@ static struct ctl_table kern_table[] = {
.mode = 0644,
.proc_handler = proc_dointvec,
},
+ {
+ .procname = "traceoff_on_warning",
+ .data = &__disable_trace_on_warning,
+ .maxlen = sizeof(__disable_trace_on_warning),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
#endif
#ifdef CONFIG_MODULES
{
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 5f4a09c12e0b..c4c9296b1916 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -115,6 +115,9 @@ cpumask_var_t __read_mostly tracing_buffer_mask;
enum ftrace_dump_mode ftrace_dump_on_oops;
+/* When set, tracing will stop when a WARN*() is hit */
+int __disable_trace_on_warning;
+
static int tracing_set_tracer(const char *buf);
#define MAX_TRACER_SIZE 100
@@ -149,6 +152,13 @@ static int __init set_ftrace_dump_on_oops(char *str)
}
__setup("ftrace_dump_on_oops", set_ftrace_dump_on_oops);
+static int __init stop_trace_on_warning(char *str)
+{
+ __disable_trace_on_warning = 1;
+ return 1;
+}
+__setup("traceoff_on_warning=", stop_trace_on_warning);
+
static int __init boot_alloc_snapshot(char *str)
{
allocate_snapshot = true;
@@ -170,6 +180,7 @@ static int __init set_trace_boot_options(char *str)
}
__setup("trace_options=", set_trace_boot_options);
+
unsigned long long ns2usecs(cycle_t nsec)
{
nsec += 500;
@@ -562,6 +573,12 @@ void tracing_off(void)
}
EXPORT_SYMBOL_GPL(tracing_off);
+void disable_trace_on_warning(void)
+{
+ if (__disable_trace_on_warning)
+ tracing_off();
+}
+
/**
* tracing_is_on - show state of ring buffers enabled
*/