Commit 91dc9542 authored by Paul E. McKenney's avatar Paul E. McKenney
Browse files

rcu: Protect ->gp_flags accesses with ACCESS_ONCE()



A number of ->gp_flags accesses don't have ACCESS_ONCE(), but all of
the can race against other loads or stores.  This commit therefore
applies ACCESS_ONCE() to the unprotected ->gp_flags accesses.

Reported-by: default avatarAlexey Roytman <alexey.roytman@oracle.com>
Signed-off-by: default avatarPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Reviewed-by: default avatarJosh Triplett <josh@joshtriplett.org>
parent c9eaa447
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -1403,12 +1403,12 @@ static int rcu_gp_init(struct rcu_state *rsp)
	rcu_bind_gp_kthread();
	raw_spin_lock_irq(&rnp->lock);
	smp_mb__after_unlock_lock();
	if (rsp->gp_flags == 0) {
	if (!ACCESS_ONCE(rsp->gp_flags)) {
		/* Spurious wakeup, tell caller to go back to sleep.  */
		raw_spin_unlock_irq(&rnp->lock);
		return 0;
	}
	rsp->gp_flags = 0; /* Clear all flags: New grace period. */
	ACCESS_ONCE(rsp->gp_flags) = 0; /* Clear all flags: New grace period. */

	if (WARN_ON_ONCE(rcu_gp_in_progress(rsp))) {
		/*
@@ -1501,7 +1501,7 @@ static int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in)
	if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) {
		raw_spin_lock_irq(&rnp->lock);
		smp_mb__after_unlock_lock();
		rsp->gp_flags &= ~RCU_GP_FLAG_FQS;
		ACCESS_ONCE(rsp->gp_flags) &= ~RCU_GP_FLAG_FQS;
		raw_spin_unlock_irq(&rnp->lock);
	}
	return fqs_state;
@@ -1566,7 +1566,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
	rdp = this_cpu_ptr(rsp->rda);
	rcu_advance_cbs(rsp, rnp, rdp);  /* Reduce false positives below. */
	if (cpu_needs_another_gp(rsp, rdp)) {
		rsp->gp_flags = RCU_GP_FLAG_INIT;
		ACCESS_ONCE(rsp->gp_flags) = RCU_GP_FLAG_INIT;
		trace_rcu_grace_period(rsp->name,
				       ACCESS_ONCE(rsp->gpnum),
				       TPS("newreq"));
@@ -1695,7 +1695,7 @@ rcu_start_gp_advanced(struct rcu_state *rsp, struct rcu_node *rnp,
		 */
		return;
	}
	rsp->gp_flags = RCU_GP_FLAG_INIT;
	ACCESS_ONCE(rsp->gp_flags) = RCU_GP_FLAG_INIT;
	trace_rcu_grace_period(rsp->name, ACCESS_ONCE(rsp->gpnum),
			       TPS("newreq"));

@@ -2320,7 +2320,7 @@ static void force_quiescent_state(struct rcu_state *rsp)
		raw_spin_unlock_irqrestore(&rnp_old->lock, flags);
		return;  /* Someone beat us to it. */
	}
	rsp->gp_flags |= RCU_GP_FLAG_FQS;
	ACCESS_ONCE(rsp->gp_flags) |= RCU_GP_FLAG_FQS;
	raw_spin_unlock_irqrestore(&rnp_old->lock, flags);
	wake_up(&rsp->gp_wq);  /* Memory barrier implied by wake_up() path. */
}