Commit 8163bcac authored by Heiko Carstens's avatar Heiko Carstens Committed by Rusty Russell

stop_machine: fix error code handling on multiple cpus

Using |= for updating a value which might be updated on several cpus
concurrently will not always work since we need to make sure that the
update happens atomically.
To fix this just use a write if the called function returns an error
code on a cpu. We end up writing the error code of an arbitrary cpu
if multiple ones fail but that should be sufficient.
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent c9583e55
...@@ -66,6 +66,7 @@ static void stop_cpu(struct work_struct *unused) ...@@ -66,6 +66,7 @@ static void stop_cpu(struct work_struct *unused)
enum stopmachine_state curstate = STOPMACHINE_NONE; enum stopmachine_state curstate = STOPMACHINE_NONE;
struct stop_machine_data *smdata = &idle; struct stop_machine_data *smdata = &idle;
int cpu = smp_processor_id(); int cpu = smp_processor_id();
int err;
if (!active_cpus) { if (!active_cpus) {
if (cpu == first_cpu(cpu_online_map)) if (cpu == first_cpu(cpu_online_map))
...@@ -86,9 +87,11 @@ static void stop_cpu(struct work_struct *unused) ...@@ -86,9 +87,11 @@ static void stop_cpu(struct work_struct *unused)
hard_irq_disable(); hard_irq_disable();
break; break;
case STOPMACHINE_RUN: case STOPMACHINE_RUN:
/* |= allows error detection if functions on /* On multiple CPUs only a single error code
* multiple CPUs. */ * is needed to tell that something failed. */
smdata->fnret |= smdata->fn(smdata->data); err = smdata->fn(smdata->data);
if (err)
smdata->fnret = err;
break; break;
default: default:
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment