[PATCH] scsi: core: Set BLK_FEAT_SKIP_TAGSET_QUIESCE on pseudo SCSI devices
From: Stanley Jhu
Date: Tue Sep 01 2026 - 08:26:53 EST
Commit d630fbf6fc8c ("scsi: core: Support allocating a pseudo SCSI
device") introduced pseudo SCSI devices to allocate and dispatch
internal SCSI commands (such as device management commands) via
scsi_get_internal_cmd(). Subsequently, commit 08b12cda6c44 ("scsi: ufs:
core: Switch to scsi_get_internal_cmd()") switched UFS internal commands
to use this mechanism.
However, pseudo SCSI devices share the host tagset (&shost->tag_set)
with regular LUNs. During error recovery or host reset, drivers
typically quiesce the host tagset via
blk_mq_quiesce_tagset(&shost->tag_set) to freeze user block I/O.
Because pseudo_sdev->request_queue belongs to shost->tag_set,
blk_mq_quiesce_tagset() marks it QUEUE_FLAG_QUIESCED as well.
When error handling then attempts to issue internal commands to recover
or verify the device (e.g. ufshcd_verify_dev_init() issuing a NOP OUT
UPIU), blk_execute_rq() inserts the request into the request_queue of
pseudo_sdev. Because the queue is quiesced, blk_mq_run_hw_queue() skips
running the queue, and blk_execute_rq() blocks indefinitely waiting for
completion. Since blk_mq_unquiesce_tagset() is only invoked after error
recovery finishes, this results in an unrecoverable circular wait
deadlock.
Resolve this by setting BLK_FEAT_SKIP_TAGSET_QUIESCE in struct
queue_limits when allocating a pseudo SCSI device in scsi_alloc_sdev().
Passing this feature directly into blk_mq_alloc_queue() conforms to the
Block Layer's atomic queue limits initialization model and mirrors
NVMe's canonical pattern for its internal connect_q in
drivers/nvme/host/core.c. This ensures that blk_mq_quiesce_tagset()
ignores the pseudo device's request queue, allowing internal commands to
be dispatched while user I/O remains quiesced.
Fixes: d630fbf6fc8c ("scsi: core: Support allocating a pseudo SCSI device")
Fixes: 08b12cda6c44 ("scsi: ufs: core: Switch to scsi_get_internal_cmd()")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Stanley Jhu <stanleyjhu@xxxxxxxxxx>
---
drivers/scsi/scsi_scan.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 3b82e80e807a..eb48866ed0dc 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -336,6 +336,8 @@ static struct scsi_device *scsi_alloc_sdev(struct
scsi_target *starget,
sdev->sg_reserved_size = INT_MAX;
scsi_init_limits(shost, &lim);
+ if (scsi_device_is_pseudo_dev(sdev))
+ lim.features |= BLK_FEAT_SKIP_TAGSET_QUIESCE;
q = blk_mq_alloc_queue(&sdev->host->tag_set, &lim, sdev);
if (IS_ERR(q)) {
/* release fn is set up in scsi_sysfs_device_initialise, so
--
2.43.0