Pull stop-machine fix from Thomas Gleixner: "A single fix, amending stop machine with WRITE/READ_ONCE() to address the fallout of KCSAN" * 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: stop_machine: Avoid potential race behaviour
Unified · Split
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | * Copyright (C) 2010 SUSE Linux Products GmbH | 7 | * Copyright (C) 2010 SUSE Linux Products GmbH |
| 8 | * Copyright (C) 2010 Tejun Heo <tj@kernel.org> | 8 | * Copyright (C) 2010 Tejun Heo <tj@kernel.org> |
| 9 | */ | 9 | */ |
| 10 | #include <linux/compiler.h> | ||
| 10 | #include <linux/completion.h> | 11 | #include <linux/completion.h> |
| 11 | #include <linux/cpu.h> | 12 | #include <linux/cpu.h> |
| 12 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| @@ -167,7 +168,7 @@ static void set_state(struct multi_stop_data *msdata, · 154 unmodified lines | |||
| 167 | /* Reset ack counter. */ | 168 | /* Reset ack counter. */ |
| 168 | atomic_set(&msdata->thread_ack, msdata->num_threads); | 169 | atomic_set(&msdata->thread_ack, msdata->num_threads); |
| 169 | smp_wmb(); | 170 | smp_wmb(); |
| 170 | msdata->state = newstate; | 171 | WRITE_ONCE(msdata->state, newstate); |
| 171 | } | 172 | } |
| 172 | 173 | ||
| 173 | /* Last one to ack a state moves to the next state. */ | 174 | /* Last one to ack a state moves to the next state. */ |
| @@ -186,7 +187,7 @@ void __weak stop_machine_yield(const struct cpumask *cpumask) · 12 unmodified lines | |||
| 186 | static int multi_cpu_stop(void *data) | 187 | static int multi_cpu_stop(void *data) |
| 187 | { | 188 | { |
| 188 | struct multi_stop_data *msdata = data; | 189 | struct multi_stop_data *msdata = data; |
| 189 | enum multi_stop_state curstate = MULTI_STOP_NONE; | 190 | enum multi_stop_state newstate, curstate = MULTI_STOP_NONE; |
| 190 | int cpu = smp_processor_id(), err = 0; | 191 | int cpu = smp_processor_id(), err = 0; |
| 191 | const struct cpumask *cpumask; | 192 | const struct cpumask *cpumask; |
| 192 | unsigned long flags; | 193 | unsigned long flags; |
| @@ -210,8 +211,9 @@ static int multi_cpu_stop(void *data) · 17 unmodified lines | |||
| 210 | do { | 211 | do { |
| 211 | /* Chill out and ensure we re-read multi_stop_state. */ | 212 | /* Chill out and ensure we re-read multi_stop_state. */ |
| 212 | stop_machine_yield(cpumask); | 213 | stop_machine_yield(cpumask); |
| 213 | if (msdata->state != curstate) { | 214 | newstate = READ_ONCE(msdata->state); |
| 214 | curstate = msdata->state; | 215 | if (newstate != curstate) { |
| 216 | curstate = newstate; | ||
| 215 | switch (curstate) { | 217 | switch (curstate) { |
| 216 | case MULTI_STOP_DISABLE_IRQ: | 218 | case MULTI_STOP_DISABLE_IRQ: |
| 217 | local_irq_disable(); | 219 | local_irq_disable(); |