diff options
author | Steven Rostedt <srostedt@redhat.com> | 2009-06-02 12:03:19 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2009-06-02 12:03:19 -0400 |
commit | 179c498ae2998461fe436437a74dc29036fc7dcc (patch) | |
tree | 7794227a9cc45c2ec22d3e3b3062a96d34e8b0b9 /kernel/trace | |
parent | 88fc86c283d9c3854e67e4155808027bc2519eb6 (diff) |
function-graph: only allocate init tasks if it was not already done
When the function graph tracer is enabled, it calls the initialization
needed for the init tasks that would be called on all created tasks.
The problem is that this is called every time the function graph tracer
is enabled, and the ret_stack is allocated for the idle tasks each time.
Thus, the old ret_stack is lost and a memory leak is created.
This is also dangerous because if an interrupt happened on another CPU
with the init task and the ret_stack is replaced, we then lose all the
return pointers for the interrupt, and a crash would take place.
[ Impact: fix memory leak and possible crash due to race ]
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/ftrace.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index f1ed080406c3..ebff62ef40be 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -2643,8 +2643,10 @@ static int start_graph_tracing(void) | |||
2643 | return -ENOMEM; | 2643 | return -ENOMEM; |
2644 | 2644 | ||
2645 | /* The cpu_boot init_task->ret_stack will never be freed */ | 2645 | /* The cpu_boot init_task->ret_stack will never be freed */ |
2646 | for_each_online_cpu(cpu) | 2646 | for_each_online_cpu(cpu) { |
2647 | ftrace_graph_init_task(idle_task(cpu)); | 2647 | if (!idle_task(cpu)->ret_stack) |
2648 | ftrace_graph_init_task(idle_task(cpu)); | ||
2649 | } | ||
2648 | 2650 | ||
2649 | do { | 2651 | do { |
2650 | ret = alloc_retstack_tasklist(ret_stack_list); | 2652 | ret = alloc_retstack_tasklist(ret_stack_list); |