Currently __this_cpu_read() and __this_cpu_write() is used to access the
->cpu_no_qs.b.exp field of the per-CPU rcu_data structure.  However,
this can fail when the accesses can happen in interrupt handlers, as
recently started being exercised by rcutorture.  This commit therefore
upgrades the uses of __this_cpu_read() and __this_cpu_write() to their
interrupt-safe counterparts this_cpu_read() and this_cpu_write().

KCSAN located this issue.

Signed-off-by: Paul E. McKenney <[email protected]>
---
 kernel/rcu/tree_exp.h    | 4 ++--
 kernel/rcu/tree_plugin.h | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/kernel/rcu/tree_exp.h b/kernel/rcu/tree_exp.h
index 82cada459e5d0c..e03cb3d447a57d 100644
--- a/kernel/rcu/tree_exp.h
+++ b/kernel/rcu/tree_exp.h
@@ -731,7 +731,7 @@ static void rcu_exp_need_qs(void)
 {
        lockdep_assert_irqs_disabled();
        
ASSERT_EXCLUSIVE_WRITER_SCOPED(*this_cpu_ptr(&rcu_data.cpu_no_qs.b.exp));
-       __this_cpu_write(rcu_data.cpu_no_qs.b.exp, true);
+       this_cpu_write(rcu_data.cpu_no_qs.b.exp, true);
        /* Store .exp before .rcu_urgent_qs. */
        smp_store_release(this_cpu_ptr(&rcu_data.rcu_urgent_qs), true);
        set_need_resched_current();
@@ -870,7 +870,7 @@ static void rcu_exp_handler(void *unused)
 
        ASSERT_EXCLUSIVE_WRITER_SCOPED(rdp->cpu_no_qs.b.exp);
        if (!(READ_ONCE(rnp->expmask) & rdp->grpmask) ||
-           __this_cpu_read(rcu_data.cpu_no_qs.b.exp))
+           this_cpu_read(rcu_data.cpu_no_qs.b.exp))
                return;
        if (rcu_is_cpu_rrupt_from_idle() ||
            (IS_ENABLED(CONFIG_PREEMPT_COUNT) && preempt_bh_enabled)) {
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 9ba136a4233a26..c3db1ad4a2807a 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -599,7 +599,7 @@ rcu_preempt_deferred_qs_irqrestore(struct task_struct *t, 
unsigned long flags)
  */
 static notrace bool rcu_preempt_need_deferred_qs(struct task_struct *t)
 {
-       return (__this_cpu_read(rcu_data.cpu_no_qs.b.exp) ||
+       return (this_cpu_read(rcu_data.cpu_no_qs.b.exp) ||
                READ_ONCE(t->rcu_read_unlock_special.s)) &&
               rcu_preempt_depth() == 0;
 }
@@ -981,7 +981,7 @@ static void rcu_qs(void)
        trace_rcu_grace_period(TPS("rcu_sched"),
                               __this_cpu_read(rcu_data.gp_seq), TPS("cpuqs"));
        __this_cpu_write(rcu_data.cpu_no_qs.b.norm, false);
-       if (__this_cpu_read(rcu_data.cpu_no_qs.b.exp))
+       if (this_cpu_read(rcu_data.cpu_no_qs.b.exp))
                rcu_report_exp_rdp(this_cpu_ptr(&rcu_data));
 }
 
-- 
2.40.1


Reply via email to