To advoid invalid reference, updating work result is moved to cpu_stop_signal_done().
Signed-off-by: Hillf Danton <dhi...@gmail.com> --- --- a/kernel/stop_machine.c Wed Feb 6 19:50:56 2013 +++ b/kernel/stop_machine.c Wed Feb 6 19:54:34 2013 @@ -51,9 +51,11 @@ static void cpu_stop_init_done(struct cp } /* signal completion unless @done is NULL */ -static void cpu_stop_signal_done(struct cpu_stop_done *done, bool executed) +static void cpu_stop_signal_done(struct cpu_stop_done *done, bool executed, int ret) { if (done) { + if (ret) + done->ret = ret; if (executed) done->executed = true; if (atomic_dec_and_test(&done->nr_todo)) @@ -73,7 +75,7 @@ static void cpu_stop_queue_work(struct c list_add_tail(&work->list, &stopper->works); wake_up_process(stopper->thread); } else - cpu_stop_signal_done(work->done, false); + cpu_stop_signal_done(work->done, false, 0); spin_unlock_irqrestore(&stopper->lock, flags); } @@ -279,8 +281,6 @@ repeat: preempt_disable(); ret = fn(arg); - if (ret) - done->ret = ret; /* restore preemption and check it's still balanced */ preempt_enable(); @@ -289,7 +289,7 @@ repeat: kallsyms_lookup((unsigned long)fn, NULL, NULL, NULL, ksym_buf), arg); - cpu_stop_signal_done(done, true); + cpu_stop_signal_done(done, true, ret); } else schedule(); @@ -343,7 +343,7 @@ static int __cpuinit cpu_stop_cpu_callba /* drain remaining works */ spin_lock_irq(&stopper->lock); list_for_each_entry(work, &stopper->works, list) - cpu_stop_signal_done(work->done, false); + cpu_stop_signal_done(work->done, false, 0); stopper->enabled = false; spin_unlock_irq(&stopper->lock); /* release the stopper */ -- -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/