Re: One-off rcu_nocb_rdp_deoffload bug

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>
> 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 {





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux