diff mbox series

scsi: use GFP_NOFS to avoid circular locking dependency

Message ID 20250128164700.6d8504c1@fangorn (mailing list archive)
State New
Headers show
Series scsi: use GFP_NOFS to avoid circular locking dependency | expand

Commit Message

Rik van Riel Jan. 28, 2025, 9:47 p.m. UTC
Filesystems can write to disk from page reclaim with filesystem
locks held, if __GFP_FS is set. Marc found a case where 
scsi_realloc_sdev_budget_map ends up in page reclaim with GFP_KERNEL, 
where it could try to take filesystem locks again, leading to a deadlock.

WARNING: possible circular locking dependency detected
6.13.0 #1 Not tainted
------------------------------------------------------
kswapd0/70 is trying to acquire lock:
ffff8881025d5d78 (&q->q_usage_counter(io)){++++}-{0:0}, at: blk_mq_submit_bio+0x461/0x6e0

but task is already holding lock:
ffffffff81ef5f40 (fs_reclaim){+.+.}-{0:0}, at: balance_pgdat+0x9f/0x760

The full lockdep splat can be found in Marc's report:

https://lkml.org/lkml/2025/1/24/1101

Avoid the potential deadlock by doing the allocation with GFP_NOFS.

Reported-by: Marc Aurèle La France <tsi@tuyoix.net>
Signed-off-by: Rik van Riel <riel@surriel.com>
---
 drivers/scsi/scsi_scan.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Christoph Hellwig Jan. 29, 2025, 5:35 a.m. UTC | #1
GFP_NOFS is never the right thing for block layer allocations.
The right thing here is GFP_NOIO which is a superset of GFP_NOFS.
Otherwise you could reproduce the same deadlock when using swap
instead of a file system to reproduce basically the same deadlock.

Note that this:

https://lore.kernel.org/linux-block/20250117074442.256705-3-hch@lst.de/T/#u

should probably fix the actual deadlock, but it might still need
annotations for lockdep to deal with the initial probing where
the queue is not frozen.  Compared to hacky annotations just using
GFP_NOIO feels simpler and more obvious.
diff mbox series

Patch

diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index f2093982b3db..93d6feef9c7c 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -245,7 +245,7 @@  static int scsi_realloc_sdev_budget_map(struct scsi_device *sdev,
 	}
 	ret = sbitmap_init_node(&sdev->budget_map,
 				scsi_device_max_queue_depth(sdev),
-				new_shift, GFP_KERNEL,
+				new_shift, GFP_NOFS,
 				sdev->request_queue->node, false, true);
 	if (!ret)
 		sbitmap_resize(&sdev->budget_map, depth);