On Sat, Sep 12, 2026 at 12:04:57AM +0800, Hao Zhang wrote:
> From: Hao Zhang <[email protected]>
> 
> bio_set_dev() associates the bio with a blkg through bio_associate_blkg().
> If the blkg lookup misses, blkg_tryget_closest() takes q->queue_lock with
> spin_lock_irq() and releases it with spin_unlock_irq(), which
> unconditionally enables local interrupts.
> 
> Callers may call bio_set_dev() with interrupts already disabled, e.g.
> dm-thin's pool_map() does so while holding pool->lock taken with
> spin_lock_irq().  The nested spin_unlock_irq() then enables interrupts
> while pool->lock is still held, so an I/O completion softirq can run on
> the same CPU, re-acquire pool->lock (thin_endio(), or overwrite_endio()
> -> complete_mapping_preparation()) and deadlock.  lockdep reports this
> as inconsistent SOFTIRQ-ON-W to IN-SOFTIRQ-W usage.
> 
> Commit 3a762de55b4e ("block: save irq state in blkg_lookup_create()")
> fixed the same problem while the lock lived in blkg_lookup_create(), but
> commit 9327a865e395 ("blk-cgroup: don't nest queue_lock under rcu in
> blkg_lookup_create()") moved the locking into blkg_tryget_closest() and
> reverted it to spin_lock_irq().
> 
> Save and restore the caller's IRQ state instead.
> 
> Fixes: 9327a865e395 ("blk-cgroup: don't nest queue_lock under rcu in 
> blkg_lookup_create()")
> Cc: Ming Lei <[email protected]>
> Signed-off-by: Hao Zhang <[email protected]>

Acked-by: Tejun Heo <[email protected]>

Thanks.

-- 
tejun

Reply via email to