]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
rcu: Add *_ONCE() to rcu_node ->boost_kthread_status
authorPaul E. McKenney <paulmck@kernel.org>
Thu, 9 Jan 2020 04:12:59 +0000 (20:12 -0800)
committerPaul E. McKenney <paulmck@kernel.org>
Thu, 20 Feb 2020 23:58:22 +0000 (15:58 -0800)
The rcu_node structure's ->boost_kthread_status field is accessed
locklessly, so this commit causes all updates to use WRITE_ONCE() and
all reads to use READ_ONCE().

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/tree_plugin.h

index b5ba148640153141280586ed85843ba064e895df..0f8b714f09f5ad576ce00efe7be28035d7eaeb33 100644 (file)
@@ -1032,18 +1032,18 @@ static int rcu_boost_kthread(void *arg)
 
        trace_rcu_utilization(TPS("Start boost kthread@init"));
        for (;;) {
-               rnp->boost_kthread_status = RCU_KTHREAD_WAITING;
+               WRITE_ONCE(rnp->boost_kthread_status, RCU_KTHREAD_WAITING);
                trace_rcu_utilization(TPS("End boost kthread@rcu_wait"));
                rcu_wait(rnp->boost_tasks || rnp->exp_tasks);
                trace_rcu_utilization(TPS("Start boost kthread@rcu_wait"));
-               rnp->boost_kthread_status = RCU_KTHREAD_RUNNING;
+               WRITE_ONCE(rnp->boost_kthread_status, RCU_KTHREAD_RUNNING);
                more2boost = rcu_boost(rnp);
                if (more2boost)
                        spincnt++;
                else
                        spincnt = 0;
                if (spincnt > 10) {
-                       rnp->boost_kthread_status = RCU_KTHREAD_YIELDING;
+                       WRITE_ONCE(rnp->boost_kthread_status, RCU_KTHREAD_YIELDING);
                        trace_rcu_utilization(TPS("End boost kthread@rcu_yield"));
                        schedule_timeout_interruptible(2);
                        trace_rcu_utilization(TPS("Start boost kthread@rcu_yield"));
@@ -1082,7 +1082,7 @@ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags)
                        rnp->boost_tasks = rnp->gp_tasks;
                raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                rcu_wake_cond(rnp->boost_kthread_task,
-                             rnp->boost_kthread_status);
+                             READ_ONCE(rnp->boost_kthread_status));
        } else {
                raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
        }