[PATCH] null_blk: fix sleeping in atomic context with shared_tags and memory_backed

From: Cheng Lingfei

Date: Tue Aug 25 2026 - 02:17:18 EST


When a null_blk device is configured with both shared_tags and
memory_backed (or blocking), the zone lock uses a mutex which may sleep.
However, the global shared tag_set only checks the g_blocking module
parameter to decide whether to set BLK_MQ_F_BLOCKING, ignoring the
per-device dev->blocking flag. Without BLK_MQ_F_BLOCKING, blk-mq uses
rcu_read_lock() instead of srcu_read_lock() to protect the dispatch
path, making it illegal to sleep.

This leads to a "sleeping function called from invalid context" BUG when
I/O is submitted during add_disk() partition scanning, as the call chain
enters null_lock_zone() -> mutex_lock() inside an RCU read-side critical
section.

Fix this by disabling shared_tags in null_validate_conf() when the
device needs blocking but the global tag_set was not initialized with
BLK_MQ_F_BLOCKING (i.e., g_blocking is false). The device falls back to
a per-device tag_set which correctly propagates dev->blocking to
BLK_MQ_F_BLOCKING, allowing blk-mq to use SRCU and permit sleeping in
the dispatch path.

Users who need both shared_tags and memory_backed simultaneously should
load the module with the blocking=1 parameter so the global tag_set is
initialized with BLK_MQ_F_BLOCKING from the start.

Reported-by: syzbot+b6fd00508cc05a5c003c@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=b6fd00508cc05a5c003c
Tested-by: syzbot+b6fd00508cc05a5c003c@xxxxxxxxxxxxxxxxxxxxxxxxx
Signed-off-by: Cheng Lingfei <chenglingfei@xxxxxxxxxxx>
---
drivers/block/null_blk/main.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c
index f8c0fd57e041..0dc7fd106db8 100644
--- a/drivers/block/null_blk/main.c
+++ b/drivers/block/null_blk/main.c
@@ -1912,6 +1912,12 @@ static int null_validate_conf(struct nullb_device *dev)
dev->blocking = true;
else /* cache is meaningless */
dev->cache_size = 0;
+
+ if (dev->shared_tags && dev->blocking && !g_blocking) {
+ pr_info("shared_tags disabled: memory_backed/blocking device requires per-device tag set for BLK_MQ_F_BLOCKING\n");
+ dev->shared_tags = false;
+ }
+
dev->cache_size = min_t(unsigned long, ULONG_MAX / 1024 / 1024,
dev->cache_size);
dev->mbps = min_t(unsigned int, 1024 * 40, dev->mbps);

---
base-commit: 2f1baf1fc8929e6c48370be543ad028ac7ad4131
change-id: 20260825-b4-null-blk-sleep-fix-64a1a6323e97

Best regards,
--
Cheng Lingfei <chenglingfei@xxxxxxxxxxx>