From: Andrea Righi <andrea.righi@canonical.com>
To: Pavel Machek <pavel@ucw.cz>
Cc: Boqun Feng <boqun.feng@gmail.com>,
Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>, Will Deacon <will@kernel.org>,
linux-kernel@vger.kernel.org
Subject: Re: lockdep: possible irq lock inversion dependency detected (trig->leddev_list_lock)
Date: Mon, 2 Nov 2020 10:09:27 +0100 [thread overview]
Message-ID: <20201102090927.GC9930@xps-13-7390> (raw)
In-Reply-To: <20201102085658.GA5506@amd>
On Mon, Nov 02, 2020 at 09:56:58AM +0100, Pavel Machek wrote:
> Hi!
>
> > > > I'm getting the following lockdep splat (see below).
> > > >
> > > > Apparently this warning starts to be reported after applying:
> > > >
> > > > e918188611f0 ("locking: More accurate annotations for read_lock()")
> > > >
> > > > It looks like a false positive to me, but it made me think a bit and
> > > > IIUC there can be still a potential deadlock, even if the deadlock
> > > > scenario is a bit different than what lockdep is showing.
> > > >
> > > > In the assumption that read-locks are recursive only in_interrupt()
> > > > context (as stated in e918188611f0), the following scenario can still
> > > > happen:
> > > >
> > > > CPU0 CPU1
> > > > ---- ----
> > > > read_lock(&trig->leddev_list_lock);
> > > > write_lock(&trig->leddev_list_lock);
> > > > <soft-irq>
> > > > kbd_bh()
> > > > -> read_lock(&trig->leddev_list_lock);
> > > >
> > > > *** DEADLOCK ***
> > > >
> > > > The write-lock is waiting on CPU1 and the second read_lock() on CPU0
> > > > would be blocked by the write-lock *waiter* on CPU1 => deadlock.
> > > >
> > >
> > > No, this is not a deadlock, as a write-lock waiter only blocks
> > > *non-recursive* readers, so since the read_lock() in kbd_bh() is called
> > > in soft-irq (which in_interrupt() returns true), so it's a recursive
> > > reader and won't get blocked by the write-lock waiter.
> >
> > That's right, I was missing that in_interrupt() returns true also from
> > soft-irq context.
> >
> > > > In that case we could prevent this deadlock condition using a workqueue
> > > > to call kbd_propagate_led_state() instead of calling it directly from
> > > > kbd_bh() (even if lockdep would still report the false positive).
> > > >
> > >
> > > The deadlock senario reported by the following splat is:
> > >
> > >
> > > CPU 0: CPU 1: CPU 2:
> > > ----- ----- -----
> > > led_trigger_event():
> > > read_lock(&trig->leddev_list_lock);
> > > <work queue processing>
> > > ata_hsm_qs_complete():
> > > spin_lock_irqsave(&host->lock);
> > > write_lock(&trig->leddev_list_lock);
> > > ata_port_freeze():
> > > ata_do_link_abort():
> > > ata_qc_complete():
> > > ledtrig_disk_activity():
> > > led_trigger_blink_oneshot():
> > > read_lock(&trig->leddev_list_lock);
> > > // ^ not in in_interrupt() context, so could get blocked by CPU 2
> > > <interrupt>
> > > ata_bmdma_interrupt():
> > > spin_lock_irqsave(&host->lock);
> > >
> > > , where CPU 0 is blocked by CPU 1 because of the spin_lock_irqsave() in
> > > ata_bmdma_interrupt() and CPU 1 is blocked by CPU 2 because of the
> > > read_lock() in led_trigger_blink_oneshot() and CPU 2 is blocked by CPU 0
> > > because of an arbitrary writer on &trig->leddev_list_lock.
> > >
> > > So I don't think it's false positive, but I might miss something
> > > obvious, because I don't know what the code here actually does ;-)
> >
> > With the CPU2 part it all makes sense now and lockdep was right. :)
> >
> > At this point I think we could just schedule a separate work to do the
> > led trigger and avoid calling it with host->lock held and that should
> > prevent the deadlock. I'll send a patch to do that.
>
> Let's... not do that, unless we have no choice.
>
> Would it help if leddev_list_lock used _irqsave() locking?
Using read_lock_irqsave/irqrestore() in led_trigger_event() would be
enough to prevent the deadlock. If it's an acceptable solution I can
send a patch (already tested it and lockdep doesn't complain :)).
Thanks,
-Andrea
next prev parent reply other threads:[~2020-11-02 9:09 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-01 9:26 lockdep: possible irq lock inversion dependency detected (trig->leddev_list_lock) Andrea Righi
2020-10-31 10:17 ` Boqun Feng
2020-11-02 7:33 ` Andrea Righi
2020-11-02 8:56 ` Pavel Machek
2020-11-02 9:09 ` Andrea Righi [this message]
2020-11-06 7:40 ` Andrea Righi
2020-11-01 16:28 ` Pavel Machek
2020-11-02 7:39 ` Andrea Righi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201102090927.GC9930@xps-13-7390 \
--to=andrea.righi@canonical.com \
--cc=boqun.feng@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=pavel@ucw.cz \
--cc=peterz@infradead.org \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.