rcu: Expedited wakeups need to be fully ordered
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Sat, 4 Mar 2017 20:33:53 +0000 (12:33 -0800)
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Tue, 18 Apr 2017 18:38:19 +0000 (11:38 -0700)
Expedited grace periods use workqueue handlers that wake up the requesters,
but there is no lock mediating this wakeup.  Therefore, memory barriers
are required to ensure that the handler's memory references are seen by
all to occur before synchronize_*_expedited() returns to its caller.
Possibly detected by syzkaller.

Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
kernel/rcu/tree_exp.h

index 51ca287828a21c740e77e38b4484ff0b03ed718f..027e123d93c728af62690ddc762927ab5c33514c 100644 (file)
@@ -533,6 +533,7 @@ static void rcu_exp_wait_wake(struct rcu_state *rsp, unsigned long s)
                                rnp->exp_seq_rq = s;
                        spin_unlock(&rnp->exp_lock);
                }
+               smp_mb(); /* All above changes before wakeup. */
                wake_up_all(&rnp->exp_wq[(rsp->expedited_sequence >> 1) & 0x3]);
        }
        trace_rcu_exp_grace_period(rsp->name, s, TPS("endwake"));
@@ -614,6 +615,7 @@ static void _synchronize_rcu_expedited(struct rcu_state *rsp,
        wait_event(rnp->exp_wq[(s >> 1) & 0x3],
                   sync_exp_work_done(rsp,
                                      &rdp->exp_workdone0, s));
+       smp_mb(); /* Workqueue actions happen before return. */
 
        /* Let the next expedited grace period start. */
        mutex_unlock(&rsp->exp_mutex);