rcu: Add READ_ONCE() to rcu_node ->gp_seq
authorPaul E. McKenney <paulmck@kernel.org>
Fri, 3 Jan 2020 22:53:31 +0000 (14:53 -0800)
committerPaul E. McKenney <paulmck@kernel.org>
Thu, 20 Feb 2020 23:58:22 +0000 (15:58 -0800)
The rcu_node structure's ->gp_seq field is read locklessly, so this
commit adds the READ_ONCE() to several loads in order to avoid
destructive compiler optimizations.

This data race was reported by KCSAN.  Not appropriate for backporting
because this affects only tracing and warnings.

Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
kernel/rcu/tree.c

index bb57c24dbe9a50bcc736052079335fa4334fd84f..236692d7762fcfe2d50783b745d32ed732fdde41 100644 (file)
@@ -1126,8 +1126,9 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)
 static void trace_rcu_this_gp(struct rcu_node *rnp, struct rcu_data *rdp,
                              unsigned long gp_seq_req, const char *s)
 {
-       trace_rcu_future_grace_period(rcu_state.name, rnp->gp_seq, gp_seq_req,
-                                     rnp->level, rnp->grplo, rnp->grphi, s);
+       trace_rcu_future_grace_period(rcu_state.name, READ_ONCE(rnp->gp_seq),
+                                     gp_seq_req, rnp->level,
+                                     rnp->grplo, rnp->grphi, s);
 }
 
 /*
@@ -1904,7 +1905,7 @@ static void rcu_report_qs_rnp(unsigned long mask, struct rcu_node *rnp,
                rnp_c = rnp;
                rnp = rnp->parent;
                raw_spin_lock_irqsave_rcu_node(rnp, flags);
-               oldmask = rnp_c->qsmask;
+               oldmask = READ_ONCE(rnp_c->qsmask);
        }
 
        /*
@@ -2052,7 +2053,7 @@ int rcutree_dying_cpu(unsigned int cpu)
                return 0;
 
        blkd = !!(rnp->qsmask & rdp->grpmask);
-       trace_rcu_grace_period(rcu_state.name, rnp->gp_seq,
+       trace_rcu_grace_period(rcu_state.name, READ_ONCE(rnp->gp_seq),
                               blkd ? TPS("cpuofl") : TPS("cpuofl-bgp"));
        return 0;
 }