Linux SCSI subsystem development
 help / color / mirror / Atom feed
From: Bart Van Assche <bvanassche@acm.org>
To: "Martin K . Petersen" <martin.petersen@oracle.com>
Cc: linux-scsi@vger.kernel.org, Bart Van Assche <bvanassche@acm.org>,
	John Garry <john.garry@huawei.com>,
	Hannes Reinecke <hare@suse.de>,
	"James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
Subject: [PATCH v7 05/28] scsi: core: Introduce .queue_reserved_command()
Date: Thu, 30 Oct 2025 12:36:04 -0700	[thread overview]
Message-ID: <20251030193720.871635-6-bvanassche@acm.org> (raw)
In-Reply-To: <20251030193720.871635-1-bvanassche@acm.org>

From: John Garry <john.garry@huawei.com>

Reserved commands will be used by SCSI LLDs for submitting internal
commands. Since the SCSI host, target and device limits do not apply to
the reserved command use cases, bypass the SCSI host limit checks for
reserved commands. Introduce the .queue_reserved_command() callback for
reserved commands. Additionally, do not activate the SCSI error handler
if a reserved command fails such that reserved commands can be submitted
from inside the SCSI error handler.

Cc: Hannes Reinecke <hare@suse.de>
Signed-off-by: John Garry <john.garry@huawei.com>
[ bvanassche: modified patch title and patch description. Renamed
  .reserved_queuecommand() into .queue_reserved_command(). Changed
  the second argument of __blk_mq_end_request() from 0 into error
  code in the completion path if cmd->result != 0. Rewrote the
  scsi_queue_rq() changes. See also
  https://lore.kernel.org/linux-scsi/1666693096-180008-5-git-send-email-john.garry@huawei.com/ ]
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 drivers/scsi/hosts.c     |  6 +++++
 drivers/scsi/scsi_lib.c  | 54 ++++++++++++++++++++++++++++------------
 include/scsi/scsi_host.h |  6 +++++
 3 files changed, 50 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index ad1476fb5035..e047747d4ecf 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -231,6 +231,12 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
 		goto fail;
 	}
 
+	if (shost->nr_reserved_cmds && !sht->queue_reserved_command) {
+		shost_printk(KERN_ERR, shost,
+			     "nr_reserved_cmds set but no method to queue\n");
+		goto fail;
+	}
+
 	/* Use min_t(int, ...) in case shost->can_queue exceeds SHRT_MAX */
 	shost->cmd_per_lun = min_t(int, shost->cmd_per_lun,
 				   shost->can_queue);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 53ff348b3a4c..d4e874bbf2ea 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1534,6 +1534,14 @@ static void scsi_complete(struct request *rq)
 	struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
 	enum scsi_disposition disposition;
 
+	if (blk_mq_is_reserved_rq(rq)) {
+		/* Only pass-through requests are supported in this code path. */
+		WARN_ON_ONCE(!blk_rq_is_passthrough(scsi_cmd_to_rq(cmd)));
+		scsi_mq_uninit_cmd(cmd);
+		__blk_mq_end_request(rq, scsi_result_to_blk_status(cmd->result));
+		return;
+	}
+
 	INIT_LIST_HEAD(&cmd->eh_entry);
 
 	atomic_inc(&cmd->device->iodone_cnt);
@@ -1823,25 +1831,31 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
 	WARN_ON_ONCE(cmd->budget_token < 0);
 
 	/*
-	 * If the device is not in running state we will reject some or all
-	 * commands.
+	 * Bypass the SCSI device, SCSI target and SCSI host checks for
+	 * reserved commands.
 	 */
-	if (unlikely(sdev->sdev_state != SDEV_RUNNING)) {
-		ret = scsi_device_state_check(sdev, req);
-		if (ret != BLK_STS_OK)
-			goto out_put_budget;
-	}
+	if (!blk_mq_is_reserved_rq(req)) {
+		/*
+		 * If the device is not in running state we will reject some or
+		 * all commands.
+		 */
+		if (unlikely(sdev->sdev_state != SDEV_RUNNING)) {
+			ret = scsi_device_state_check(sdev, req);
+			if (ret != BLK_STS_OK)
+				goto out_put_budget;
+		}
 
-	ret = BLK_STS_RESOURCE;
-	if (!scsi_target_queue_ready(shost, sdev))
-		goto out_put_budget;
-	if (unlikely(scsi_host_in_recovery(shost))) {
-		if (cmd->flags & SCMD_FAIL_IF_RECOVERING)
-			ret = BLK_STS_OFFLINE;
-		goto out_dec_target_busy;
+		ret = BLK_STS_RESOURCE;
+		if (!scsi_target_queue_ready(shost, sdev))
+			goto out_put_budget;
+		if (unlikely(scsi_host_in_recovery(shost))) {
+			if (cmd->flags & SCMD_FAIL_IF_RECOVERING)
+				ret = BLK_STS_OFFLINE;
+			goto out_dec_target_busy;
+		}
+		if (!scsi_host_queue_ready(q, shost, sdev, cmd))
+			goto out_dec_target_busy;
 	}
-	if (!scsi_host_queue_ready(q, shost, sdev, cmd))
-		goto out_dec_target_busy;
 
 	/*
 	 * Only clear the driver-private command data if the LLD does not supply
@@ -1870,6 +1884,14 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
 	cmd->submitter = SUBMITTED_BY_BLOCK_LAYER;
 
 	blk_mq_start_request(req);
+	if (blk_mq_is_reserved_rq(req)) {
+		reason = shost->hostt->queue_reserved_command(shost, cmd);
+		if (reason) {
+			ret = BLK_STS_RESOURCE;
+			goto out_put_budget;
+		}
+		return BLK_STS_OK;
+	}
 	reason = scsi_dispatch_cmd(cmd);
 	if (reason) {
 		scsi_set_blocked(cmd, reason);
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 4f945a20d198..e87cf7eadd26 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -86,6 +86,12 @@ struct scsi_host_template {
 	 */
 	int (* queuecommand)(struct Scsi_Host *, struct scsi_cmnd *);
 
+	/*
+	 * Queue a reserved command (BLK_MQ_REQ_RESERVED). The .queuecommand()
+	 * documentation also applies to the .queue_reserved_command() callback.
+	 */
+	int (*queue_reserved_command)(struct Scsi_Host *, struct scsi_cmnd *);
+
 	/*
 	 * The commit_rqs function is used to trigger a hardware
 	 * doorbell after some requests have been queued with

  parent reply	other threads:[~2025-10-30 19:38 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-30 19:35 [PATCH v7 00/28] Optimize the hot path in the UFS driver Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 01/28] scsi: core: Support allocating reserved commands Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 02/28] scsi: core: Move two statements Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 03/28] scsi: core: Make the budget map optional Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 04/28] scsi: core: Support allocating a pseudo SCSI device Bart Van Assche
2025-10-30 19:36 ` Bart Van Assche [this message]
2025-10-30 19:36 ` [PATCH v7 06/28] scsi: core: Add scsi_{get,put}_internal_cmd() helpers Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 07/28] scsi_debug: Abort SCSI commands via an internal command Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 08/28] ufs: core: Move an assignment in ufshcd_mcq_process_cqe() Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 09/28] ufs: core: Change the type of one ufshcd_add_cmd_upiu_trace() argument Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 10/28] ufs: core: Only call ufshcd_add_command_trace() for SCSI commands Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 11/28] ufs: core: Change the type of one ufshcd_add_command_trace() argument Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 12/28] ufs: core: Change the type of one ufshcd_send_command() argument Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 13/28] ufs: core: Only call ufshcd_should_inform_monitor() for SCSI commands Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 14/28] ufs: core: Change the monitor function argument types Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 15/28] ufs: core: Rework ufshcd_mcq_compl_pending_transfer() Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 16/28] ufs: core: Rework ufshcd_eh_device_reset_handler() Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 17/28] ufs: core: Rework the SCSI host queue depth calculation code Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 18/28] ufs: core: Allocate the SCSI host earlier Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 19/28] ufs: core: Call ufshcd_init_lrb() later Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 20/28] ufs: core: Use hba->reserved_slot Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 21/28] ufs: core: Make the reserved slot a reserved request Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 22/28] ufs: core: Do not clear driver-private command data Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 23/28] ufs: core: Optimize the hot path Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 24/28] ufs: core: Pass a SCSI pointer instead of an LRB pointer Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 25/28] ufs: core: Remove the ufshcd_lrb task_tag member Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 26/28] ufs: core: Make blk_mq_tagset_busy_iter() skip reserved requests Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 27/28] ufs: core: Move code out of ufshcd_wait_for_dev_cmd() Bart Van Assche
2025-10-30 19:36 ` [PATCH v7 28/28] ufs: core: Switch to scsi_get_internal_cmd() Bart Van Assche

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=20251030193720.871635-6-bvanassche@acm.org \
    --to=bvanassche@acm.org \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=hare@suse.de \
    --cc=john.garry@huawei.com \
    --cc=linux-scsi@vger.kernel.org \
    --cc=martin.petersen@oracle.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