Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

scsi: core: Introduce .queue_reserved_command()

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.

[ 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/ ]

Cc: Hannes Reinecke <hare@suse.de>
Signed-off-by: John Garry <john.garry@huawei.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Link: https://patch.msgid.link/20251031204029.2883185-6-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

John Garry and committed by
Martin K. Petersen
11ea1de3 d630fbf6

+50 -16
+6
drivers/scsi/hosts.c
··· 231 231 goto fail; 232 232 } 233 233 234 + if (shost->nr_reserved_cmds && !sht->queue_reserved_command) { 235 + shost_printk(KERN_ERR, shost, 236 + "nr_reserved_cmds set but no method to queue\n"); 237 + goto fail; 238 + } 239 + 234 240 /* Use min_t(int, ...) in case shost->can_queue exceeds SHRT_MAX */ 235 241 shost->cmd_per_lun = min_t(int, shost->cmd_per_lun, 236 242 shost->can_queue);
+38 -16
drivers/scsi/scsi_lib.c
··· 1534 1534 struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq); 1535 1535 enum scsi_disposition disposition; 1536 1536 1537 + if (blk_mq_is_reserved_rq(rq)) { 1538 + /* Only pass-through requests are supported in this code path. */ 1539 + WARN_ON_ONCE(!blk_rq_is_passthrough(scsi_cmd_to_rq(cmd))); 1540 + scsi_mq_uninit_cmd(cmd); 1541 + __blk_mq_end_request(rq, scsi_result_to_blk_status(cmd->result)); 1542 + return; 1543 + } 1544 + 1537 1545 INIT_LIST_HEAD(&cmd->eh_entry); 1538 1546 1539 1547 atomic_inc(&cmd->device->iodone_cnt); ··· 1831 1823 WARN_ON_ONCE(cmd->budget_token < 0); 1832 1824 1833 1825 /* 1834 - * If the device is not in running state we will reject some or all 1835 - * commands. 1826 + * Bypass the SCSI device, SCSI target and SCSI host checks for 1827 + * reserved commands. 1836 1828 */ 1837 - if (unlikely(sdev->sdev_state != SDEV_RUNNING)) { 1838 - ret = scsi_device_state_check(sdev, req); 1839 - if (ret != BLK_STS_OK) 1840 - goto out_put_budget; 1841 - } 1829 + if (!blk_mq_is_reserved_rq(req)) { 1830 + /* 1831 + * If the device is not in running state we will reject some or 1832 + * all commands. 1833 + */ 1834 + if (unlikely(sdev->sdev_state != SDEV_RUNNING)) { 1835 + ret = scsi_device_state_check(sdev, req); 1836 + if (ret != BLK_STS_OK) 1837 + goto out_put_budget; 1838 + } 1842 1839 1843 - ret = BLK_STS_RESOURCE; 1844 - if (!scsi_target_queue_ready(shost, sdev)) 1845 - goto out_put_budget; 1846 - if (unlikely(scsi_host_in_recovery(shost))) { 1847 - if (cmd->flags & SCMD_FAIL_IF_RECOVERING) 1848 - ret = BLK_STS_OFFLINE; 1849 - goto out_dec_target_busy; 1840 + ret = BLK_STS_RESOURCE; 1841 + if (!scsi_target_queue_ready(shost, sdev)) 1842 + goto out_put_budget; 1843 + if (unlikely(scsi_host_in_recovery(shost))) { 1844 + if (cmd->flags & SCMD_FAIL_IF_RECOVERING) 1845 + ret = BLK_STS_OFFLINE; 1846 + goto out_dec_target_busy; 1847 + } 1848 + if (!scsi_host_queue_ready(q, shost, sdev, cmd)) 1849 + goto out_dec_target_busy; 1850 1850 } 1851 - if (!scsi_host_queue_ready(q, shost, sdev, cmd)) 1852 - goto out_dec_target_busy; 1853 1851 1854 1852 /* 1855 1853 * Only clear the driver-private command data if the LLD does not supply ··· 1884 1870 cmd->submitter = SUBMITTED_BY_BLOCK_LAYER; 1885 1871 1886 1872 blk_mq_start_request(req); 1873 + if (blk_mq_is_reserved_rq(req)) { 1874 + reason = shost->hostt->queue_reserved_command(shost, cmd); 1875 + if (reason) { 1876 + ret = BLK_STS_RESOURCE; 1877 + goto out_put_budget; 1878 + } 1879 + return BLK_STS_OK; 1880 + } 1887 1881 reason = scsi_dispatch_cmd(cmd); 1888 1882 if (reason) { 1889 1883 scsi_set_blocked(cmd, reason);
+6
include/scsi/scsi_host.h
··· 87 87 int (* queuecommand)(struct Scsi_Host *, struct scsi_cmnd *); 88 88 89 89 /* 90 + * Queue a reserved command (BLK_MQ_REQ_RESERVED). The .queuecommand() 91 + * documentation also applies to the .queue_reserved_command() callback. 92 + */ 93 + int (*queue_reserved_command)(struct Scsi_Host *, struct scsi_cmnd *); 94 + 95 + /* 90 96 * The commit_rqs function is used to trigger a hardware 91 97 * doorbell after some requests have been queued with 92 98 * queuecommand, when an error is encountered before sending