For virtio-scsi, we export a wide variety of non-scsi devices like NVMe (local and RDMA/TCP based) drives and block based devices using ublk. And then it's common to have multiple high perf devices im a LVM volume. The problem for these setups, is we can easily hit the 4096 scsi_device queue depth limit so we end up throttling IO in the guest when the real device can handle more IO.
In these situations we don't have a device wide limit that maps to cmd_per_lun. We have per hw queue limits or on the host we are doing more dynamic throttling. To allow for these types of devices, this patch allows drivers to set SCSI_UNLIMITED_CMD_PER_LUN for the cmd_per_lun. When set, we will then only be limited by the per hw queue limits. Signed-off-by: Mike Christie <[email protected]> --- drivers/scsi/hosts.c | 5 +++-- drivers/scsi/scsi_scan.c | 25 ++++++++++++++----------- include/scsi/scsi_host.h | 4 ++++ 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index e047747d4ecf..c93c59e847c5 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -238,8 +238,9 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, } /* 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); + if (shost->cmd_per_lun != SCSI_UNLIMITED_CMD_PER_LUN) + shost->cmd_per_lun = min_t(int, shost->cmd_per_lun, + shost->can_queue); error = scsi_init_sense_cache(shost); if (error) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 7b11bc7de0e3..ecc3638c1909 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -352,18 +352,20 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, if (scsi_device_is_pseudo_dev(sdev)) return sdev; - depth = sdev->host->cmd_per_lun ?: 1; + if (sdev->host->cmd_per_lun != SCSI_UNLIMITED_CMD_PER_LUN) { + depth = sdev->host->cmd_per_lun ?: 1; - /* - * Use .can_queue as budget map's depth because we have to - * support adjusting queue depth from sysfs. Meantime use - * default device queue depth to figure out sbitmap shift - * since we use this queue depth most of times. - */ - if (scsi_realloc_sdev_budget_map(sdev, depth)) - goto out_device_destroy; + /* + * Use .can_queue as budget map's depth because we have to + * support adjusting queue depth from sysfs. Meantime use + * default device queue depth to figure out sbitmap shift + * since we use this queue depth most of times. + */ + if (scsi_realloc_sdev_budget_map(sdev, depth)) + goto out_device_destroy; - scsi_change_queue_depth(sdev, depth); + scsi_change_queue_depth(sdev, depth); + } if (shost->hostt->sdev_init) { ret = shost->hostt->sdev_init(sdev); @@ -1108,7 +1110,8 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, * Set up budget map again since memory consumption of the map depends * on actual queue depth. */ - if (hostt->sdev_configure) + if (hostt->sdev_configure && + sdev->host->cmd_per_lun != SCSI_UNLIMITED_CMD_PER_LUN) scsi_realloc_sdev_budget_map(sdev, sdev->queue_depth); if (sdev->scsi_level >= SCSI_3) diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 7c747b566bc3..7555898dba25 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -443,6 +443,7 @@ struct scsi_host_template { */ #define SCSI_DEFAULT_MAX_SECTORS 1024 +#define SCSI_UNLIMITED_CMD_PER_LUN -1 /* * True if this host adapter can make good use of linked commands. * This will allow more than one command to be queued to a given @@ -451,6 +452,9 @@ struct scsi_host_template { * command block per lun, 2 for two, etc. Do not set this to 0. * You should make sure that the host adapter will do the right thing * before you try setting this above 1. + * + * Adapters that do not have a device limit can set this to + * SCSI_UNLIMITED_CMD_PER_LUN. */ short cmd_per_lun; -- 2.47.1

