When CONFIG_THREAD_INFO_IN_TASK is selected, task stacks may be freed before a task is destroyed. To account for this, the stacks are refcounted, and when manipulating the stack of another task, it is necessary to get/put the stack to ensure it isn't freed and/or re-used while we do so. This patch reworks the MIPS stack walking code to account for this. When CONFIG_THREAD_INFO_IN_TASK is not selected these perform no refcounting, and this should only be a structural change that does not affect behaviour. Signed-off-by: Matt Redfearn <matt.redfearn@xxxxxxxx> --- arch/mips/kernel/process.c | 3 ++- arch/mips/kernel/stacktrace.c | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 45d0b6b037ee..24b4e8c02508 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -627,7 +627,7 @@ unsigned long get_wchan(struct task_struct *task) if (!task || task == current || task->state == TASK_RUNNING) goto out; - if (!task_stack_page(task)) + if (!try_get_task_stack(task)) goto out; pc = thread_saved_pc(task); @@ -639,6 +639,7 @@ unsigned long get_wchan(struct task_struct *task) pc = unwind_stack(task, &sp, pc, &ra); #endif + put_task_stack(task); out: return pc; } diff --git a/arch/mips/kernel/stacktrace.c b/arch/mips/kernel/stacktrace.c index 7c7c902249f2..babf2dd165a0 100644 --- a/arch/mips/kernel/stacktrace.c +++ b/arch/mips/kernel/stacktrace.c @@ -81,6 +81,9 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) WARN_ON(trace->nr_entries || !trace->max_entries); + if (!try_get_task_stack(tsk)) + return; + if (tsk != current) { regs->regs[29] = tsk->thread.reg29; regs->regs[31] = 0; @@ -88,5 +91,7 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) } else prepare_frametrace(regs); save_context_stack(trace, tsk, regs, tsk == current); + + put_task_stack(tsk); } EXPORT_SYMBOL_GPL(save_stack_trace_tsk); -- 2.7.4