[PATCH] blk-mq: clear stale inactive flag on hctx reuse
From: Nirmoy Das
Date: Tue Oct 20 2026 - 08:52:57 EST
When the last CPU mapped to an hctx goes offline,
blk_mq_hctx_notify_offline() sets BLK_MQ_S_INACTIVE. Updating the
number of hardware queues exits every hctx and parks it on
q->unused_hctx_list. A later update can reuse a parked hctx through
blk_mq_alloc_and_init_hctx(), at any queue index, and nothing clears
the flag.
If the reused hctx is mapped to an online CPU, blk_mq_get_tag() keeps
returning BLK_MQ_NO_TAG for it. __blk_mq_alloc_requests() sleeps and
retries, expecting CPU hotplug to move the task to another CPU, so a
task that stays on that CPU never gets a tag. Onlining the original CPU
doesn't recover it either, because blk_mq_hctx_notify_online() only
clears the flag on the hctx that CPU now maps to.
Clear BLK_MQ_S_INACTIVE in blk_mq_init_hctx() so a reused hctx starts
like a freshly allocated one. A reused hctx has no cpuhp instances at
that point, so the offline callback can't set the flag again before
blk_mq_add_hw_queues_cpuhp() registers it. Clearing the flag in
blk_mq_exit_hctx() is not enough, because a parked hctx keeps its cpuhp
instances until blk_mq_remove_hw_queues_cpuhp(). Preserve the other
hctx state flags.
Reproduced with null_blk on v7.3 in a four-vCPU arm64 QEMU/KVM guest:
modprobe null_blk nr_devices=0
mkdir /sys/kernel/config/nullb/nullb0
cd /sys/kernel/config/nullb/nullb0
echo 4 > submit_queues; echo 1 > memory_backed; echo 16 > size
echo 1 > power
echo 0 > /sys/devices/system/cpu/cpu3/online
echo 2 > submit_queues
echo 4 > submit_queues
Offlining CPU3 marks hctx3 inactive. After the two updates it comes back
as hctx1 and is mapped to CPU0:
# cat /sys/block/nullb0/mq/1/cpu_list
0
# cat /sys/kernel/debug/block/nullb0/hctx1/state
INACTIVE
A 4K O_DIRECT read pinned to CPU0 hangs in D state, while the same read
on CPU1 and CPU2 completes. Onlining CPU3 again leaves hctx1 inactive
and the CPU0 read still hangs. With this change hctx1 state is empty and
the reads on CPU0, CPU1 and CPU2 complete, before and after onlining
CPU3.
Fixes: bf0beec0607d ("blk-mq: drain I/O when all CPUs in a hctx are offline")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: LLM
Signed-off-by: Nirmoy Das <nirmoyd@xxxxxxxxxx>
---
block/blk-mq.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 025a799f35b924d..00b75eb95dd943a 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -4002,6 +4002,7 @@ static int blk_mq_init_hctx(struct request_queue *q,
goto fail;
hctx->queue_num = hctx_idx;
+ clear_bit(BLK_MQ_S_INACTIVE, &hctx->state);
hctx->tags = set->tags[hctx_idx];
--
2.43.0