From: Brian Bunker <brian@purestorage.com>
To: linux-scsi@vger.kernel.org,
"Martin K . Petersen" <martin.petersen@oracle.com>,
"James E . J . Bottomley" <James.Bottomley@HansenPartnership.com>
Cc: lijinlin <lijinlin3@huawei.com>, Wu Bo <wubo40@huawei.com>,
Bart Van Assche <bvanassche@acm.org>,
linux-kernel@vger.kernel.org,
Brian Bunker <brian@purestorage.com>
Subject: [PATCH 1/1] scsi: core: Restart a stopped queue when sysfs sets a device running
Date: Fri, 30 Oct 2026 09:42:29 -0700 [thread overview]
Message-ID: <20261030164229.10037-2-brian@purestorage.com> (raw)
In-Reply-To: <20261030164229.10037-1-brian@purestorage.com>
A device that its transport blocks has its queue stopped. If the SCSI
error handler then gives up on the device, it moves it from SDEV_BLOCK
to SDEV_OFFLINE and leaves the queue stopped. When userspace later
writes "running" to the device's state attribute, store_state_field()
moves it to SDEV_RUNNING, still with the queue stopped, and rescans it.
The rescan takes the device lock and waits for I/O that can never be
dispatched.
Nothing restarts the queue after that. When the transport later
unblocks the device, scsi_internal_device_unblock_nowait() rejects a
device that is already in SDEV_RUNNING and returns before
scsi_start_queue(), so the device is left running with its queue
stopped for good. The task that wrote "running" hangs forever holding
the device lock, and anything else that takes it hangs behind it.
This shows up with iSCSI when a session drops again just after
recovering. iscsid onlines the session's devices after a relogin by
writing "running" to every device it finds offline:
1. The session is blocked, which blocks the device and stops its
queue.
2. The error handler cannot recover the device and moves it from
SDEV_BLOCK to SDEV_OFFLINE. The queue stays stopped.
3. iscsid writes "running": SDEV_OFFLINE -> SDEV_RUNNING with the
queue still stopped, then the rescan sends an INQUIRY that sits
unsent while holding the device lock.
4. The session recovery timeout calls scsi_target_unblock(). The
other devices go from SDEV_BLOCK to SDEV_TRANSPORT_OFFLINE and get
their queues restarted, but this one is skipped because it is
already running.
A vmcore from such a hang shows the device in SDEV_RUNNING with
queue_stopped set and the queue's quiesce_depth at 1, the rescan's
INQUIRY never started (MQ_RQ_IDLE, no start time or deadline), and
iscsid owning the device lock while other tasks wait for it.
Restart the queue in store_state_field() when it moves a device to
SDEV_RUNNING. scsi_start_queue() only unquiesces the queue when
queue_stopped is set, so this is a no-op for a device whose queue is
already running, and it keeps a later scsi_start_queue() from the
transport balanced. If the transport is still blocked, its own
readiness checks in queuecommand keep commands from reaching the wire,
as for any other running device.
Fixes: f0f82e2476f6 ("scsi: core: Fix capacity set to zero after offlinining device")
Signed-off-by: Brian Bunker <brian@purestorage.com>
---
drivers/scsi/scsi_sysfs.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index fe54792ed69e..f5416a1548bd 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -811,8 +811,16 @@ store_state_field(struct device *dev, struct device_attribute *attr,
ret = 0;
} else {
ret = scsi_device_set_state(sdev, state);
- if (ret == 0 && state == SDEV_RUNNING)
+ if (ret == 0 && state == SDEV_RUNNING) {
+ /*
+ * The device may have been offlined while blocked by
+ * its transport, so its queue can still be stopped.
+ * The transport's unblock skips a running device and
+ * would never restart it, so restart it here.
+ */
+ scsi_start_queue(sdev);
rescan_dev = true;
+ }
}
mutex_unlock(&sdev->state_mutex);
--
2.56.0
next prev parent reply other threads:[~2026-10-30 16:42 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-30 16:42 [PATCH 0/1] scsi: core: Restart a stopped queue when sysfs sets a device running Brian Bunker
2026-10-30 16:42 ` Brian Bunker [this message]
2026-10-30 16:58 ` [PATCH 1/1] " sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261030164229.10037-2-brian@purestorage.com \
--to=brian@purestorage.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=bvanassche@acm.org \
--cc=lijinlin3@huawei.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
--cc=wubo40@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox