linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* lockdep warning about possible circular dependency in PSI
@ 2020-04-15 23:01 Suren Baghdasaryan
  2020-04-24 16:34 ` Suren Baghdasaryan
  0 siblings, 1 reply; 7+ messages in thread
From: Suren Baghdasaryan @ 2020-04-15 23:01 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Andrew Morton, will,
	Johannes Weiner, Shakeel Butt, LKML, kernel-team

I received a report about possible circular locking dependency warning
generated from PSI polling code. I think we are protected from this
scenario by poll_scheduled atomic but wanted to double-check and I’m
looking for an advice on how to annotate this case to fix the lockdep
warning. I copied the detailed information at the end of this email
but the short story is this:

"WARNING: possible circular locking dependency detected" is generated
with CONFIG_PSI and CONFIG_LOCKDEP enabled. The dependency chain it
describes is:

#0
kthread_delayed_work_timer_fn()
 |
worker->lock
 |
try_to_wake_up()
 |
p->pi_lock

#1
sched_fork()
 |
p->pi_lock
 |
task_fork_fair()
 |
rq->lock

#2
psi_memstall_enter
 |
rq->lock
 |
kthread_queue_delayed_work()
 |
worker->lock

#0 holds worker->lock and takes task->pi_lock
#1 holds task->pi_lock and takes rq->lock;
#2 holds rq->lock and takes worker->lock;

However before #2 calls kthread_queue_delayed_work (to schedule
psi_poll_work) and takes worker->lock it checks and sets
poll_scheduled atomic here:
https://elixir.bootlin.com/linux/latest/source/kernel/sched/psi.c#L561
which will prevent it from proceeding. For #0 to hold worker->lock
psi_poll_work should be scheduled, so these two events should never
happen at the same time. The logic here is that we do not reschedule
psi_poll_work if it’s already scheduled and
kthread_delayed_work_timer_fn will not be holding worker->lock unless
psi_poll_work is scheduled.

Note: poll_scheduled gets reset inside psi_poll_work
https://elixir.bootlin.com/linux/latest/source/kernel/sched/psi.c#L589,
at which time it’s not scheduled and kthread_delayed_work_timer_fn
can’t hold the worker->lock.
Note: worker used in kthread_delayed_work_timer_fn and in
kthread_queue_delayed_work is not shared with any other delayed work
because it is created for each individual PSI group:
https://elixir.bootlin.com/linux/latest/source/kernel/sched/psi.c#L1068.

Could someone please (1) confirm that this lockdep warning is indeed a
false positive and (2) advise on how to annotate this situation so
that lockdep is satisfied. AFAIK there is no construct like
lockdep_assert_not_held which I could call after setting
poll_scheduled and before calling kthread_queue_delayed_work to
declare that worker->lock is not held by anyone.
Thanks,
Suren.

COMPLETE REPORT:

<4>[  337.948389] c3 ======================================================
<4>[  337.948392] c3 WARNING: possible circular locking dependency detected
<4>[  337.948399] c3 4.14.133+ #1 Tainted: G S         O
<4>[  337.948401] c3 ------------------------------------------------------
<4>[  337.948407] c3 kswapd0/813 is trying to acquire lock:
<4>[  337.948410] c3  (&p->pi_lock){-.-.}, at: [<0000000031701355>]
try_to_wake_up+0x4c/0x6c4
<4>[  337.948434] c3
<4>[  337.948434] c3 but task is already holding lock:
<4>[  337.948436] c3  ((worker)->lock){..-.}, at: [<0000000038d38987>]
kthread_delayed_work_timer_fn+0x2c/0x98
<4>[  337.948450] c3
<4>[  337.948450] c3 which lock already depends on the new lock.
<4>[  337.948450] c3
<4>[  337.948452] c3
<4>[  337.948452] c3 the existing dependency chain (in reverse order) is:
<4>[  337.948455] c3
<4>[  337.948455] c3 -> #2 ((worker)->lock){..-.}:
<4>[  337.948471] c3        _raw_spin_lock_irqsave+0x54/0x94
<4>[  337.948475] c3        kthread_queue_delayed_work+0x30/0xac
<4>[  337.948482] c3        psi_schedule_poll_work+0xe0/0x148
<4>[  337.948486] c3        psi_task_change+0x318/0x374
<4>[  337.948491] c3        psi_memstall_enter+0xa4/0xbc
<4>[  337.948497] c3        kswapd+0x69c/0x9d4
<4>[  337.948501] c3        kthread+0x11c/0x12c
<4>[  337.948507] c3        ret_from_fork+0x10/0x18
<4>[  337.948509] c3
<4>[  337.948509] c3 -> #1 (&rq->lock){-.-.}:
<4>[  337.948521] c3        _raw_spin_lock+0x48/0x84
<4>[  337.948526] c3        task_fork_fair+0x3c/0xfc
<4>[  337.948531] c3        sched_fork+0x100/0x274
<4>[  337.948536] c3        copy_process+0x608/0x1860
<4>[  337.948540] c3        _do_fork+0xa8/0x620
<4>[  337.948544] c3        kernel_thread+0x44/0x54
<4>[  337.948549] c3        rest_init+0x28/0x200
<4>[  337.948556] c3        start_kernel+0x3a8/0x41c
<4>[  337.948560] c3
<4>[  337.948560] c3 -> #0 (&p->pi_lock){-.-.}:
<4>[  337.948572] c3        lock_acquire+0x210/0x248
<4>[  337.948576] c3        _raw_spin_lock_irqsave+0x54/0x94
<4>[  337.948580] c3        try_to_wake_up+0x4c/0x6c4
<4>[  337.948584] c3        wake_up_process+0x28/0x34
<4>[  337.948587] c3        kthread_insert_work+0x54/0x64
<4>[  337.948591] c3        kthread_delayed_work_timer_fn+0x68/0x98
<4>[  337.948597] c3        call_timer_fn+0x1f0/0x40c
<4>[  337.948602] c3        run_timer_softirq+0x33c/0x6fc
<4>[  337.948606] c3        __do_softirq+0x308/0x52c
<4>[  337.948611] c3        irq_exit+0xe4/0xf0
<4>[  337.948617] c3        __handle_domain_irq+0x8c/0xc4
<4>[  337.948621] c3        gic_handle_irq+0x144/0x1a4
<4>[  337.948624] c3        el1_irq+0xbc/0x138
<4>[  337.948629] c3        lock_release+0x460/0x4a4
<4>[  337.948633] c3        _raw_spin_unlock+0x28/0x60
<4>[  337.948638] c3        page_vma_mapped_walk+0x30/0x170
<4>[  337.948642] c3        page_referenced_one+0xa0/0x11c
<4>[  337.948645] c3        rmap_walk_anon+0x128/0x16c
<4>[  337.948649] c3        rmap_walk+0x54/0x60
<4>[  337.948653] c3        page_referenced+0x104/0x158
<4>[  337.948657] c3        shrink_active_list+0x240/0x538
<4>[  337.948660] c3        shrink_node_memcg+0x3e8/0x6b4
<4>[  337.948664] c3        shrink_node+0x1d0/0x30c
<4>[  337.948668] c3        kswapd+0x858/0x9d4
<4>[  337.948672] c3        kthread+0x11c/0x12c
<4>[  337.948676] c3        ret_from_fork+0x10/0x18
<4>[  337.948678] c3
<4>[  337.948678] c3 other info that might help us debug this:
<4>[  337.948678] c3
<4>[  337.948681] c3 Chain exists of:
<4>[  337.948681] c3   &p->pi_lock --> &rq->lock --> (worker)->lock
<4>[  337.948681] c3
<4>[  337.948696] c3  Possible unsafe locking scenario:
<4>[  337.948696] c3
<4>[  337.948698] c3        CPU0                    CPU1
<4>[  337.948701] c3        ----                    ----
<4>[  337.948703] c3   lock((worker)->lock);
<4>[  337.948710] c3                                lock(&rq->lock);
<4>[  337.948716] c3                                lock((worker)->lock);
<4>[  337.948722] c3   lock(&p->pi_lock);
<4>[  337.948728] c3
<4>[  337.948728] c3  *** DEADLOCK ***
<4>[  337.948728] c3
<4>[  337.948732] c3 3 locks held by kswapd0/813:
<4>[  337.948735] c3  #0:  (&anon_vma->rwsem){++++}, at:
[<000000007b6a6058>]page_lock_anon_vma_read+0x90/0x200
<4>[  337.948747] c3  #1:  ((&(&group->poll_work)->timer)){..-.}, at:
[<00000000e5121d4f>] call_timer_fn+0x54/0x40c
<4>[  337.948760] c3  #2:  ((worker)->lock){..-.}, at:
[<0000000038d38987>] kthread_delayed_work_timer_fn+0x2c/0x98
<4>[  337.948774] c3
<4>[  337.948774] c3 stack backtrace:
<4>[  337.948780] c3 CPU: 3 PID: 813 Comm: kswapd0 Tainted: G S
 O    4.14.133+ #1
<4>[  337.948783] c3 Hardware name: Unisoc UMS512 1H10 board (DT)
<4>[  337.948788] c3 Call trace:
<4>[  337.948794] c3 [<000000004d057b6f>] dump_backtrace+0x0/0x42c
<4>[  337.948799] c3 [<00000000bb3bf168>] show_stack+0x20/0x2c
<4>[  337.948804] c3 [<000000004fa8c8e4>] dump_stack+0x94/0xe4
<4>[  337.948809] c3 [<00000000b04d6c0e>] print_circular_bug+0x29c/0x2b4
<4>[  337.948813] c3 [<00000000a9e5ccc5>] __lock_acquire+0x15e0/0x15e8
<4>[  337.948817] c3 [<00000000722130d2>] lock_acquire+0x210/0x248
<4>[  337.948821] c3 [<00000000260f5fe3>] _raw_spin_lock_irqsave+0x54/0x94
<4>[  337.948825] c3 [<0000000031701355>] try_to_wake_up+0x4c/0x6c4
<4>[  337.948829] c3 [<0000000076823b43>] wake_up_process+0x28/0x34
<4>[  337.948834] c3 [<000000003c172f76>] kthread_insert_work+0x54/0x64
<4>[  337.948838] c3 [<00000000eb441b43>]
kthread_delayed_work_timer_fn+0x68/0x98
<4>[  337.948842] c3 [<000000005366d34d>] call_timer_fn+0x1f0/0x40c
<4>[  337.948846] c3 [<00000000d5906f3d>] run_timer_softirq+0x33c/0x6fc
<4>[  337.948850] c3 [<00000000b3d1ef99>] __do_softirq+0x308/0x52c
<4>[  337.948854] c3 [<00000000c9cf0fe4>] irq_exit+0xe4/0xf0
<4>[  337.948858] c3 [<0000000020b4257b>] __handle_domain_irq+0x8c/0xc4
<4>[  337.948862] c3 [<0000000069f6ed49>] gic_handle_irq+0x144/0x1a4
<4>[  337.948866] c3 Exception stack(0xffffff800b7c3650 to 0xffffff800b7c3790)
<4>[  337.948870] c3 3640:
0000000000000000 0000000000000002
<4>[  337.948874] c3 3660: 0000000000000002 ffffff800b7c3894
0000000000000001 0000000000000000
<4>[  337.948879] c3 3680: 0000000000000000 ffffff8008241768
0000000000000001 0000000000000001
<4>[  337.948883] c3 36a0: ffffffc0fb2f9b60 000000000004b5ca
00000000000000e0 000000000000010d
<4>[  337.948887] c3 36c0: 0000000000000000 ffffff800b7c3b10
0000000000000000 00000000c28f5c29
<4>[  337.948891] c3 36e0: 0000000000000004 ffffffc0f73bb980
0000000000000002 0000000000000301
<4>[  337.948896] c3 3700: ffffff80098fd898 ffffffc0f73bc300
0000000000000040 ffffff800a2c1000
<4>[  337.948900] c3 3720: 0000007f94ef8000 ffffffbf03e86c40
000000000000001a ffffff800b7c38e0
<4>[  337.948905] c3 3740: ffffff8008123540 ffffff800b7c3890
ffffff80081235e4 0000000060c00045
<4>[  337.948909] c3 3760: 0000000000000001 0000000000000000
ffffffffffffffff ffffffc0f73bb980
<4>[  337.948913] c3 3780: ffffff800b7c38e0 ffffff80081235e4
<4>[  337.948917] c3 [<00000000be726f21>] el1_irq+0xbc/0x138
<4>[  337.948921] c3 [<00000000f4a53f17>] lock_release+0x460/0x4a4
<4>[  337.948926] c3 [<00000000895b89bb>] _raw_spin_unlock+0x28/0x60
<4>[  337.948929] c3 [<00000000be16e394>] page_vma_mapped_walk+0x30/0x170
<4>[  337.948933] c3 [<0000000056ad5ed1>] page_referenced_one+0xa0/0x11c
<4>[  337.948937] c3 [<000000004a62c7eb>] rmap_walk_anon+0x128/0x16c
<4>[  337.948941] c3 [<0000000087e56155>] rmap_walk+0x54/0x60
<4>[  337.948944] c3 [<0000000030e2896b>] page_referenced+0x104/0x158
<4>[  337.948949] c3 [<0000000068cfe94a>] shrink_active_list+0x240/0x538
<4>[  337.948953] c3 [<00000000ac1be63e>] shrink_node_memcg+0x3e8/0x6b4
<4>[  337.948957] c3 [<00000000ba3f8cf8>] shrink_node+0x1d0/0x30c
<4>[  337.948961] c3 [<00000000608ff904>] kswapd+0x858/0x9d4
<4>[  337.948965] c3 [<00000000fa01e737>] kthread+0x11c/0x12c
<4>[  337.948969] c3 [<00000000f21b5e5f>] ret_from_fork+0x10/0x18

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: lockdep warning about possible circular dependency in PSI
  2020-04-15 23:01 lockdep warning about possible circular dependency in PSI Suren Baghdasaryan
@ 2020-04-24 16:34 ` Suren Baghdasaryan
  2020-04-24 17:40   ` Peter Zijlstra
  0 siblings, 1 reply; 7+ messages in thread
From: Suren Baghdasaryan @ 2020-04-24 16:34 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Andrew Morton, will,
	Johannes Weiner, Shakeel Butt, LKML, kernel-team

Sorry to bother you again folks. Any suggestions on how to silence
this lockdep warning which I believe to be a false positive?

On Wed, Apr 15, 2020 at 4:01 PM Suren Baghdasaryan <surenb@google.com> wrote:
>
> I received a report about possible circular locking dependency warning
> generated from PSI polling code. I think we are protected from this
> scenario by poll_scheduled atomic but wanted to double-check and I’m
> looking for an advice on how to annotate this case to fix the lockdep
> warning. I copied the detailed information at the end of this email
> but the short story is this:
>
> "WARNING: possible circular locking dependency detected" is generated
> with CONFIG_PSI and CONFIG_LOCKDEP enabled. The dependency chain it
> describes is:
>
> #0
> kthread_delayed_work_timer_fn()
>  |
> worker->lock
>  |
> try_to_wake_up()
>  |
> p->pi_lock
>
> #1
> sched_fork()
>  |
> p->pi_lock
>  |
> task_fork_fair()
>  |
> rq->lock
>
> #2
> psi_memstall_enter
>  |
> rq->lock
>  |
> kthread_queue_delayed_work()
>  |
> worker->lock
>
> #0 holds worker->lock and takes task->pi_lock
> #1 holds task->pi_lock and takes rq->lock;
> #2 holds rq->lock and takes worker->lock;
>
> However before #2 calls kthread_queue_delayed_work (to schedule
> psi_poll_work) and takes worker->lock it checks and sets
> poll_scheduled atomic here:
> https://elixir.bootlin.com/linux/latest/source/kernel/sched/psi.c#L561
> which will prevent it from proceeding. For #0 to hold worker->lock
> psi_poll_work should be scheduled, so these two events should never
> happen at the same time. The logic here is that we do not reschedule
> psi_poll_work if it’s already scheduled and
> kthread_delayed_work_timer_fn will not be holding worker->lock unless
> psi_poll_work is scheduled.
>
> Note: poll_scheduled gets reset inside psi_poll_work
> https://elixir.bootlin.com/linux/latest/source/kernel/sched/psi.c#L589,
> at which time it’s not scheduled and kthread_delayed_work_timer_fn
> can’t hold the worker->lock.
> Note: worker used in kthread_delayed_work_timer_fn and in
> kthread_queue_delayed_work is not shared with any other delayed work
> because it is created for each individual PSI group:
> https://elixir.bootlin.com/linux/latest/source/kernel/sched/psi.c#L1068.
>
> Could someone please (1) confirm that this lockdep warning is indeed a
> false positive and (2) advise on how to annotate this situation so
> that lockdep is satisfied. AFAIK there is no construct like
> lockdep_assert_not_held which I could call after setting
> poll_scheduled and before calling kthread_queue_delayed_work to
> declare that worker->lock is not held by anyone.
> Thanks,
> Suren.
>
> COMPLETE REPORT:
>
> <4>[  337.948389] c3 ======================================================
> <4>[  337.948392] c3 WARNING: possible circular locking dependency detected
> <4>[  337.948399] c3 4.14.133+ #1 Tainted: G S         O
> <4>[  337.948401] c3 ------------------------------------------------------
> <4>[  337.948407] c3 kswapd0/813 is trying to acquire lock:
> <4>[  337.948410] c3  (&p->pi_lock){-.-.}, at: [<0000000031701355>]
> try_to_wake_up+0x4c/0x6c4
> <4>[  337.948434] c3
> <4>[  337.948434] c3 but task is already holding lock:
> <4>[  337.948436] c3  ((worker)->lock){..-.}, at: [<0000000038d38987>]
> kthread_delayed_work_timer_fn+0x2c/0x98
> <4>[  337.948450] c3
> <4>[  337.948450] c3 which lock already depends on the new lock.
> <4>[  337.948450] c3
> <4>[  337.948452] c3
> <4>[  337.948452] c3 the existing dependency chain (in reverse order) is:
> <4>[  337.948455] c3
> <4>[  337.948455] c3 -> #2 ((worker)->lock){..-.}:
> <4>[  337.948471] c3        _raw_spin_lock_irqsave+0x54/0x94
> <4>[  337.948475] c3        kthread_queue_delayed_work+0x30/0xac
> <4>[  337.948482] c3        psi_schedule_poll_work+0xe0/0x148
> <4>[  337.948486] c3        psi_task_change+0x318/0x374
> <4>[  337.948491] c3        psi_memstall_enter+0xa4/0xbc
> <4>[  337.948497] c3        kswapd+0x69c/0x9d4
> <4>[  337.948501] c3        kthread+0x11c/0x12c
> <4>[  337.948507] c3        ret_from_fork+0x10/0x18
> <4>[  337.948509] c3
> <4>[  337.948509] c3 -> #1 (&rq->lock){-.-.}:
> <4>[  337.948521] c3        _raw_spin_lock+0x48/0x84
> <4>[  337.948526] c3        task_fork_fair+0x3c/0xfc
> <4>[  337.948531] c3        sched_fork+0x100/0x274
> <4>[  337.948536] c3        copy_process+0x608/0x1860
> <4>[  337.948540] c3        _do_fork+0xa8/0x620
> <4>[  337.948544] c3        kernel_thread+0x44/0x54
> <4>[  337.948549] c3        rest_init+0x28/0x200
> <4>[  337.948556] c3        start_kernel+0x3a8/0x41c
> <4>[  337.948560] c3
> <4>[  337.948560] c3 -> #0 (&p->pi_lock){-.-.}:
> <4>[  337.948572] c3        lock_acquire+0x210/0x248
> <4>[  337.948576] c3        _raw_spin_lock_irqsave+0x54/0x94
> <4>[  337.948580] c3        try_to_wake_up+0x4c/0x6c4
> <4>[  337.948584] c3        wake_up_process+0x28/0x34
> <4>[  337.948587] c3        kthread_insert_work+0x54/0x64
> <4>[  337.948591] c3        kthread_delayed_work_timer_fn+0x68/0x98
> <4>[  337.948597] c3        call_timer_fn+0x1f0/0x40c
> <4>[  337.948602] c3        run_timer_softirq+0x33c/0x6fc
> <4>[  337.948606] c3        __do_softirq+0x308/0x52c
> <4>[  337.948611] c3        irq_exit+0xe4/0xf0
> <4>[  337.948617] c3        __handle_domain_irq+0x8c/0xc4
> <4>[  337.948621] c3        gic_handle_irq+0x144/0x1a4
> <4>[  337.948624] c3        el1_irq+0xbc/0x138
> <4>[  337.948629] c3        lock_release+0x460/0x4a4
> <4>[  337.948633] c3        _raw_spin_unlock+0x28/0x60
> <4>[  337.948638] c3        page_vma_mapped_walk+0x30/0x170
> <4>[  337.948642] c3        page_referenced_one+0xa0/0x11c
> <4>[  337.948645] c3        rmap_walk_anon+0x128/0x16c
> <4>[  337.948649] c3        rmap_walk+0x54/0x60
> <4>[  337.948653] c3        page_referenced+0x104/0x158
> <4>[  337.948657] c3        shrink_active_list+0x240/0x538
> <4>[  337.948660] c3        shrink_node_memcg+0x3e8/0x6b4
> <4>[  337.948664] c3        shrink_node+0x1d0/0x30c
> <4>[  337.948668] c3        kswapd+0x858/0x9d4
> <4>[  337.948672] c3        kthread+0x11c/0x12c
> <4>[  337.948676] c3        ret_from_fork+0x10/0x18
> <4>[  337.948678] c3
> <4>[  337.948678] c3 other info that might help us debug this:
> <4>[  337.948678] c3
> <4>[  337.948681] c3 Chain exists of:
> <4>[  337.948681] c3   &p->pi_lock --> &rq->lock --> (worker)->lock
> <4>[  337.948681] c3
> <4>[  337.948696] c3  Possible unsafe locking scenario:
> <4>[  337.948696] c3
> <4>[  337.948698] c3        CPU0                    CPU1
> <4>[  337.948701] c3        ----                    ----
> <4>[  337.948703] c3   lock((worker)->lock);
> <4>[  337.948710] c3                                lock(&rq->lock);
> <4>[  337.948716] c3                                lock((worker)->lock);
> <4>[  337.948722] c3   lock(&p->pi_lock);
> <4>[  337.948728] c3
> <4>[  337.948728] c3  *** DEADLOCK ***
> <4>[  337.948728] c3
> <4>[  337.948732] c3 3 locks held by kswapd0/813:
> <4>[  337.948735] c3  #0:  (&anon_vma->rwsem){++++}, at:
> [<000000007b6a6058>]page_lock_anon_vma_read+0x90/0x200
> <4>[  337.948747] c3  #1:  ((&(&group->poll_work)->timer)){..-.}, at:
> [<00000000e5121d4f>] call_timer_fn+0x54/0x40c
> <4>[  337.948760] c3  #2:  ((worker)->lock){..-.}, at:
> [<0000000038d38987>] kthread_delayed_work_timer_fn+0x2c/0x98
> <4>[  337.948774] c3
> <4>[  337.948774] c3 stack backtrace:
> <4>[  337.948780] c3 CPU: 3 PID: 813 Comm: kswapd0 Tainted: G S
>  O    4.14.133+ #1
> <4>[  337.948783] c3 Hardware name: Unisoc UMS512 1H10 board (DT)
> <4>[  337.948788] c3 Call trace:
> <4>[  337.948794] c3 [<000000004d057b6f>] dump_backtrace+0x0/0x42c
> <4>[  337.948799] c3 [<00000000bb3bf168>] show_stack+0x20/0x2c
> <4>[  337.948804] c3 [<000000004fa8c8e4>] dump_stack+0x94/0xe4
> <4>[  337.948809] c3 [<00000000b04d6c0e>] print_circular_bug+0x29c/0x2b4
> <4>[  337.948813] c3 [<00000000a9e5ccc5>] __lock_acquire+0x15e0/0x15e8
> <4>[  337.948817] c3 [<00000000722130d2>] lock_acquire+0x210/0x248
> <4>[  337.948821] c3 [<00000000260f5fe3>] _raw_spin_lock_irqsave+0x54/0x94
> <4>[  337.948825] c3 [<0000000031701355>] try_to_wake_up+0x4c/0x6c4
> <4>[  337.948829] c3 [<0000000076823b43>] wake_up_process+0x28/0x34
> <4>[  337.948834] c3 [<000000003c172f76>] kthread_insert_work+0x54/0x64
> <4>[  337.948838] c3 [<00000000eb441b43>]
> kthread_delayed_work_timer_fn+0x68/0x98
> <4>[  337.948842] c3 [<000000005366d34d>] call_timer_fn+0x1f0/0x40c
> <4>[  337.948846] c3 [<00000000d5906f3d>] run_timer_softirq+0x33c/0x6fc
> <4>[  337.948850] c3 [<00000000b3d1ef99>] __do_softirq+0x308/0x52c
> <4>[  337.948854] c3 [<00000000c9cf0fe4>] irq_exit+0xe4/0xf0
> <4>[  337.948858] c3 [<0000000020b4257b>] __handle_domain_irq+0x8c/0xc4
> <4>[  337.948862] c3 [<0000000069f6ed49>] gic_handle_irq+0x144/0x1a4
> <4>[  337.948866] c3 Exception stack(0xffffff800b7c3650 to 0xffffff800b7c3790)
> <4>[  337.948870] c3 3640:
> 0000000000000000 0000000000000002
> <4>[  337.948874] c3 3660: 0000000000000002 ffffff800b7c3894
> 0000000000000001 0000000000000000
> <4>[  337.948879] c3 3680: 0000000000000000 ffffff8008241768
> 0000000000000001 0000000000000001
> <4>[  337.948883] c3 36a0: ffffffc0fb2f9b60 000000000004b5ca
> 00000000000000e0 000000000000010d
> <4>[  337.948887] c3 36c0: 0000000000000000 ffffff800b7c3b10
> 0000000000000000 00000000c28f5c29
> <4>[  337.948891] c3 36e0: 0000000000000004 ffffffc0f73bb980
> 0000000000000002 0000000000000301
> <4>[  337.948896] c3 3700: ffffff80098fd898 ffffffc0f73bc300
> 0000000000000040 ffffff800a2c1000
> <4>[  337.948900] c3 3720: 0000007f94ef8000 ffffffbf03e86c40
> 000000000000001a ffffff800b7c38e0
> <4>[  337.948905] c3 3740: ffffff8008123540 ffffff800b7c3890
> ffffff80081235e4 0000000060c00045
> <4>[  337.948909] c3 3760: 0000000000000001 0000000000000000
> ffffffffffffffff ffffffc0f73bb980
> <4>[  337.948913] c3 3780: ffffff800b7c38e0 ffffff80081235e4
> <4>[  337.948917] c3 [<00000000be726f21>] el1_irq+0xbc/0x138
> <4>[  337.948921] c3 [<00000000f4a53f17>] lock_release+0x460/0x4a4
> <4>[  337.948926] c3 [<00000000895b89bb>] _raw_spin_unlock+0x28/0x60
> <4>[  337.948929] c3 [<00000000be16e394>] page_vma_mapped_walk+0x30/0x170
> <4>[  337.948933] c3 [<0000000056ad5ed1>] page_referenced_one+0xa0/0x11c
> <4>[  337.948937] c3 [<000000004a62c7eb>] rmap_walk_anon+0x128/0x16c
> <4>[  337.948941] c3 [<0000000087e56155>] rmap_walk+0x54/0x60
> <4>[  337.948944] c3 [<0000000030e2896b>] page_referenced+0x104/0x158
> <4>[  337.948949] c3 [<0000000068cfe94a>] shrink_active_list+0x240/0x538
> <4>[  337.948953] c3 [<00000000ac1be63e>] shrink_node_memcg+0x3e8/0x6b4
> <4>[  337.948957] c3 [<00000000ba3f8cf8>] shrink_node+0x1d0/0x30c
> <4>[  337.948961] c3 [<00000000608ff904>] kswapd+0x858/0x9d4
> <4>[  337.948965] c3 [<00000000fa01e737>] kthread+0x11c/0x12c
> <4>[  337.948969] c3 [<00000000f21b5e5f>] ret_from_fork+0x10/0x18

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: lockdep warning about possible circular dependency in PSI
  2020-04-24 16:34 ` Suren Baghdasaryan
@ 2020-04-24 17:40   ` Peter Zijlstra
  2020-04-24 17:52     ` Suren Baghdasaryan
  0 siblings, 1 reply; 7+ messages in thread
From: Peter Zijlstra @ 2020-04-24 17:40 UTC (permalink / raw)
  To: Suren Baghdasaryan
  Cc: Ingo Molnar, Andrew Morton, will, Johannes Weiner, Shakeel Butt,
	LKML, kernel-team

On Fri, Apr 24, 2020 at 09:34:42AM -0700, Suren Baghdasaryan wrote:
> Sorry to bother you again folks. Any suggestions on how to silence
> this lockdep warning which I believe to be a false positive?
> 
> On Wed, Apr 15, 2020 at 4:01 PM Suren Baghdasaryan <surenb@google.com> wrote:
> >
> > I received a report about possible circular locking dependency warning
> > generated from PSI polling code. I think we are protected from this
> > scenario by poll_scheduled atomic but wanted to double-check and I’m
> > looking for an advice on how to annotate this case to fix the lockdep
> > warning. I copied the detailed information at the end of this email
> > but the short story is this:
> >
> > "WARNING: possible circular locking dependency detected" is generated
> > with CONFIG_PSI and CONFIG_LOCKDEP enabled. The dependency chain it
> > describes is:
> >
> > #0
> > kthread_delayed_work_timer_fn()
> >  |
> > worker->lock
> >  |
> > try_to_wake_up()
> >  |
> > p->pi_lock
> >
> > #1
> > sched_fork()
> >  |
> > p->pi_lock
> >  |
> > task_fork_fair()
> >  |
> > rq->lock
> >
> > #2
> > psi_memstall_enter
> >  |
> > rq->lock
> >  |
> > kthread_queue_delayed_work()
> >  |
> > worker->lock

Irrespective of it actually being a deadlock or not, it is fairly
fragile. Ideally we'd fix #2, we really should minimize the number of
locks nested under rq->lock.

That said, here's the easy fix, which breaks #0.

---
diff --git a/kernel/kthread.c b/kernel/kthread.c
index bfbfa481be3a..b443bba7dd21 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -806,14 +806,15 @@ static void kthread_insert_work_sanity_check(struct kthread_worker *worker,
 /* insert @work before @pos in @worker */
 static void kthread_insert_work(struct kthread_worker *worker,
 				struct kthread_work *work,
-				struct list_head *pos)
+				struct list_head *pos,
+				struct wake_q_head *wake_q)
 {
 	kthread_insert_work_sanity_check(worker, work);
 
 	list_add_tail(&work->node, pos);
 	work->worker = worker;
 	if (!worker->current_work && likely(worker->task))
-		wake_up_process(worker->task);
+		wake_q_add(wake_q, worker->task);
 }
 
 /**
@@ -831,15 +832,19 @@ static void kthread_insert_work(struct kthread_worker *worker,
 bool kthread_queue_work(struct kthread_worker *worker,
 			struct kthread_work *work)
 {
-	bool ret = false;
+	DEFINE_WAKE_Q(wake_q);
 	unsigned long flags;
+	bool ret = false;
 
 	raw_spin_lock_irqsave(&worker->lock, flags);
 	if (!queuing_blocked(worker, work)) {
-		kthread_insert_work(worker, work, &worker->work_list);
+		kthread_insert_work(worker, work, &worker->work_list, &wake_q);
 		ret = true;
 	}
 	raw_spin_unlock_irqrestore(&worker->lock, flags);
+
+	wake_up_q(&wake_q);
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(kthread_queue_work);
@@ -857,6 +862,7 @@ void kthread_delayed_work_timer_fn(struct timer_list *t)
 	struct kthread_delayed_work *dwork = from_timer(dwork, t, timer);
 	struct kthread_work *work = &dwork->work;
 	struct kthread_worker *worker = work->worker;
+	DEFINE_WAKE_Q(wake_q);
 	unsigned long flags;
 
 	/*
@@ -873,15 +879,18 @@ void kthread_delayed_work_timer_fn(struct timer_list *t)
 	/* Move the work from worker->delayed_work_list. */
 	WARN_ON_ONCE(list_empty(&work->node));
 	list_del_init(&work->node);
-	kthread_insert_work(worker, work, &worker->work_list);
+	kthread_insert_work(worker, work, &worker->work_list, &wake_q);
 
 	raw_spin_unlock_irqrestore(&worker->lock, flags);
+
+	wake_up_q(&wake_q);
 }
 EXPORT_SYMBOL(kthread_delayed_work_timer_fn);
 
 static void __kthread_queue_delayed_work(struct kthread_worker *worker,
 					 struct kthread_delayed_work *dwork,
-					 unsigned long delay)
+					 unsigned long delay,
+					 struct wake_q_head *wake_q)
 {
 	struct timer_list *timer = &dwork->timer;
 	struct kthread_work *work = &dwork->work;
@@ -895,7 +904,7 @@ static void __kthread_queue_delayed_work(struct kthread_worker *worker,
 	 * on that there's no such delay when @delay is 0.
 	 */
 	if (!delay) {
-		kthread_insert_work(worker, work, &worker->work_list);
+		kthread_insert_work(worker, work, &worker->work_list, wake_q);
 		return;
 	}
 
@@ -928,17 +937,21 @@ bool kthread_queue_delayed_work(struct kthread_worker *worker,
 				unsigned long delay)
 {
 	struct kthread_work *work = &dwork->work;
+	DEFINE_WAKE_Q(wake_q);
 	unsigned long flags;
 	bool ret = false;
 
 	raw_spin_lock_irqsave(&worker->lock, flags);
 
 	if (!queuing_blocked(worker, work)) {
-		__kthread_queue_delayed_work(worker, dwork, delay);
+		__kthread_queue_delayed_work(worker, dwork, delay, &wake_q);
 		ret = true;
 	}
 
 	raw_spin_unlock_irqrestore(&worker->lock, flags);
+
+	wake_up_q(&wake_q);
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(kthread_queue_delayed_work);
@@ -967,6 +980,7 @@ void kthread_flush_work(struct kthread_work *work)
 		KTHREAD_WORK_INIT(fwork.work, kthread_flush_work_fn),
 		COMPLETION_INITIALIZER_ONSTACK(fwork.done),
 	};
+	DEFINE_WAKE_Q(wake_q);
 	struct kthread_worker *worker;
 	bool noop = false;
 
@@ -979,15 +993,17 @@ void kthread_flush_work(struct kthread_work *work)
 	WARN_ON_ONCE(work->worker != worker);
 
 	if (!list_empty(&work->node))
-		kthread_insert_work(worker, &fwork.work, work->node.next);
+		kthread_insert_work(worker, &fwork.work, work->node.next, &wake_q);
 	else if (worker->current_work == work)
 		kthread_insert_work(worker, &fwork.work,
-				    worker->work_list.next);
+				    worker->work_list.next, &wake_q);
 	else
 		noop = true;
 
 	raw_spin_unlock_irq(&worker->lock);
 
+	wake_up_q(&wake_q);
+
 	if (!noop)
 		wait_for_completion(&fwork.done);
 }
@@ -1065,6 +1081,7 @@ bool kthread_mod_delayed_work(struct kthread_worker *worker,
 			      unsigned long delay)
 {
 	struct kthread_work *work = &dwork->work;
+	DEFINE_WAKE_Q(wake_q);
 	unsigned long flags;
 	int ret = false;
 
@@ -1083,9 +1100,12 @@ bool kthread_mod_delayed_work(struct kthread_worker *worker,
 
 	ret = __kthread_cancel_work(work, true, &flags);
 fast_queue:
-	__kthread_queue_delayed_work(worker, dwork, delay);
+	__kthread_queue_delayed_work(worker, dwork, delay, &wake_q);
 out:
 	raw_spin_unlock_irqrestore(&worker->lock, flags);
+
+	wake_up_q(&wake_q);
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(kthread_mod_delayed_work);


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: lockdep warning about possible circular dependency in PSI
  2020-04-24 17:40   ` Peter Zijlstra
@ 2020-04-24 17:52     ` Suren Baghdasaryan
  2020-04-24 20:53       ` Shakeel Butt
  0 siblings, 1 reply; 7+ messages in thread
From: Suren Baghdasaryan @ 2020-04-24 17:52 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Ingo Molnar, Andrew Morton, will, Johannes Weiner, Shakeel Butt,
	LKML, kernel-team

On Fri, Apr 24, 2020 at 10:40 AM Peter Zijlstra <peterz@infradead.org> wrote:
>
> On Fri, Apr 24, 2020 at 09:34:42AM -0700, Suren Baghdasaryan wrote:
> > Sorry to bother you again folks. Any suggestions on how to silence
> > this lockdep warning which I believe to be a false positive?
> >
> > On Wed, Apr 15, 2020 at 4:01 PM Suren Baghdasaryan <surenb@google.com> wrote:
> > >
> > > I received a report about possible circular locking dependency warning
> > > generated from PSI polling code. I think we are protected from this
> > > scenario by poll_scheduled atomic but wanted to double-check and I’m
> > > looking for an advice on how to annotate this case to fix the lockdep
> > > warning. I copied the detailed information at the end of this email
> > > but the short story is this:
> > >
> > > "WARNING: possible circular locking dependency detected" is generated
> > > with CONFIG_PSI and CONFIG_LOCKDEP enabled. The dependency chain it
> > > describes is:
> > >
> > > #0
> > > kthread_delayed_work_timer_fn()
> > >  |
> > > worker->lock
> > >  |
> > > try_to_wake_up()
> > >  |
> > > p->pi_lock
> > >
> > > #1
> > > sched_fork()
> > >  |
> > > p->pi_lock
> > >  |
> > > task_fork_fair()
> > >  |
> > > rq->lock
> > >
> > > #2
> > > psi_memstall_enter
> > >  |
> > > rq->lock
> > >  |
> > > kthread_queue_delayed_work()
> > >  |
> > > worker->lock
>
> Irrespective of it actually being a deadlock or not, it is fairly
> fragile. Ideally we'd fix #2, we really should minimize the number of
> locks nested under rq->lock.
>
> That said, here's the easy fix, which breaks #0.
>

Thanks for the suggestion, Peter. Let me digest this and will post a
patch with your Suggested-by.
Cheers!

> ---
> diff --git a/kernel/kthread.c b/kernel/kthread.c
> index bfbfa481be3a..b443bba7dd21 100644
> --- a/kernel/kthread.c
> +++ b/kernel/kthread.c
> @@ -806,14 +806,15 @@ static void kthread_insert_work_sanity_check(struct kthread_worker *worker,
>  /* insert @work before @pos in @worker */
>  static void kthread_insert_work(struct kthread_worker *worker,
>                                 struct kthread_work *work,
> -                               struct list_head *pos)
> +                               struct list_head *pos,
> +                               struct wake_q_head *wake_q)
>  {
>         kthread_insert_work_sanity_check(worker, work);
>
>         list_add_tail(&work->node, pos);
>         work->worker = worker;
>         if (!worker->current_work && likely(worker->task))
> -               wake_up_process(worker->task);
> +               wake_q_add(wake_q, worker->task);
>  }
>
>  /**
> @@ -831,15 +832,19 @@ static void kthread_insert_work(struct kthread_worker *worker,
>  bool kthread_queue_work(struct kthread_worker *worker,
>                         struct kthread_work *work)
>  {
> -       bool ret = false;
> +       DEFINE_WAKE_Q(wake_q);
>         unsigned long flags;
> +       bool ret = false;
>
>         raw_spin_lock_irqsave(&worker->lock, flags);
>         if (!queuing_blocked(worker, work)) {
> -               kthread_insert_work(worker, work, &worker->work_list);
> +               kthread_insert_work(worker, work, &worker->work_list, &wake_q);
>                 ret = true;
>         }
>         raw_spin_unlock_irqrestore(&worker->lock, flags);
> +
> +       wake_up_q(&wake_q);
> +
>         return ret;
>  }
>  EXPORT_SYMBOL_GPL(kthread_queue_work);
> @@ -857,6 +862,7 @@ void kthread_delayed_work_timer_fn(struct timer_list *t)
>         struct kthread_delayed_work *dwork = from_timer(dwork, t, timer);
>         struct kthread_work *work = &dwork->work;
>         struct kthread_worker *worker = work->worker;
> +       DEFINE_WAKE_Q(wake_q);
>         unsigned long flags;
>
>         /*
> @@ -873,15 +879,18 @@ void kthread_delayed_work_timer_fn(struct timer_list *t)
>         /* Move the work from worker->delayed_work_list. */
>         WARN_ON_ONCE(list_empty(&work->node));
>         list_del_init(&work->node);
> -       kthread_insert_work(worker, work, &worker->work_list);
> +       kthread_insert_work(worker, work, &worker->work_list, &wake_q);
>
>         raw_spin_unlock_irqrestore(&worker->lock, flags);
> +
> +       wake_up_q(&wake_q);
>  }
>  EXPORT_SYMBOL(kthread_delayed_work_timer_fn);
>
>  static void __kthread_queue_delayed_work(struct kthread_worker *worker,
>                                          struct kthread_delayed_work *dwork,
> -                                        unsigned long delay)
> +                                        unsigned long delay,
> +                                        struct wake_q_head *wake_q)
>  {
>         struct timer_list *timer = &dwork->timer;
>         struct kthread_work *work = &dwork->work;
> @@ -895,7 +904,7 @@ static void __kthread_queue_delayed_work(struct kthread_worker *worker,
>          * on that there's no such delay when @delay is 0.
>          */
>         if (!delay) {
> -               kthread_insert_work(worker, work, &worker->work_list);
> +               kthread_insert_work(worker, work, &worker->work_list, wake_q);
>                 return;
>         }
>
> @@ -928,17 +937,21 @@ bool kthread_queue_delayed_work(struct kthread_worker *worker,
>                                 unsigned long delay)
>  {
>         struct kthread_work *work = &dwork->work;
> +       DEFINE_WAKE_Q(wake_q);
>         unsigned long flags;
>         bool ret = false;
>
>         raw_spin_lock_irqsave(&worker->lock, flags);
>
>         if (!queuing_blocked(worker, work)) {
> -               __kthread_queue_delayed_work(worker, dwork, delay);
> +               __kthread_queue_delayed_work(worker, dwork, delay, &wake_q);
>                 ret = true;
>         }
>
>         raw_spin_unlock_irqrestore(&worker->lock, flags);
> +
> +       wake_up_q(&wake_q);
> +
>         return ret;
>  }
>  EXPORT_SYMBOL_GPL(kthread_queue_delayed_work);
> @@ -967,6 +980,7 @@ void kthread_flush_work(struct kthread_work *work)
>                 KTHREAD_WORK_INIT(fwork.work, kthread_flush_work_fn),
>                 COMPLETION_INITIALIZER_ONSTACK(fwork.done),
>         };
> +       DEFINE_WAKE_Q(wake_q);
>         struct kthread_worker *worker;
>         bool noop = false;
>
> @@ -979,15 +993,17 @@ void kthread_flush_work(struct kthread_work *work)
>         WARN_ON_ONCE(work->worker != worker);
>
>         if (!list_empty(&work->node))
> -               kthread_insert_work(worker, &fwork.work, work->node.next);
> +               kthread_insert_work(worker, &fwork.work, work->node.next, &wake_q);
>         else if (worker->current_work == work)
>                 kthread_insert_work(worker, &fwork.work,
> -                                   worker->work_list.next);
> +                                   worker->work_list.next, &wake_q);
>         else
>                 noop = true;
>
>         raw_spin_unlock_irq(&worker->lock);
>
> +       wake_up_q(&wake_q);
> +
>         if (!noop)
>                 wait_for_completion(&fwork.done);
>  }
> @@ -1065,6 +1081,7 @@ bool kthread_mod_delayed_work(struct kthread_worker *worker,
>                               unsigned long delay)
>  {
>         struct kthread_work *work = &dwork->work;
> +       DEFINE_WAKE_Q(wake_q);
>         unsigned long flags;
>         int ret = false;
>
> @@ -1083,9 +1100,12 @@ bool kthread_mod_delayed_work(struct kthread_worker *worker,
>
>         ret = __kthread_cancel_work(work, true, &flags);
>  fast_queue:
> -       __kthread_queue_delayed_work(worker, dwork, delay);
> +       __kthread_queue_delayed_work(worker, dwork, delay, &wake_q);
>  out:
>         raw_spin_unlock_irqrestore(&worker->lock, flags);
> +
> +       wake_up_q(&wake_q);
> +
>         return ret;
>  }
>  EXPORT_SYMBOL_GPL(kthread_mod_delayed_work);
>
> --
> To unsubscribe from this group and stop receiving emails from it, send an email to kernel-team+unsubscribe@android.com.
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: lockdep warning about possible circular dependency in PSI
  2020-04-24 17:52     ` Suren Baghdasaryan
@ 2020-04-24 20:53       ` Shakeel Butt
  2020-04-27  0:00         ` Suren Baghdasaryan
  0 siblings, 1 reply; 7+ messages in thread
From: Shakeel Butt @ 2020-04-24 20:53 UTC (permalink / raw)
  To: Suren Baghdasaryan
  Cc: Peter Zijlstra, Ingo Molnar, Andrew Morton, will,
	Johannes Weiner, LKML, kernel-team

On Fri, Apr 24, 2020 at 10:52 AM Suren Baghdasaryan <surenb@google.com> wrote:
>
> On Fri, Apr 24, 2020 at 10:40 AM Peter Zijlstra <peterz@infradead.org> wrote:
> >
> > On Fri, Apr 24, 2020 at 09:34:42AM -0700, Suren Baghdasaryan wrote:
> > > Sorry to bother you again folks. Any suggestions on how to silence
> > > this lockdep warning which I believe to be a false positive?
> > >
> > > On Wed, Apr 15, 2020 at 4:01 PM Suren Baghdasaryan <surenb@google.com> wrote:
> > > >
> > > > I received a report about possible circular locking dependency warning
> > > > generated from PSI polling code. I think we are protected from this
> > > > scenario by poll_scheduled atomic but wanted to double-check and I’m
> > > > looking for an advice on how to annotate this case to fix the lockdep
> > > > warning. I copied the detailed information at the end of this email
> > > > but the short story is this:
> > > >
> > > > "WARNING: possible circular locking dependency detected" is generated
> > > > with CONFIG_PSI and CONFIG_LOCKDEP enabled. The dependency chain it
> > > > describes is:
> > > >
> > > > #0
> > > > kthread_delayed_work_timer_fn()
> > > >  |
> > > > worker->lock
> > > >  |
> > > > try_to_wake_up()
> > > >  |
> > > > p->pi_lock
> > > >
> > > > #1
> > > > sched_fork()
> > > >  |
> > > > p->pi_lock
> > > >  |
> > > > task_fork_fair()
> > > >  |
> > > > rq->lock
> > > >
> > > > #2
> > > > psi_memstall_enter
> > > >  |
> > > > rq->lock
> > > >  |
> > > > kthread_queue_delayed_work()
> > > >  |
> > > > worker->lock
> >
> > Irrespective of it actually being a deadlock or not, it is fairly
> > fragile. Ideally we'd fix #2, we really should minimize the number of
> > locks nested under rq->lock.
> >
> > That said, here's the easy fix, which breaks #0.
> >
>
> Thanks for the suggestion, Peter. Let me digest this and will post a
> patch with your Suggested-by.
> Cheers!
>

I tested on my simple repro and the patch fixes the lockdep splat.

You can add
Tested-by: Shakeel Butt <shakeelb@google.com>

> > ---
> > diff --git a/kernel/kthread.c b/kernel/kthread.c
> > index bfbfa481be3a..b443bba7dd21 100644
> > --- a/kernel/kthread.c
> > +++ b/kernel/kthread.c
> > @@ -806,14 +806,15 @@ static void kthread_insert_work_sanity_check(struct kthread_worker *worker,
> >  /* insert @work before @pos in @worker */
> >  static void kthread_insert_work(struct kthread_worker *worker,
> >                                 struct kthread_work *work,
> > -                               struct list_head *pos)
> > +                               struct list_head *pos,
> > +                               struct wake_q_head *wake_q)
> >  {
> >         kthread_insert_work_sanity_check(worker, work);
> >
> >         list_add_tail(&work->node, pos);
> >         work->worker = worker;
> >         if (!worker->current_work && likely(worker->task))
> > -               wake_up_process(worker->task);
> > +               wake_q_add(wake_q, worker->task);
> >  }
> >
> >  /**
> > @@ -831,15 +832,19 @@ static void kthread_insert_work(struct kthread_worker *worker,
> >  bool kthread_queue_work(struct kthread_worker *worker,
> >                         struct kthread_work *work)
> >  {
> > -       bool ret = false;
> > +       DEFINE_WAKE_Q(wake_q);
> >         unsigned long flags;
> > +       bool ret = false;
> >
> >         raw_spin_lock_irqsave(&worker->lock, flags);
> >         if (!queuing_blocked(worker, work)) {
> > -               kthread_insert_work(worker, work, &worker->work_list);
> > +               kthread_insert_work(worker, work, &worker->work_list, &wake_q);
> >                 ret = true;
> >         }
> >         raw_spin_unlock_irqrestore(&worker->lock, flags);
> > +
> > +       wake_up_q(&wake_q);
> > +
> >         return ret;
> >  }
> >  EXPORT_SYMBOL_GPL(kthread_queue_work);
> > @@ -857,6 +862,7 @@ void kthread_delayed_work_timer_fn(struct timer_list *t)
> >         struct kthread_delayed_work *dwork = from_timer(dwork, t, timer);
> >         struct kthread_work *work = &dwork->work;
> >         struct kthread_worker *worker = work->worker;
> > +       DEFINE_WAKE_Q(wake_q);
> >         unsigned long flags;
> >
> >         /*
> > @@ -873,15 +879,18 @@ void kthread_delayed_work_timer_fn(struct timer_list *t)
> >         /* Move the work from worker->delayed_work_list. */
> >         WARN_ON_ONCE(list_empty(&work->node));
> >         list_del_init(&work->node);
> > -       kthread_insert_work(worker, work, &worker->work_list);
> > +       kthread_insert_work(worker, work, &worker->work_list, &wake_q);
> >
> >         raw_spin_unlock_irqrestore(&worker->lock, flags);
> > +
> > +       wake_up_q(&wake_q);
> >  }
> >  EXPORT_SYMBOL(kthread_delayed_work_timer_fn);
> >
> >  static void __kthread_queue_delayed_work(struct kthread_worker *worker,
> >                                          struct kthread_delayed_work *dwork,
> > -                                        unsigned long delay)
> > +                                        unsigned long delay,
> > +                                        struct wake_q_head *wake_q)
> >  {
> >         struct timer_list *timer = &dwork->timer;
> >         struct kthread_work *work = &dwork->work;
> > @@ -895,7 +904,7 @@ static void __kthread_queue_delayed_work(struct kthread_worker *worker,
> >          * on that there's no such delay when @delay is 0.
> >          */
> >         if (!delay) {
> > -               kthread_insert_work(worker, work, &worker->work_list);
> > +               kthread_insert_work(worker, work, &worker->work_list, wake_q);
> >                 return;
> >         }
> >
> > @@ -928,17 +937,21 @@ bool kthread_queue_delayed_work(struct kthread_worker *worker,
> >                                 unsigned long delay)
> >  {
> >         struct kthread_work *work = &dwork->work;
> > +       DEFINE_WAKE_Q(wake_q);
> >         unsigned long flags;
> >         bool ret = false;
> >
> >         raw_spin_lock_irqsave(&worker->lock, flags);
> >
> >         if (!queuing_blocked(worker, work)) {
> > -               __kthread_queue_delayed_work(worker, dwork, delay);
> > +               __kthread_queue_delayed_work(worker, dwork, delay, &wake_q);
> >                 ret = true;
> >         }
> >
> >         raw_spin_unlock_irqrestore(&worker->lock, flags);
> > +
> > +       wake_up_q(&wake_q);
> > +
> >         return ret;
> >  }
> >  EXPORT_SYMBOL_GPL(kthread_queue_delayed_work);
> > @@ -967,6 +980,7 @@ void kthread_flush_work(struct kthread_work *work)
> >                 KTHREAD_WORK_INIT(fwork.work, kthread_flush_work_fn),
> >                 COMPLETION_INITIALIZER_ONSTACK(fwork.done),
> >         };
> > +       DEFINE_WAKE_Q(wake_q);
> >         struct kthread_worker *worker;
> >         bool noop = false;
> >
> > @@ -979,15 +993,17 @@ void kthread_flush_work(struct kthread_work *work)
> >         WARN_ON_ONCE(work->worker != worker);
> >
> >         if (!list_empty(&work->node))
> > -               kthread_insert_work(worker, &fwork.work, work->node.next);
> > +               kthread_insert_work(worker, &fwork.work, work->node.next, &wake_q);
> >         else if (worker->current_work == work)
> >                 kthread_insert_work(worker, &fwork.work,
> > -                                   worker->work_list.next);
> > +                                   worker->work_list.next, &wake_q);
> >         else
> >                 noop = true;
> >
> >         raw_spin_unlock_irq(&worker->lock);
> >
> > +       wake_up_q(&wake_q);
> > +
> >         if (!noop)
> >                 wait_for_completion(&fwork.done);
> >  }
> > @@ -1065,6 +1081,7 @@ bool kthread_mod_delayed_work(struct kthread_worker *worker,
> >                               unsigned long delay)
> >  {
> >         struct kthread_work *work = &dwork->work;
> > +       DEFINE_WAKE_Q(wake_q);
> >         unsigned long flags;
> >         int ret = false;
> >
> > @@ -1083,9 +1100,12 @@ bool kthread_mod_delayed_work(struct kthread_worker *worker,
> >
> >         ret = __kthread_cancel_work(work, true, &flags);
> >  fast_queue:
> > -       __kthread_queue_delayed_work(worker, dwork, delay);
> > +       __kthread_queue_delayed_work(worker, dwork, delay, &wake_q);
> >  out:
> >         raw_spin_unlock_irqrestore(&worker->lock, flags);
> > +
> > +       wake_up_q(&wake_q);
> > +
> >         return ret;
> >  }
> >  EXPORT_SYMBOL_GPL(kthread_mod_delayed_work);
> >
> > --
> > To unsubscribe from this group and stop receiving emails from it, send an email to kernel-team+unsubscribe@android.com.
> >

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: lockdep warning about possible circular dependency in PSI
  2020-04-24 20:53       ` Shakeel Butt
@ 2020-04-27  0:00         ` Suren Baghdasaryan
  2020-04-27 18:47           ` Suren Baghdasaryan
  0 siblings, 1 reply; 7+ messages in thread
From: Suren Baghdasaryan @ 2020-04-27  0:00 UTC (permalink / raw)
  To: Shakeel Butt
  Cc: Peter Zijlstra, Ingo Molnar, Andrew Morton, will,
	Johannes Weiner, LKML, kernel-team

On Fri, Apr 24, 2020 at 1:54 PM Shakeel Butt <shakeelb@google.com> wrote:
>
> On Fri, Apr 24, 2020 at 10:52 AM Suren Baghdasaryan <surenb@google.com> wrote:
> >
> > On Fri, Apr 24, 2020 at 10:40 AM Peter Zijlstra <peterz@infradead.org> wrote:
> > >
> > > On Fri, Apr 24, 2020 at 09:34:42AM -0700, Suren Baghdasaryan wrote:
> > > > Sorry to bother you again folks. Any suggestions on how to silence
> > > > this lockdep warning which I believe to be a false positive?
> > > >
> > > > On Wed, Apr 15, 2020 at 4:01 PM Suren Baghdasaryan <surenb@google.com> wrote:
> > > > >
> > > > > I received a report about possible circular locking dependency warning
> > > > > generated from PSI polling code. I think we are protected from this
> > > > > scenario by poll_scheduled atomic but wanted to double-check and I’m
> > > > > looking for an advice on how to annotate this case to fix the lockdep
> > > > > warning. I copied the detailed information at the end of this email
> > > > > but the short story is this:
> > > > >
> > > > > "WARNING: possible circular locking dependency detected" is generated
> > > > > with CONFIG_PSI and CONFIG_LOCKDEP enabled. The dependency chain it
> > > > > describes is:
> > > > >
> > > > > #0
> > > > > kthread_delayed_work_timer_fn()
> > > > >  |
> > > > > worker->lock
> > > > >  |
> > > > > try_to_wake_up()
> > > > >  |
> > > > > p->pi_lock
> > > > >
> > > > > #1
> > > > > sched_fork()
> > > > >  |
> > > > > p->pi_lock
> > > > >  |
> > > > > task_fork_fair()
> > > > >  |
> > > > > rq->lock
> > > > >
> > > > > #2
> > > > > psi_memstall_enter
> > > > >  |
> > > > > rq->lock
> > > > >  |
> > > > > kthread_queue_delayed_work()
> > > > >  |
> > > > > worker->lock
> > >
> > > Irrespective of it actually being a deadlock or not, it is fairly
> > > fragile. Ideally we'd fix #2, we really should minimize the number of
> > > locks nested under rq->lock.
> > >
> > > That said, here's the easy fix, which breaks #0.
> > >
> >
> > Thanks for the suggestion, Peter. Let me digest this and will post a
> > patch with your Suggested-by.
> > Cheers!
> >
>
> I tested on my simple repro and the patch fixes the lockdep splat.
>
> You can add
> Tested-by: Shakeel Butt <shakeelb@google.com>
>

Thanks Shakeel! Will do.

> > > ---
> > > diff --git a/kernel/kthread.c b/kernel/kthread.c
> > > index bfbfa481be3a..b443bba7dd21 100644
> > > --- a/kernel/kthread.c
> > > +++ b/kernel/kthread.c
> > > @@ -806,14 +806,15 @@ static void kthread_insert_work_sanity_check(struct kthread_worker *worker,
> > >  /* insert @work before @pos in @worker */
> > >  static void kthread_insert_work(struct kthread_worker *worker,
> > >                                 struct kthread_work *work,
> > > -                               struct list_head *pos)
> > > +                               struct list_head *pos,
> > > +                               struct wake_q_head *wake_q)
> > >  {
> > >         kthread_insert_work_sanity_check(worker, work);
> > >
> > >         list_add_tail(&work->node, pos);
> > >         work->worker = worker;
> > >         if (!worker->current_work && likely(worker->task))
> > > -               wake_up_process(worker->task);
> > > +               wake_q_add(wake_q, worker->task);
> > >  }
> > >
> > >  /**
> > > @@ -831,15 +832,19 @@ static void kthread_insert_work(struct kthread_worker *worker,
> > >  bool kthread_queue_work(struct kthread_worker *worker,
> > >                         struct kthread_work *work)
> > >  {
> > > -       bool ret = false;
> > > +       DEFINE_WAKE_Q(wake_q);
> > >         unsigned long flags;
> > > +       bool ret = false;
> > >
> > >         raw_spin_lock_irqsave(&worker->lock, flags);
> > >         if (!queuing_blocked(worker, work)) {
> > > -               kthread_insert_work(worker, work, &worker->work_list);
> > > +               kthread_insert_work(worker, work, &worker->work_list, &wake_q);
> > >                 ret = true;
> > >         }
> > >         raw_spin_unlock_irqrestore(&worker->lock, flags);
> > > +
> > > +       wake_up_q(&wake_q);
> > > +
> > >         return ret;
> > >  }
> > >  EXPORT_SYMBOL_GPL(kthread_queue_work);
> > > @@ -857,6 +862,7 @@ void kthread_delayed_work_timer_fn(struct timer_list *t)
> > >         struct kthread_delayed_work *dwork = from_timer(dwork, t, timer);
> > >         struct kthread_work *work = &dwork->work;
> > >         struct kthread_worker *worker = work->worker;
> > > +       DEFINE_WAKE_Q(wake_q);
> > >         unsigned long flags;
> > >
> > >         /*
> > > @@ -873,15 +879,18 @@ void kthread_delayed_work_timer_fn(struct timer_list *t)
> > >         /* Move the work from worker->delayed_work_list. */
> > >         WARN_ON_ONCE(list_empty(&work->node));
> > >         list_del_init(&work->node);
> > > -       kthread_insert_work(worker, work, &worker->work_list);
> > > +       kthread_insert_work(worker, work, &worker->work_list, &wake_q);
> > >
> > >         raw_spin_unlock_irqrestore(&worker->lock, flags);
> > > +
> > > +       wake_up_q(&wake_q);
> > >  }
> > >  EXPORT_SYMBOL(kthread_delayed_work_timer_fn);
> > >
> > >  static void __kthread_queue_delayed_work(struct kthread_worker *worker,
> > >                                          struct kthread_delayed_work *dwork,
> > > -                                        unsigned long delay)
> > > +                                        unsigned long delay,
> > > +                                        struct wake_q_head *wake_q)
> > >  {
> > >         struct timer_list *timer = &dwork->timer;
> > >         struct kthread_work *work = &dwork->work;
> > > @@ -895,7 +904,7 @@ static void __kthread_queue_delayed_work(struct kthread_worker *worker,
> > >          * on that there's no such delay when @delay is 0.
> > >          */
> > >         if (!delay) {
> > > -               kthread_insert_work(worker, work, &worker->work_list);
> > > +               kthread_insert_work(worker, work, &worker->work_list, wake_q);
> > >                 return;
> > >         }
> > >
> > > @@ -928,17 +937,21 @@ bool kthread_queue_delayed_work(struct kthread_worker *worker,
> > >                                 unsigned long delay)
> > >  {
> > >         struct kthread_work *work = &dwork->work;
> > > +       DEFINE_WAKE_Q(wake_q);
> > >         unsigned long flags;
> > >         bool ret = false;
> > >
> > >         raw_spin_lock_irqsave(&worker->lock, flags);
> > >
> > >         if (!queuing_blocked(worker, work)) {
> > > -               __kthread_queue_delayed_work(worker, dwork, delay);
> > > +               __kthread_queue_delayed_work(worker, dwork, delay, &wake_q);
> > >                 ret = true;
> > >         }
> > >
> > >         raw_spin_unlock_irqrestore(&worker->lock, flags);
> > > +
> > > +       wake_up_q(&wake_q);
> > > +
> > >         return ret;
> > >  }
> > >  EXPORT_SYMBOL_GPL(kthread_queue_delayed_work);
> > > @@ -967,6 +980,7 @@ void kthread_flush_work(struct kthread_work *work)
> > >                 KTHREAD_WORK_INIT(fwork.work, kthread_flush_work_fn),
> > >                 COMPLETION_INITIALIZER_ONSTACK(fwork.done),
> > >         };
> > > +       DEFINE_WAKE_Q(wake_q);
> > >         struct kthread_worker *worker;
> > >         bool noop = false;
> > >
> > > @@ -979,15 +993,17 @@ void kthread_flush_work(struct kthread_work *work)
> > >         WARN_ON_ONCE(work->worker != worker);
> > >
> > >         if (!list_empty(&work->node))
> > > -               kthread_insert_work(worker, &fwork.work, work->node.next);
> > > +               kthread_insert_work(worker, &fwork.work, work->node.next, &wake_q);
> > >         else if (worker->current_work == work)
> > >                 kthread_insert_work(worker, &fwork.work,
> > > -                                   worker->work_list.next);
> > > +                                   worker->work_list.next, &wake_q);
> > >         else
> > >                 noop = true;
> > >
> > >         raw_spin_unlock_irq(&worker->lock);
> > >
> > > +       wake_up_q(&wake_q);
> > > +
> > >         if (!noop)
> > >                 wait_for_completion(&fwork.done);
> > >  }
> > > @@ -1065,6 +1081,7 @@ bool kthread_mod_delayed_work(struct kthread_worker *worker,
> > >                               unsigned long delay)
> > >  {
> > >         struct kthread_work *work = &dwork->work;
> > > +       DEFINE_WAKE_Q(wake_q);
> > >         unsigned long flags;
> > >         int ret = false;
> > >
> > > @@ -1083,9 +1100,12 @@ bool kthread_mod_delayed_work(struct kthread_worker *worker,
> > >
> > >         ret = __kthread_cancel_work(work, true, &flags);
> > >  fast_queue:
> > > -       __kthread_queue_delayed_work(worker, dwork, delay);
> > > +       __kthread_queue_delayed_work(worker, dwork, delay, &wake_q);
> > >  out:
> > >         raw_spin_unlock_irqrestore(&worker->lock, flags);
> > > +
> > > +       wake_up_q(&wake_q);
> > > +
> > >         return ret;
> > >  }
> > >  EXPORT_SYMBOL_GPL(kthread_mod_delayed_work);
> > >
> > > --
> > > To unsubscribe from this group and stop receiving emails from it, send an email to kernel-team+unsubscribe@android.com.
> > >

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: lockdep warning about possible circular dependency in PSI
  2020-04-27  0:00         ` Suren Baghdasaryan
@ 2020-04-27 18:47           ` Suren Baghdasaryan
  0 siblings, 0 replies; 7+ messages in thread
From: Suren Baghdasaryan @ 2020-04-27 18:47 UTC (permalink / raw)
  To: Shakeel Butt
  Cc: Peter Zijlstra, Ingo Molnar, Andrew Morton, will,
	Johannes Weiner, LKML, kernel-team

On Sun, Apr 26, 2020 at 5:00 PM Suren Baghdasaryan <surenb@google.com> wrote:
>
> On Fri, Apr 24, 2020 at 1:54 PM Shakeel Butt <shakeelb@google.com> wrote:
> >
> > On Fri, Apr 24, 2020 at 10:52 AM Suren Baghdasaryan <surenb@google.com> wrote:
> > >
> > > On Fri, Apr 24, 2020 at 10:40 AM Peter Zijlstra <peterz@infradead.org> wrote:
> > > >
> > > > On Fri, Apr 24, 2020 at 09:34:42AM -0700, Suren Baghdasaryan wrote:
> > > > > Sorry to bother you again folks. Any suggestions on how to silence
> > > > > this lockdep warning which I believe to be a false positive?
> > > > >
> > > > > On Wed, Apr 15, 2020 at 4:01 PM Suren Baghdasaryan <surenb@google.com> wrote:
> > > > > >
> > > > > > I received a report about possible circular locking dependency warning
> > > > > > generated from PSI polling code. I think we are protected from this
> > > > > > scenario by poll_scheduled atomic but wanted to double-check and I’m
> > > > > > looking for an advice on how to annotate this case to fix the lockdep
> > > > > > warning. I copied the detailed information at the end of this email
> > > > > > but the short story is this:
> > > > > >
> > > > > > "WARNING: possible circular locking dependency detected" is generated
> > > > > > with CONFIG_PSI and CONFIG_LOCKDEP enabled. The dependency chain it
> > > > > > describes is:
> > > > > >
> > > > > > #0
> > > > > > kthread_delayed_work_timer_fn()
> > > > > >  |
> > > > > > worker->lock
> > > > > >  |
> > > > > > try_to_wake_up()
> > > > > >  |
> > > > > > p->pi_lock
> > > > > >
> > > > > > #1
> > > > > > sched_fork()
> > > > > >  |
> > > > > > p->pi_lock
> > > > > >  |
> > > > > > task_fork_fair()
> > > > > >  |
> > > > > > rq->lock
> > > > > >
> > > > > > #2
> > > > > > psi_memstall_enter
> > > > > >  |
> > > > > > rq->lock
> > > > > >  |
> > > > > > kthread_queue_delayed_work()
> > > > > >  |
> > > > > > worker->lock
> > > >
> > > > Irrespective of it actually being a deadlock or not, it is fairly
> > > > fragile. Ideally we'd fix #2, we really should minimize the number of
> > > > locks nested under rq->lock.
> > > >
> > > > That said, here's the easy fix, which breaks #0.
> > > >
> > >
> > > Thanks for the suggestion, Peter. Let me digest this and will post a
> > > patch with your Suggested-by.
> > > Cheers!
> > >
> >
> > I tested on my simple repro and the patch fixes the lockdep splat.
> >
> > You can add
> > Tested-by: Shakeel Butt <shakeelb@google.com>
> >
>
> Thanks Shakeel! Will do.
>
> > > > ---
> > > > diff --git a/kernel/kthread.c b/kernel/kthread.c
> > > > index bfbfa481be3a..b443bba7dd21 100644
> > > > --- a/kernel/kthread.c
> > > > +++ b/kernel/kthread.c
> > > > @@ -806,14 +806,15 @@ static void kthread_insert_work_sanity_check(struct kthread_worker *worker,
> > > >  /* insert @work before @pos in @worker */
> > > >  static void kthread_insert_work(struct kthread_worker *worker,
> > > >                                 struct kthread_work *work,
> > > > -                               struct list_head *pos)
> > > > +                               struct list_head *pos,
> > > > +                               struct wake_q_head *wake_q)
> > > >  {
> > > >         kthread_insert_work_sanity_check(worker, work);
> > > >
> > > >         list_add_tail(&work->node, pos);
> > > >         work->worker = worker;
> > > >         if (!worker->current_work && likely(worker->task))
> > > > -               wake_up_process(worker->task);
> > > > +               wake_q_add(wake_q, worker->task);
> > > >  }
> > > >
> > > >  /**
> > > > @@ -831,15 +832,19 @@ static void kthread_insert_work(struct kthread_worker *worker,
> > > >  bool kthread_queue_work(struct kthread_worker *worker,
> > > >                         struct kthread_work *work)
> > > >  {
> > > > -       bool ret = false;
> > > > +       DEFINE_WAKE_Q(wake_q);
> > > >         unsigned long flags;
> > > > +       bool ret = false;
> > > >
> > > >         raw_spin_lock_irqsave(&worker->lock, flags);
> > > >         if (!queuing_blocked(worker, work)) {
> > > > -               kthread_insert_work(worker, work, &worker->work_list);
> > > > +               kthread_insert_work(worker, work, &worker->work_list, &wake_q);
> > > >                 ret = true;
> > > >         }
> > > >         raw_spin_unlock_irqrestore(&worker->lock, flags);
> > > > +
> > > > +       wake_up_q(&wake_q);
> > > > +
> > > >         return ret;
> > > >  }
> > > >  EXPORT_SYMBOL_GPL(kthread_queue_work);
> > > > @@ -857,6 +862,7 @@ void kthread_delayed_work_timer_fn(struct timer_list *t)
> > > >         struct kthread_delayed_work *dwork = from_timer(dwork, t, timer);
> > > >         struct kthread_work *work = &dwork->work;
> > > >         struct kthread_worker *worker = work->worker;
> > > > +       DEFINE_WAKE_Q(wake_q);
> > > >         unsigned long flags;
> > > >
> > > >         /*
> > > > @@ -873,15 +879,18 @@ void kthread_delayed_work_timer_fn(struct timer_list *t)
> > > >         /* Move the work from worker->delayed_work_list. */
> > > >         WARN_ON_ONCE(list_empty(&work->node));
> > > >         list_del_init(&work->node);
> > > > -       kthread_insert_work(worker, work, &worker->work_list);
> > > > +       kthread_insert_work(worker, work, &worker->work_list, &wake_q);
> > > >
> > > >         raw_spin_unlock_irqrestore(&worker->lock, flags);
> > > > +
> > > > +       wake_up_q(&wake_q);
> > > >  }
> > > >  EXPORT_SYMBOL(kthread_delayed_work_timer_fn);
> > > >
> > > >  static void __kthread_queue_delayed_work(struct kthread_worker *worker,
> > > >                                          struct kthread_delayed_work *dwork,
> > > > -                                        unsigned long delay)
> > > > +                                        unsigned long delay,
> > > > +                                        struct wake_q_head *wake_q)
> > > >  {
> > > >         struct timer_list *timer = &dwork->timer;
> > > >         struct kthread_work *work = &dwork->work;
> > > > @@ -895,7 +904,7 @@ static void __kthread_queue_delayed_work(struct kthread_worker *worker,
> > > >          * on that there's no such delay when @delay is 0.
> > > >          */
> > > >         if (!delay) {
> > > > -               kthread_insert_work(worker, work, &worker->work_list);
> > > > +               kthread_insert_work(worker, work, &worker->work_list, wake_q);
> > > >                 return;
> > > >         }
> > > >
> > > > @@ -928,17 +937,21 @@ bool kthread_queue_delayed_work(struct kthread_worker *worker,
> > > >                                 unsigned long delay)
> > > >  {
> > > >         struct kthread_work *work = &dwork->work;
> > > > +       DEFINE_WAKE_Q(wake_q);
> > > >         unsigned long flags;
> > > >         bool ret = false;
> > > >
> > > >         raw_spin_lock_irqsave(&worker->lock, flags);
> > > >
> > > >         if (!queuing_blocked(worker, work)) {
> > > > -               __kthread_queue_delayed_work(worker, dwork, delay);
> > > > +               __kthread_queue_delayed_work(worker, dwork, delay, &wake_q);
> > > >                 ret = true;
> > > >         }
> > > >
> > > >         raw_spin_unlock_irqrestore(&worker->lock, flags);
> > > > +
> > > > +       wake_up_q(&wake_q);
> > > > +
> > > >         return ret;
> > > >  }
> > > >  EXPORT_SYMBOL_GPL(kthread_queue_delayed_work);
> > > > @@ -967,6 +980,7 @@ void kthread_flush_work(struct kthread_work *work)
> > > >                 KTHREAD_WORK_INIT(fwork.work, kthread_flush_work_fn),
> > > >                 COMPLETION_INITIALIZER_ONSTACK(fwork.done),
> > > >         };
> > > > +       DEFINE_WAKE_Q(wake_q);
> > > >         struct kthread_worker *worker;
> > > >         bool noop = false;
> > > >
> > > > @@ -979,15 +993,17 @@ void kthread_flush_work(struct kthread_work *work)
> > > >         WARN_ON_ONCE(work->worker != worker);
> > > >
> > > >         if (!list_empty(&work->node))
> > > > -               kthread_insert_work(worker, &fwork.work, work->node.next);
> > > > +               kthread_insert_work(worker, &fwork.work, work->node.next, &wake_q);
> > > >         else if (worker->current_work == work)
> > > >                 kthread_insert_work(worker, &fwork.work,
> > > > -                                   worker->work_list.next);
> > > > +                                   worker->work_list.next, &wake_q);
> > > >         else
> > > >                 noop = true;
> > > >
> > > >         raw_spin_unlock_irq(&worker->lock);
> > > >
> > > > +       wake_up_q(&wake_q);
> > > > +
> > > >         if (!noop)
> > > >                 wait_for_completion(&fwork.done);
> > > >  }
> > > > @@ -1065,6 +1081,7 @@ bool kthread_mod_delayed_work(struct kthread_worker *worker,
> > > >                               unsigned long delay)
> > > >  {
> > > >         struct kthread_work *work = &dwork->work;
> > > > +       DEFINE_WAKE_Q(wake_q);
> > > >         unsigned long flags;
> > > >         int ret = false;
> > > >
> > > > @@ -1083,9 +1100,12 @@ bool kthread_mod_delayed_work(struct kthread_worker *worker,
> > > >
> > > >         ret = __kthread_cancel_work(work, true, &flags);
> > > >  fast_queue:
> > > > -       __kthread_queue_delayed_work(worker, dwork, delay);
> > > > +       __kthread_queue_delayed_work(worker, dwork, delay, &wake_q);
> > > >  out:
> > > >         raw_spin_unlock_irqrestore(&worker->lock, flags);
> > > > +
> > > > +       wake_up_q(&wake_q);
> > > > +
> > > >         return ret;
> > > >  }
> > > >  EXPORT_SYMBOL_GPL(kthread_mod_delayed_work);
> > > >

Patch is posted at https://lkml.org/lkml/2020/4/27/985 . Had to
include linux/sched/wake_q.h and fix a long line but other than that
it's unchanged.
Thanks!

> > > > --
> > > > To unsubscribe from this group and stop receiving emails from it, send an email to kernel-team+unsubscribe@android.com.
> > > >

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-04-27 18:48 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-15 23:01 lockdep warning about possible circular dependency in PSI Suren Baghdasaryan
2020-04-24 16:34 ` Suren Baghdasaryan
2020-04-24 17:40   ` Peter Zijlstra
2020-04-24 17:52     ` Suren Baghdasaryan
2020-04-24 20:53       ` Shakeel Butt
2020-04-27  0:00         ` Suren Baghdasaryan
2020-04-27 18:47           ` Suren Baghdasaryan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).