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 | 7 | * Copyright (C) 2010 SUSE Linux Products GmbH |
| 8 | 8 | * Copyright (C) 2010 Tejun Heo <tj@kernel.org> |
| 9 | 9 | */ |
| 10 | +#include <linux/compiler.h> | |
| 10 | 11 | #include <linux/completion.h> |
| 11 | 12 | #include <linux/cpu.h> |
| 12 | 13 | #include <linux/init.h> |
| @@ -167,7 +168,7 @@ static void set_state(struct multi_stop_data *msdata, · 154 unmodified lines | ||
| 167 | 168 | /* Reset ack counter. */ |
| 168 | 169 | atomic_set(&msdata->thread_ack, msdata->num_threads); |
| 169 | 170 | smp_wmb(); |
| 170 | − msdata->state = newstate; | |
| 171 | + WRITE_ONCE(msdata->state, newstate); | |
| 171 | 172 | } |
| 172 | 173 | |
| 173 | 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 | 187 | static int multi_cpu_stop(void *data) |
| 187 | 188 | { |
| 188 | 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 | 191 | int cpu = smp_processor_id(), err = 0; |
| 191 | 192 | const struct cpumask *cpumask; |
| 192 | 193 | unsigned long flags; |
| @@ -210,8 +211,9 @@ static int multi_cpu_stop(void *data) · 17 unmodified lines | ||
| 210 | 211 | do { |
| 211 | 212 | /* Chill out and ensure we re-read multi_stop_state. */ |
| 212 | 213 | stop_machine_yield(cpumask); |
| 213 | − if (msdata->state != curstate) { | |
| 214 | − curstate = msdata->state; | |
| 214 | + newstate = READ_ONCE(msdata->state); | |
| 215 | + if (newstate != curstate) { | |
| 216 | + curstate = newstate; | |
| 215 | 217 | switch (curstate) { |
| 216 | 218 | case MULTI_STOP_DISABLE_IRQ: |
| 217 | 219 | local_irq_disable(); |