diff options
| author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2008-10-22 11:00:26 -0400 |
|---|---|---|
| committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-10-21 19:00:26 -0400 |
| commit | 8163bcac779f62c6bf847caed9bce905db0693fb (patch) | |
| tree | 8fcf397c504fadbebecde09901aacef06b4551d8 /kernel | |
| parent | c9583e55fa2b08a230c549bd1e3c0bde6c50d9cc (diff) | |
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: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/stop_machine.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 0e688c6a1a63..8aff79d90ddc 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c | |||
| @@ -66,6 +66,7 @@ static void stop_cpu(struct work_struct *unused) | |||
| 66 | enum stopmachine_state curstate = STOPMACHINE_NONE; | 66 | enum stopmachine_state curstate = STOPMACHINE_NONE; |
| 67 | struct stop_machine_data *smdata = &idle; | 67 | struct stop_machine_data *smdata = &idle; |
| 68 | int cpu = smp_processor_id(); | 68 | int cpu = smp_processor_id(); |
| 69 | int err; | ||
| 69 | 70 | ||
| 70 | if (!active_cpus) { | 71 | if (!active_cpus) { |
| 71 | if (cpu == first_cpu(cpu_online_map)) | 72 | if (cpu == first_cpu(cpu_online_map)) |
| @@ -86,9 +87,11 @@ static void stop_cpu(struct work_struct *unused) | |||
| 86 | hard_irq_disable(); | 87 | hard_irq_disable(); |
| 87 | break; | 88 | break; |
| 88 | case STOPMACHINE_RUN: | 89 | case STOPMACHINE_RUN: |
| 89 | /* |= allows error detection if functions on | 90 | /* On multiple CPUs only a single error code |
| 90 | * multiple CPUs. */ | 91 | * is needed to tell that something failed. */ |
| 91 | smdata->fnret |= smdata->fn(smdata->data); | 92 | err = smdata->fn(smdata->data); |
| 93 | if (err) | ||
| 94 | smdata->fnret = err; | ||
| 92 | break; | 95 | break; |
| 93 | default: | 96 | default: |
| 94 | break; | 97 | break; |
