[Cc Joel] On Sun, Feb 23, 2025 at 08:43:10PM -0800, Boqun Feng wrote: > 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. > > Signed-off-by: Boqun Feng <boqun.feng@xxxxxxxxx> > --- > kernel/rcu/rcutorture.c | 12 ++++++++++-- > 1 file changed, 10 insertions(+), 2 deletions(-) > > diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c > index 280bff706017..4cae119dece8 100644 > --- a/kernel/rcu/rcutorture.c > +++ b/kernel/rcu/rcutorture.c > @@ -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); > > /* > -- > 2.39.5 (Apple Git-154) > >