Commit 8c9e0cb3 authored by Paul E. McKenney's avatar Paul E. McKenney
Browse files

srcu: Fix __call_srcu()/srcu_get_delay() datarace



The srcu_struct structure's ->srcu_gp_seq_needed_exp field is accessed
locklessly, so updates must use WRITE_ONCE().  This commit therefore
adds the needed WRITE_ONCE() invocations.

This data race was reported by KCSAN.  Not appropriate for backporting
due to failure being unlikely.

Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
parent 7ff8b450
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -534,7 +534,7 @@ static void srcu_gp_end(struct srcu_struct *ssp)
	rcu_seq_end(&ssp->srcu_gp_seq);
	gpseq = rcu_seq_current(&ssp->srcu_gp_seq);
	if (ULONG_CMP_LT(ssp->srcu_gp_seq_needed_exp, gpseq))
		ssp->srcu_gp_seq_needed_exp = gpseq;
		WRITE_ONCE(ssp->srcu_gp_seq_needed_exp, gpseq);
	spin_unlock_irq_rcu_node(ssp);
	mutex_unlock(&ssp->srcu_gp_mutex);
	/* A new grace period can start at this point.  But only one. */
@@ -614,7 +614,7 @@ static void srcu_funnel_exp_start(struct srcu_struct *ssp, struct srcu_node *snp
	}
	spin_lock_irqsave_rcu_node(ssp, flags);
	if (ULONG_CMP_LT(ssp->srcu_gp_seq_needed_exp, s))
		ssp->srcu_gp_seq_needed_exp = s;
		WRITE_ONCE(ssp->srcu_gp_seq_needed_exp, s);
	spin_unlock_irqrestore_rcu_node(ssp, flags);
}

@@ -674,7 +674,7 @@ static void srcu_funnel_gp_start(struct srcu_struct *ssp, struct srcu_data *sdp,
		smp_store_release(&ssp->srcu_gp_seq_needed, s); /*^^^*/
	}
	if (!do_norm && ULONG_CMP_LT(ssp->srcu_gp_seq_needed_exp, s))
		ssp->srcu_gp_seq_needed_exp = s;
		WRITE_ONCE(ssp->srcu_gp_seq_needed_exp, s);

	/* If grace period not already done and none in progress, start it. */
	if (!rcu_seq_done(&ssp->srcu_gp_seq, s) &&