]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
rcutorture: Update ->extendables check for lazy preemption
authorBoqun Feng <boqun.feng@gmail.com>
Mon, 24 Feb 2025 04:29:31 +0000 (20:29 -0800)
committerBoqun Feng <boqun.feng@gmail.com>
Wed, 5 Mar 2025 02:46:47 +0000 (18:46 -0800)
The rcutorture_one_extend_check() function's second last check assumes
that "preempt_count() & PREEMPT_MASK" is non-zero only if
RCUTORTURE_RDR_PREEMPT or RCUTORTURE_RDR_SCHED bit is set.

This works for preemptible RCU and for non-preemptible RCU running in
a non-preemptible kernel.  But it fails for non-preemptible RCU running
in a preemptible kernel because then rcu_read_lock() is just
preempt_disable(), which increases preempt count.

This commit therefore adjusts this check to take into account the case
fo non-preemptible RCU running in a preemptible kernel.

Reviewed-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
kernel/rcu/rcutorture.c

index 280bff70601764c41343577ef1f30964997e709f..4cae119dece80093e5c3603a5f5c1c7c4240ef4a 100644 (file)
@@ -1901,8 +1901,16 @@ static void rcutorture_one_extend_check(char *s, int curstate, int new, int old,
        WARN_ONCE(cur_ops->extendables &&
                  !(curstate & (RCUTORTURE_RDR_BH | RCUTORTURE_RDR_RBH)) &&
                  (preempt_count() & SOFTIRQ_MASK), ROEC_ARGS);
-       WARN_ONCE(cur_ops->extendables &&
-                 !(curstate & (RCUTORTURE_RDR_PREEMPT | RCUTORTURE_RDR_SCHED)) &&
+
+       /*
+        * non-preemptible RCU in a preemptible kernel uses preempt_disable()
+        * as rcu_read_lock().
+        */
+       mask = RCUTORTURE_RDR_PREEMPT | RCUTORTURE_RDR_SCHED;
+       if (!IS_ENABLED(CONFIG_PREEMPT_RCU))
+               mask |= RCUTORTURE_RDR_RCU_1 | RCUTORTURE_RDR_RCU_2;
+
+       WARN_ONCE(cur_ops->extendables && !(curstate & mask) &&
                  (preempt_count() & PREEMPT_MASK), ROEC_ARGS);
 
        /*