From 194605d45dcb511983caca699d81855693b25fe0 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 27 Sep 2023 21:09:01 -0500 Subject: scsi: target: Have drivers report if they support direct submissions In some cases, like with multiple LUN targets or where the target has to respond to transport level requests from the receiving context it can be better to defer cmd submission to a helper thread. If the backend driver blocks on something like request/tag allocation it can block the entire target submission path and other LUs and transport IO on that session. In other cases like single LUN targets with storage that can support all the commands that the target can queue, then it's best to submit the cmd to the backend from the target's cmd receiving context. Subsequent commits will allow the user to config what they prefer, but drivers like loop can't directly submit because they can be called from a context that can't sleep. And, drivers like vhost-scsi can support direct submission, but need to keep their default behavior of deferring execution to avoid possible regressions where the backend can block. Make the drivers tell LIO core if they support direct submissions and their current default, so we can prevent users from misconfiguring the system and initialize devices correctly. Signed-off-by: Mike Christie Link: https://lore.kernel.org/r/20230928020907.5730-2-michael.christie@oracle.com Signed-off-by: Martin K. Petersen --- drivers/vhost/scsi.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/vhost') diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index abef0619c790..dc274463bdf0 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -2598,6 +2598,9 @@ static const struct target_core_fabric_ops vhost_scsi_ops = { .tfc_wwn_attrs = vhost_scsi_wwn_attrs, .tfc_tpg_base_attrs = vhost_scsi_tpg_attrs, .tfc_tpg_attrib_attrs = vhost_scsi_tpg_attrib_attrs, + + .default_submit_type = TARGET_QUEUE_SUBMIT, + .direct_submit_supp = 1, }; static int __init vhost_scsi_init(void) -- cgit v1.2.3 From e2f4ea40138e16d1dfd768f2dead8f3f75a85673 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 27 Sep 2023 21:09:05 -0500 Subject: scsi: target: Allow userspace to request direct submissions This allows userspace to request the fabric drivers do direct submissions if they support it. With the new device file, submit_type, users can write 0 - 2 to control how commands are submitted to the backend: 0 - TARGET_FABRIC_DEFAULT_SUBMIT - LIO will use the fabric's default submission type. This is the default for compat. 1 - TARGET_DIRECT_SUBMIT - LIO will submit the cmd to the backend from the calling context if the fabric the cmd was received on supports it, else it will use the fabric's default type. 2 - TARGET_QUEUE_SUBMIT - LIO will queue the cmd to the LIO submission workqueue which will pass it to the backend. When using an NVMe drive and vhost-scsi with direct submission we see around a 20% improvement in 4K I/Os: fio jobs 1 2 4 8 10 -------------------------------------------------- defer 94K 190K 394K 770K 890K direct 128K 252K 488K 950K - And when using the queueing mode, we now no longer see issues like where the iSCSI tx thread is blocked in the block layer waiting on a tag so it can't respond to a nop or perform I/Os for other LUs. Signed-off-by: Mike Christie Link: https://lore.kernel.org/r/20230928020907.5730-6-michael.christie@oracle.com Signed-off-by: Martin K. Petersen --- drivers/target/loopback/tcm_loop.c | 2 +- drivers/target/target_core_configfs.c | 22 ++++++++++++++++++ drivers/target/target_core_device.c | 1 + drivers/target/target_core_transport.c | 41 +++++++++++++++++++++++++--------- drivers/vhost/scsi.c | 2 +- include/target/target_core_base.h | 1 + 6 files changed, 57 insertions(+), 12 deletions(-) (limited to 'drivers/vhost') diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index fbacccdd2ff6..8e4035ff3674 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -154,7 +154,7 @@ static void tcm_loop_target_queue_cmd(struct tcm_loop_cmd *tl_cmd) GFP_ATOMIC)) return; - target_queue_submission(se_cmd); + target_submit(se_cmd); return; out_done: diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 936e5ff1b209..f7eaf17e9050 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -577,6 +577,7 @@ DEF_CONFIGFS_ATTRIB_SHOW(unmap_granularity_alignment); DEF_CONFIGFS_ATTRIB_SHOW(unmap_zeroes_data); DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len); DEF_CONFIGFS_ATTRIB_SHOW(emulate_rsoc); +DEF_CONFIGFS_ATTRIB_SHOW(submit_type); #define DEF_CONFIGFS_ATTRIB_STORE_U32(_name) \ static ssize_t _name##_store(struct config_item *item, const char *page,\ @@ -1231,6 +1232,24 @@ static ssize_t emulate_rsoc_store(struct config_item *item, return count; } +static ssize_t submit_type_store(struct config_item *item, const char *page, + size_t count) +{ + struct se_dev_attrib *da = to_attrib(item); + int ret; + u8 val; + + ret = kstrtou8(page, 0, &val); + if (ret < 0) + return ret; + + if (val > TARGET_QUEUE_SUBMIT) + return -EINVAL; + + da->submit_type = val; + return count; +} + CONFIGFS_ATTR(, emulate_model_alias); CONFIGFS_ATTR(, emulate_dpo); CONFIGFS_ATTR(, emulate_fua_write); @@ -1266,6 +1285,7 @@ CONFIGFS_ATTR(, unmap_zeroes_data); CONFIGFS_ATTR(, max_write_same_len); CONFIGFS_ATTR(, alua_support); CONFIGFS_ATTR(, pgr_support); +CONFIGFS_ATTR(, submit_type); /* * dev_attrib attributes for devices using the target core SBC/SPC @@ -1308,6 +1328,7 @@ struct configfs_attribute *sbc_attrib_attrs[] = { &attr_alua_support, &attr_pgr_support, &attr_emulate_rsoc, + &attr_submit_type, NULL, }; EXPORT_SYMBOL(sbc_attrib_attrs); @@ -1325,6 +1346,7 @@ struct configfs_attribute *passthrough_attrib_attrs[] = { &attr_emulate_pr, &attr_alua_support, &attr_pgr_support, + &attr_submit_type, NULL, }; EXPORT_SYMBOL(passthrough_attrib_attrs); diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index b7ac60f4a219..0f3fd775fe6d 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -779,6 +779,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) dev->dev_attrib.unmap_zeroes_data = DA_UNMAP_ZEROES_DATA_DEFAULT; dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN; + dev->dev_attrib.submit_type = TARGET_FABRIC_DEFAULT_SUBMIT; xcopy_lun = &dev->xcopy_lun; rcu_assign_pointer(xcopy_lun->lun_se_dev, dev); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 6c8f6055fc1e..f1fab7e0ea3d 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1575,14 +1575,7 @@ target_cmd_parse_cdb(struct se_cmd *cmd) } EXPORT_SYMBOL(target_cmd_parse_cdb); -/** - * target_submit - perform final initialization and submit cmd to LIO core - * @cmd: command descriptor to submit - * - * target_submit_prep or something similar must have been called on the cmd, - * and this must be called from process context. - */ -int target_submit(struct se_cmd *cmd) +static int __target_submit(struct se_cmd *cmd) { sense_reason_t ret; @@ -1642,7 +1635,6 @@ int target_submit(struct se_cmd *cmd) transport_generic_request_failure(cmd, ret); return 0; } -EXPORT_SYMBOL_GPL(target_submit); sense_reason_t transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *sgl, @@ -1904,7 +1896,7 @@ void target_queued_submit_work(struct work_struct *work) se_plug = target_plug_device(se_dev); } - target_submit(se_cmd); + __target_submit(se_cmd); } if (se_plug) @@ -1927,6 +1919,35 @@ void target_queue_submission(struct se_cmd *se_cmd) } EXPORT_SYMBOL_GPL(target_queue_submission); +/** + * target_submit - perform final initialization and submit cmd to LIO core + * @cmd: command descriptor to submit + * + * target_submit_prep or something similar must have been called on the cmd, + * and this must be called from process context. + */ +int target_submit(struct se_cmd *se_cmd) +{ + const struct target_core_fabric_ops *tfo = se_cmd->se_sess->se_tpg->se_tpg_tfo; + struct se_dev_attrib *da = &se_cmd->se_dev->dev_attrib; + u8 submit_type; + + if (da->submit_type == TARGET_FABRIC_DEFAULT_SUBMIT) + submit_type = tfo->default_submit_type; + else if (da->submit_type == TARGET_DIRECT_SUBMIT && + tfo->direct_submit_supp) + submit_type = TARGET_DIRECT_SUBMIT; + else + submit_type = TARGET_QUEUE_SUBMIT; + + if (submit_type == TARGET_DIRECT_SUBMIT) + return __target_submit(se_cmd); + + target_queue_submission(se_cmd); + return 0; +} +EXPORT_SYMBOL_GPL(target_submit); + static void target_complete_tmr_failure(struct work_struct *work) { struct se_cmd *se_cmd = container_of(work, struct se_cmd, work); diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index dc274463bdf0..4e3b2c25c721 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -909,7 +909,7 @@ static void vhost_scsi_target_queue_cmd(struct vhost_scsi_cmd *cmd) cmd->tvc_prot_sgl_count, GFP_KERNEL)) return; - target_queue_submission(se_cmd); + target_submit(se_cmd); } static void diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 401abdf8a9ef..97099a5e3f6c 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -726,6 +726,7 @@ struct se_dev_attrib { u32 unmap_granularity; u32 unmap_granularity_alignment; u32 max_write_same_len; + u8 submit_type; struct se_device *da_dev; struct config_group da_group; }; -- cgit v1.2.3