Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

blk-zoned: Fix a lockdep complaint about recursive locking

If preparing a write bio fails then blk_zone_wplug_bio_work() calls
bio_endio() with zwplug->lock held. If a device mapper driver is stacked
on top of the zoned block device then this results in nested locking of
zwplug->lock. The resulting lockdep complaint is a false positive
because this is nested locking and not recursive locking. Suppress this
false positive by calling blk_zone_wplug_bio_io_error() without holding
zwplug->lock. This is safe because no code in
blk_zone_wplug_bio_io_error() depends on zwplug->lock being held. This
patch suppresses the following lockdep complaint:

WARNING: possible recursive locking detected
--------------------------------------------
kworker/3:0H/46 is trying to acquire lock:
ffffff882968b830 (&zwplug->lock){-...}-{2:2}, at: blk_zone_write_plug_bio_endio+0x64/0x1f0

but task is already holding lock:
ffffff88315bc230 (&zwplug->lock){-...}-{2:2}, at: blk_zone_wplug_bio_work+0x8c/0x48c

other info that might help us debug this:
Possible unsafe locking scenario:

CPU0
----
lock(&zwplug->lock);
lock(&zwplug->lock);

*** DEADLOCK ***

May be due to missing lock nesting notation

3 locks held by kworker/3:0H/46:
#0: ffffff8809486758 ((wq_completion)sdd_zwplugs){+.+.}-{0:0}, at: process_one_work+0x1bc/0x65c
#1: ffffffc085de3d70 ((work_completion)(&zwplug->bio_work)){+.+.}-{0:0}, at: process_one_work+0x1e4/0x65c
#2: ffffff88315bc230 (&zwplug->lock){-...}-{2:2}, at: blk_zone_wplug_bio_work+0x8c/0x48c

stack backtrace:
CPU: 3 UID: 0 PID: 46 Comm: kworker/3:0H Tainted: G W OE 6.12.38-android16-5-maybe-dirty-4k #1 8b362b6f76e3645a58cd27d86982bce10d150025
Tainted: [W]=WARN, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
Hardware name: Spacecraft board based on MALIBU (DT)
Workqueue: sdd_zwplugs blk_zone_wplug_bio_work
Call trace:
dump_backtrace+0xfc/0x17c
show_stack+0x18/0x28
dump_stack_lvl+0x40/0xa0
dump_stack+0x18/0x24
print_deadlock_bug+0x38c/0x398
__lock_acquire+0x13e8/0x2e1c
lock_acquire+0x134/0x2b4
_raw_spin_lock_irqsave+0x5c/0x80
blk_zone_write_plug_bio_endio+0x64/0x1f0
bio_endio+0x9c/0x240
__dm_io_complete+0x214/0x260
clone_endio+0xe8/0x214
bio_endio+0x218/0x240
blk_zone_wplug_bio_work+0x204/0x48c
process_one_work+0x26c/0x65c
worker_thread+0x33c/0x498
kthread+0x110/0x134
ret_from_fork+0x10/0x20

Cc: stable@vger.kernel.org
Cc: Damien Le Moal <dlemoal@kernel.org>
Cc: Christoph Hellwig <hch@lst.de>
Fixes: dd291d77cc90 ("block: Introduce zone write plugging")
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Link: https://lore.kernel.org/r/20250825182720.1697203-1-bvanassche@acm.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Bart Van Assche and committed by
Jens Axboe
198f36f9 d14469ed

+6 -5
+6 -5
block/blk-zoned.c
··· 1286 1286 struct block_device *bdev; 1287 1287 unsigned long flags; 1288 1288 struct bio *bio; 1289 + bool prepared; 1289 1290 1290 1291 /* 1291 1292 * Submit the next plugged BIO. If we do not have any, clear 1292 1293 * the plugged flag. 1293 1294 */ 1294 - spin_lock_irqsave(&zwplug->lock, flags); 1295 - 1296 1295 again: 1296 + spin_lock_irqsave(&zwplug->lock, flags); 1297 1297 bio = bio_list_pop(&zwplug->bio_list); 1298 1298 if (!bio) { 1299 1299 zwplug->flags &= ~BLK_ZONE_WPLUG_PLUGGED; ··· 1304 1304 trace_blk_zone_wplug_bio(zwplug->disk->queue, zwplug->zone_no, 1305 1305 bio->bi_iter.bi_sector, bio_sectors(bio)); 1306 1306 1307 - if (!blk_zone_wplug_prepare_bio(zwplug, bio)) { 1307 + prepared = blk_zone_wplug_prepare_bio(zwplug, bio); 1308 + spin_unlock_irqrestore(&zwplug->lock, flags); 1309 + 1310 + if (!prepared) { 1308 1311 blk_zone_wplug_bio_io_error(zwplug, bio); 1309 1312 goto again; 1310 1313 } 1311 - 1312 - spin_unlock_irqrestore(&zwplug->lock, flags); 1313 1314 1314 1315 bdev = bio->bi_bdev; 1315 1316