lkml.org 
[lkml]   [2008]   [Dec]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH 1/5] ftrace: add ftrace_graph_stop
From: Steven Rostedt <srostedt@redhat.com>

Impact: new ftrace_graph_stop function

While developing more features of function graph, I hit a bug that
caused the WARN_ON to trigger in the prepare_ftrace_return function.
Well, it was hard for me to find out that was happening because the
bug would not print, it would just cause a hard lockup or reboot.
The reason is that it is not safe to call printk from this function.

Looking further, I also found that it calls unregister_ftrace_graph,
which grabs a mutex and calls kstop machine. This would definitely
lock the box up if it were to trigger.

This patch adds a fast and safe ftrace_graph_stop() which will
stop the function tracer. Then it is safe to call the WARN ON.

Signed-off-by: Steven Rostedt <srostedt@redhat.com>
---
arch/x86/kernel/ftrace.c | 10 ++++++----
include/linux/ftrace.h | 2 ++
kernel/trace/ftrace.c | 5 +++++
3 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 1a5b8f8..adba8e9 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -484,14 +484,16 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
: "memory"
);

- if (WARN_ON(faulted)) {
- unregister_ftrace_graph();
+ if (unlikely(faulted)) {
+ ftrace_graph_stop();
+ WARN_ON(1);
return;
}

- if (WARN_ON(!__kernel_text_address(old))) {
- unregister_ftrace_graph();
+ if (unlikely(!__kernel_text_address(old))) {
+ ftrace_graph_stop();
*parent = old;
+ WARN_ON(1);
return;
}

diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index afba918..58ca1c3 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -376,6 +376,8 @@ typedef void (*trace_func_graph_ent_t)(struct ftrace_graph_ent *); /* entry */
extern int register_ftrace_graph(trace_func_graph_ret_t retfunc,
trace_func_graph_ent_t entryfunc);

+extern void ftrace_graph_stop(void);
+
/* The current handlers in use */
extern trace_func_graph_ret_t ftrace_graph_return;
extern trace_func_graph_ent_t ftrace_graph_entry;
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 2e78628..a44af05 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -1769,5 +1769,10 @@ void ftrace_graph_exit_task(struct task_struct *t)

kfree(ret_stack);
}
+
+void ftrace_graph_stop(void)
+{
+ ftrace_stop();
+}
#endif

--
1.5.6.5
--


\
 
 \ /
  Last update: 2008-12-03 05:53    [W:0.060 / U:0.736 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site