> > Le Thu, Sep 05, 2024 at 08:32:16PM +0200, Frederic Weisbecker a écrit : > > Le Wed, Sep 04, 2024 at 06:52:36AM -0700, Paul E. McKenney a écrit : > > > > Yes, I'm preparing an update for the offending patch (which has one more > > > > embarassing issue while I'm going through it again). > > > > > > Very good, thank you! > > > > So my proposal for a replacement patch is this (to replace the patch > > of the same name in Neeraj tree): > > FYI, the diffstat against the previous version of the same patch is as follows. > The rationale being: > > 1) rdp->nocb_cb_kthread doesn't need to be protected by nocb_gp_kthread_mutex > > 2) Once rcuoc is parked, we really _must_ observe the callback list counter decremented > after the barrier's completion. > > 3) This fixes another issue: rcuoc must be parked _before_ > rcu_nocb_queue_toggle_rdp() is called, otherwise a nocb locked sequence > within rcuoc would race with rcuog clearing SEGCBLIST_OFFLOADED concurrently, > leaving the nocb locked forever. > > This WARN_ON_ONCE(rcu_segcblist_n_cbs(&rdp->cblist)) warning still occurs. insmod rcutorture.ko torture_type=rcu fwd_progress=8 n_barrier_cbs=8 nocbs_nthreads=8 nocbs_toggle=100 onoff_interval=60 test_boost=2 I added some debug modifications: diff --git a/kernel/rcu/tree_nocb.h b/kernel/rcu/tree_nocb.h index 97b99cd06923..f44eee88b8ad 100644 --- a/kernel/rcu/tree_nocb.h +++ b/kernel/rcu/tree_nocb.h @@ -1042,6 +1042,20 @@ static bool rcu_nocb_rdp_deoffload_wait_cond(struct rcu_data *rdp) return ret; } +static void rcu_nocb_dump_cblist(struct rcu_segcblist *cblist, int ncheck) +{ + struct rcu_head *rhp; + int index = 0; + + rhp = cblist->head; + while (rhp) { + pr_info("rcu_callback func: %ps\n", rhp->func); + if (++index >= ncheck) + break; + rhp = rhp->next; + } +} + static int rcu_nocb_rdp_deoffload(struct rcu_data *rdp) { unsigned long flags; @@ -1065,7 +1079,8 @@ static int rcu_nocb_rdp_deoffload(struct rcu_data *rdp) rcu_nocb_lock_irqsave(rdp, flags); WARN_ON_ONCE(rcu_cblist_n_cbs(&rdp->nocb_bypass)); - WARN_ON_ONCE(rcu_segcblist_n_cbs(&rdp->cblist)); + if (WARN_ON_ONCE(rcu_segcblist_n_cbs(&rdp->cblist))) + rcu_nocb_dump_cblist(&rdp->cblist, 10); rcu_nocb_unlock_irqrestore(rdp, flags); wake_gp = rcu_nocb_queue_toggle_rdp(rdp); dmesg: 4,5360,150691992,-,caller=T453;WARNING: CPU: 4 PID: 453 at kernel/rcu/tree_nocb.h:1082 rcu_nocb_rdp_deoffload+0x565/0x7e0 4,5361,150692011,-,caller=T453;Modules linked in: rcutorture torture 4,5362,150692040,-,caller=T453;CPU: 4 UID: 0 PID: 453 Comm: rcu_nocb_toggle Not tainted 6.11.0-next-20240927-yoctodev-standard-dirty #67 3a2655b4a49977d4639e002ae2d5e9a4a1f2d7e2 4,5363,150692054,-,caller=T453;Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.2-0-gea1b7a073390-prebuilt.qemu.org 04/01/2014 4,5364,150692064,-,caller=T453;RIP: 0010:rcu_nocb_rdp_deoffload+0x565/0x7e0 4,5365,150692082,-,caller=T453;Code: 48 b8 00 00 00 00 00 fc ff df 80 3c 02 00 0f 85 f2 01 00 00 48 b8 22 01 00 00 00 00 ad de 48 89 83 e0 04 00 00 e9 fa fd ff ff <0f> 0b 48 8d bb a8 00 00 00 48 b8 00 00a 4,5366,150692092,-,caller=T453;RSP: 0018:ffff888006a0fcf8 EFLAGS: 00010002 4,5367,150692114,-,caller=T453;RAX: 0000000000000001 RBX: ffff88806ce103c0 RCX: 1ffff1100d9c2096 4,5368,150692124,-,caller=T453;RDX: 0000000000000000 RSI: 0000000000000008 RDI: ffff88806ce104b0 4,5369,150692133,-,caller=T453;RBP: ffff888006a0fda8 R08: ffffed100d9c2097 R09: ffffed100d9c2097 4,5370,150692142,-,caller=T453;R10: ffffed100d9c2096 R11: ffff88806ce104b7 R12: ffff88806ce105e0 4,5371,150692152,-,caller=T453;R13: ffff88806c2103c0 R14: 0000000000000246 R15: ffff88806ce104b0 4,5372,150692162,-,caller=T453;FS: 0000000000000000(0000) GS:ffff88806c000000(0000) knlGS:0000000000000000 4,5373,150692174,-,caller=T453;CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 4,5374,150692183,-,caller=T453;CR2: 0000000000000000 CR3: 000000000bbd2000 CR4: 00000000001506f0 4,5375,150692193,-,caller=T453;Call Trace: 4,5376,150692202,-,caller=T453; <TASK> 4,5377,150692214,-,caller=T453; ? show_regs+0x65/0x70 4,5378,150692232,-,caller=T453; ? __warn+0xd5/0x310 4,5379,150692255,-,caller=T453; ? rcu_nocb_rdp_deoffload+0x565/0x7e0 4,5380,150692274,-,caller=T453; ? report_bug+0x23e/0x490 4,5381,150692312,-,caller=T453; ? handle_bug+0x5b/0xa0 4,5382,150692327,-,caller=T453; ? exc_invalid_op+0x1c/0x50 4,5383,150692346,-,caller=T453; ? asm_exc_invalid_op+0x1f/0x30 4,5384,150692398,-,caller=T453; ? rcu_nocb_rdp_deoffload+0x565/0x7e0 4,5385,150692420,-,caller=T453; ? rcu_nocb_rdp_deoffload+0x1f4/0x7e0 4,5386,150692448,-,caller=T453; ? __pfx_rcu_nocb_rdp_deoffload+0x10/0x10 4,5387,150692498,-,caller=T453; rcu_nocb_cpu_deoffload+0xb9/0x140 4,5388,150692521,-,caller=T453; rcu_nocb_toggle+0x2ac/0x3c0 [rcutorture 4065733c5816d1d4498e7501cdbf52edab89e7f2] 4,5389,150692547,-,caller=T453; ? _raw_spin_unlock_irqrestore+0x4a/0x80 4,5390,150692579,-,caller=T453; ? __pfx_rcu_nocb_toggle+0x10/0x10 [rcutorture 4065733c5816d1d4498e7501cdbf52edab89e7f2] 4,5391,150692620,-,caller=T453; ? __kthread_parkme+0xb8/0x1e0 4,5392,150692637,-,caller=T453; ? preempt_count_sub+0x124/0x1b0 4,5393,150692661,-,caller=T453; ? __kasan_check_read+0x15/0x20 4,5394,150692675,-,caller=T453; ? __kthread_parkme+0xc5/0x1e0 4,5395,150692699,-,caller=T453; ? __pfx_rcu_nocb_toggle+0x10/0x10 [rcutorture 4065733c5816d1d4498e7501cdbf52edab89e7f2] 4,5396,150692728,-,caller=T453; kthread+0x306/0x3e0 4,5397,150692746,-,caller=T453; ? __pfx_kthread+0x10/0x10 4,5398,150692767,-,caller=T453; ret_from_fork+0x40/0x70 4,5399,150692779,-,caller=T453; ? __pfx_kthread+0x10/0x10 4,5400,150692797,-,caller=T453; ret_from_fork_asm+0x1a/0x30 4,5401,150692863,-,caller=T453; </TASK> 4,5402,150692872,-,caller=T453;irq event stamp: 21504 4,5403,150692880,-,caller=T453;hardirqs last enabled at (21503): [<ffffffffb3680a63>] _raw_spin_unlock_irqrestore+0x63/0x80 4,5404,150692894,-,caller=T453;hardirqs last disabled at (21504): [<ffffffffb03fc77e>] rcu_nocb_rdp_deoffload+0x3ee/0x7e0 4,5405,150692906,-,caller=T453;softirqs last enabled at (21324): [<ffffffffb01dd618>] handle_softirqs+0x428/0x800 4,5406,150692917,-,caller=T453;softirqs last disabled at (21315): [<ffffffffb01de8ef>] irq_exit_rcu+0x1af/0x220 4,5407,150692927,-,caller=T453;---[ end trace 0000000000000000 ]--- When the rcuoc kthreads process rcu callback, before invoke rcu_segcblist_add_len(&rdp->cblist, -count), the rcu_barrier() can insert rcu_barrier_callback() func to offline cpu rdp's->list. 6,5408,150692937,-,caller=T453;rcu: rcu_callback func: rcu_barrier_callback Maybe we can wait until rcu_segcblist_n_cbs(&rdp->cblist) return zero and then invoke kthread_parkme() in rcuoc kthreads. Any thoughts ? Thanks Zqiang > diff --git a/kernel/rcu/tree_nocb.h b/kernel/rcu/tree_nocb.h > index 755ada098035..97b99cd06923 100644 > --- a/kernel/rcu/tree_nocb.h > +++ b/kernel/rcu/tree_nocb.h > @@ -1056,6 +1056,13 @@ static int rcu_nocb_rdp_deoffload(struct rcu_data *rdp) > /* Flush all callbacks from segcblist and bypass */ > rcu_barrier(); > > + /* > + * Make sure the rcuoc kthread isn't in the middle of a nocb locked > + * sequence while offloading is deactivated, along with nocb locking. > + */ > + if (rdp->nocb_cb_kthread) > + kthread_park(rdp->nocb_cb_kthread); > + > rcu_nocb_lock_irqsave(rdp, flags); > WARN_ON_ONCE(rcu_cblist_n_cbs(&rdp->nocb_bypass)); > WARN_ON_ONCE(rcu_segcblist_n_cbs(&rdp->cblist)); > @@ -1064,13 +1071,11 @@ static int rcu_nocb_rdp_deoffload(struct rcu_data *rdp) > wake_gp = rcu_nocb_queue_toggle_rdp(rdp); > > mutex_lock(&rdp_gp->nocb_gp_kthread_mutex); > + > if (rdp_gp->nocb_gp_kthread) { > if (wake_gp) > wake_up_process(rdp_gp->nocb_gp_kthread); > > - if (rdp->nocb_cb_kthread) > - kthread_park(rdp->nocb_cb_kthread); > - > swait_event_exclusive(rdp->nocb_state_wq, > rcu_nocb_rdp_deoffload_wait_cond(rdp)); > } else {