srcu: Fix __call_srcu()/process_srcu() datarace
authorPaul E. McKenney <paulmck@kernel.org>
Mon, 23 Dec 2019 03:32:54 +0000 (19:32 -0800)
committerPaul E. McKenney <paulmck@kernel.org>
Fri, 21 Feb 2020 00:01:11 +0000 (16:01 -0800)
The srcu_node 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: Paul E. McKenney <paulmck@kernel.org>
kernel/rcu/srcutree.c

index 657e6a7d1c03e5dde1223fe2ca289acdd97777da..b1edac93e403f9d75120026a0a6a72240c415949 100644 (file)
@@ -550,7 +550,7 @@ static void srcu_gp_end(struct srcu_struct *ssp)
                snp->srcu_have_cbs[idx] = gpseq;
                rcu_seq_set_state(&snp->srcu_have_cbs[idx], 1);
                if (ULONG_CMP_LT(snp->srcu_gp_seq_needed_exp, gpseq))
-                       snp->srcu_gp_seq_needed_exp = gpseq;
+                       WRITE_ONCE(snp->srcu_gp_seq_needed_exp, gpseq);
                mask = snp->srcu_data_have_cbs[idx];
                snp->srcu_data_have_cbs[idx] = 0;
                spin_unlock_irq_rcu_node(snp);
@@ -660,7 +660,7 @@ static void srcu_funnel_gp_start(struct srcu_struct *ssp, struct srcu_data *sdp,
                if (snp == sdp->mynode)
                        snp->srcu_data_have_cbs[idx] |= sdp->grpmask;
                if (!do_norm && ULONG_CMP_LT(snp->srcu_gp_seq_needed_exp, s))
-                       snp->srcu_gp_seq_needed_exp = s;
+                       WRITE_ONCE(snp->srcu_gp_seq_needed_exp, s);
                spin_unlock_irqrestore_rcu_node(snp, flags);
        }