summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ftrace.h1
-rw-r--r--kernel/trace/ftrace.c5
-rw-r--r--kernel/trace/trace_functions_graph.c35
3 files changed, 36 insertions, 5 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 4807a39e7ae1..18fb2c4a3f7f 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -760,6 +760,7 @@ extern char __irqentry_text_end[];
extern int register_ftrace_graph(trace_func_graph_ret_t retfunc,
trace_func_graph_ent_t entryfunc);
+extern bool ftrace_graph_is_dead(void);
extern void ftrace_graph_stop(void);
/* The current handlers in use */
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 1776153ea6e0..8063280fd53d 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -5473,9 +5473,4 @@ void ftrace_graph_exit_task(struct task_struct *t)
kfree(ret_stack);
}
-
-void ftrace_graph_stop(void)
-{
- ftrace_stop();
-}
#endif
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 4de3e57f723c..3604690be70b 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -15,6 +15,38 @@
#include "trace.h"
#include "trace_output.h"
+static bool kill_ftrace_graph;
+
+/**
+ * ftrace_graph_is_dead - returns true if ftrace_graph_stop() was called
+ *
+ * ftrace_graph_stop() is called when a severe error is detected in
+ * the function graph tracing. This function is called by the critical
+ * paths of function graph to keep those paths from doing any more harm.
+ */
+bool ftrace_graph_is_dead(void)
+{
+ return kill_ftrace_graph;
+}
+
+/**
+ * ftrace_graph_stop - set to permanently disable function graph tracincg
+ *
+ * In case of an error int function graph tracing, this is called
+ * to try to keep function graph tracing from causing any more harm.
+ * Usually this is pretty severe and this is called to try to at least
+ * get a warning out to the user.
+ */
+void ftrace_graph_stop(void)
+{
+ kill_ftrace_graph = true;
+ /*
+ * ftrace_stop() will be removed when all archs are updated to
+ * use ftrace_graph_is_dead()
+ */
+ ftrace_stop();
+}
+
/* When set, irq functions will be ignored */
static int ftrace_graph_skip_irqs;
@@ -92,6 +124,9 @@ ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth,
unsigned long long calltime;
int index;
+ if (unlikely(ftrace_graph_is_dead()))
+ return -EBUSY;
+
if (!current->ret_stack)
return -EBUSY;
OpenPOWER on IntegriCloud