aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2023-10-13 15:56:37 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2023-10-13 15:56:37 -0400
commit1caddfc5816e4bf55cf7962775e6ed509ddfdf9b (patch)
treee6d5b7166dc0c320a939825b2cfcda58d20d5d27 /drivers/target
parent9f4c887fe64e27413509979b5be3fb2630d813ba (diff)
parent6dbc829d101d9edb41081de01968792a009c9a78 (diff)
downloadlinux-1caddfc5816e4bf55cf7962775e6ed509ddfdf9b.tar.gz
Merge patch series "scsi: target: Allow userspace to config cmd submission"
Mike Christie <michael.christie@oracle.com> says: The following patches were made over Linus's tree but apply over Martin's branches. They allow userspace to configure how fabric drivers submit cmds to backend drivers. Right now loop and vhost use a worker thread, and the other drivers submit from the contexts they receive/process the cmd from. For multiple LUN cases where the target can queue more cmds than the backend can handle then deferring to a worker thread is safest because the backend driver can block when doing things like waiting for a free request/tag. Deferring also helps when the target has to handle transport level requests from the recv context. For cases where the backend devices can queue everything the target sends, then there is no need to defer to a workqueue and you can see a perf boost of up to 26% for small IO workloads. For a nvme device and vhost-scsi I can see with 4K IOs: fio jobs 1 2 4 8 10 -------------------------------------------------- workqueue submit 94K 190K 394K 770K 890K direct submit 128K 252K 488K 950K - Link: https://lore.kernel.org/r/1b1f7a5c-0988-45f9-b103-dfed2c0405b1@oracle.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/iscsi/iscsi_target.c6
-rw-r--r--drivers/target/iscsi/iscsi_target_configfs.c5
-rw-r--r--drivers/target/iscsi/iscsi_target_erl1.c2
-rw-r--r--drivers/target/iscsi/iscsi_target_tmr.c2
-rw-r--r--drivers/target/loopback/tcm_loop.c4
-rw-r--r--drivers/target/sbp/sbp_target.c3
-rw-r--r--drivers/target/target_core_alua.c1
-rw-r--r--drivers/target/target_core_configfs.c22
-rw-r--r--drivers/target/target_core_device.c1
-rw-r--r--drivers/target/target_core_fabric_configfs.c24
-rw-r--r--drivers/target/target_core_transport.c116
-rw-r--r--drivers/target/tcm_fc/tfc_conf.c3
12 files changed, 121 insertions, 68 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index b516c2893420bc..1d25e64b068a02 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -1234,12 +1234,6 @@ attach_cmd:
spin_lock_bh(&conn->cmd_lock);
list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
spin_unlock_bh(&conn->cmd_lock);
- /*
- * Check if we need to delay processing because of ALUA
- * Active/NonOptimized primary access state..
- */
- core_alua_check_nonop_delay(&cmd->se_cmd);
-
return 0;
}
EXPORT_SYMBOL(iscsit_setup_scsi_cmd);
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index 1cff6052e82021..88db94f382bb92 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -1589,5 +1589,8 @@ const struct target_core_fabric_ops iscsi_ops = {
.tfc_tpg_nacl_auth_attrs = lio_target_nacl_auth_attrs,
.tfc_tpg_nacl_param_attrs = lio_target_nacl_param_attrs,
- .write_pending_must_be_called = true,
+ .write_pending_must_be_called = 1,
+
+ .default_submit_type = TARGET_DIRECT_SUBMIT,
+ .direct_submit_supp = 1,
};
diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c
index f460a66c0e7c50..6797200211836d 100644
--- a/drivers/target/iscsi/iscsi_target_erl1.c
+++ b/drivers/target/iscsi/iscsi_target_erl1.c
@@ -948,7 +948,7 @@ int iscsit_execute_cmd(struct iscsit_cmd *cmd, int ooo)
iscsit_set_unsolicited_dataout(cmd);
}
- return transport_handle_cdb_direct(&cmd->se_cmd);
+ return target_submit(&cmd->se_cmd);
case ISCSI_OP_NOOP_OUT:
case ISCSI_OP_TEXT:
diff --git a/drivers/target/iscsi/iscsi_target_tmr.c b/drivers/target/iscsi/iscsi_target_tmr.c
index afc801f255f5d3..9c4aa01b6351b5 100644
--- a/drivers/target/iscsi/iscsi_target_tmr.c
+++ b/drivers/target/iscsi/iscsi_target_tmr.c
@@ -318,7 +318,7 @@ static int iscsit_task_reassign_complete_read(
pr_debug("READ ITT: 0x%08x: t_state: %d never sent to"
" transport\n", cmd->init_task_tag,
cmd->se_cmd.t_state);
- transport_handle_cdb_direct(se_cmd);
+ target_submit(se_cmd);
return 0;
}
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index 4ec99a55ac305a..8e4035ff367485 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:
@@ -1102,6 +1102,8 @@ static const struct target_core_fabric_ops loop_ops = {
.tfc_wwn_attrs = tcm_loop_wwn_attrs,
.tfc_tpg_base_attrs = tcm_loop_tpg_attrs,
.tfc_tpg_attrib_attrs = tcm_loop_tpg_attrib_attrs,
+ .default_submit_type = TARGET_QUEUE_SUBMIT,
+ .direct_submit_supp = 0,
};
static int __init tcm_loop_fabric_init(void)
diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c
index 2a761bc0919389..b604fcae21e112 100644
--- a/drivers/target/sbp/sbp_target.c
+++ b/drivers/target/sbp/sbp_target.c
@@ -2278,6 +2278,9 @@ static const struct target_core_fabric_ops sbp_ops = {
.tfc_wwn_attrs = sbp_wwn_attrs,
.tfc_tpg_base_attrs = sbp_tpg_base_attrs,
.tfc_tpg_attrib_attrs = sbp_tpg_attrib_attrs,
+
+ .default_submit_type = TARGET_DIRECT_SUBMIT,
+ .direct_submit_supp = 1,
};
static int __init sbp_init(void)
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index 3372856319f72f..01751faad38663 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -850,7 +850,6 @@ int core_alua_check_nonop_delay(
msleep_interruptible(cmd->alua_nonop_delay);
return 0;
}
-EXPORT_SYMBOL(core_alua_check_nonop_delay);
static int core_alua_write_tpg_metadata(
const char *path,
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index d5860c1c1f469e..a5f58988130a15 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 b7ac60f4a21945..0f3fd775fe6dd2 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_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c
index b7c637644cd48d..7156a4dc1ca7d9 100644
--- a/drivers/target/target_core_fabric_configfs.c
+++ b/drivers/target/target_core_fabric_configfs.c
@@ -1065,8 +1065,32 @@ target_fabric_wwn_cmd_completion_affinity_store(struct config_item *item,
}
CONFIGFS_ATTR(target_fabric_wwn_, cmd_completion_affinity);
+static ssize_t
+target_fabric_wwn_default_submit_type_show(struct config_item *item,
+ char *page)
+{
+ struct se_wwn *wwn = container_of(to_config_group(item), struct se_wwn,
+ param_group);
+ return sysfs_emit(page, "%u\n",
+ wwn->wwn_tf->tf_ops->default_submit_type);
+}
+CONFIGFS_ATTR_RO(target_fabric_wwn_, default_submit_type);
+
+static ssize_t
+target_fabric_wwn_direct_submit_supported_show(struct config_item *item,
+ char *page)
+{
+ struct se_wwn *wwn = container_of(to_config_group(item), struct se_wwn,
+ param_group);
+ return sysfs_emit(page, "%u\n",
+ wwn->wwn_tf->tf_ops->direct_submit_supp);
+}
+CONFIGFS_ATTR_RO(target_fabric_wwn_, direct_submit_supported);
+
static struct configfs_attribute *target_fabric_wwn_param_attrs[] = {
&target_fabric_wwn_attr_cmd_completion_affinity,
+ &target_fabric_wwn_attr_default_submit_type,
+ &target_fabric_wwn_attr_direct_submit_supported,
NULL,
};
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 0686882bcbda35..c81def3c96df6b 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1576,17 +1576,39 @@ target_cmd_parse_cdb(struct se_cmd *cmd)
}
EXPORT_SYMBOL(target_cmd_parse_cdb);
-/*
- * Used by fabric module frontends to queue tasks directly.
- * May only be used from process context.
- */
-int transport_handle_cdb_direct(
- struct se_cmd *cmd)
+static int __target_submit(struct se_cmd *cmd)
{
sense_reason_t ret;
might_sleep();
+ /*
+ * Check if we need to delay processing because of ALUA
+ * Active/NonOptimized primary access state..
+ */
+ core_alua_check_nonop_delay(cmd);
+
+ if (cmd->t_data_nents != 0) {
+ /*
+ * This is primarily a hack for udev and tcm loop which sends
+ * INQUIRYs with a single page and expects the data to be
+ * cleared.
+ */
+ if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) &&
+ cmd->data_direction == DMA_FROM_DEVICE) {
+ struct scatterlist *sgl = cmd->t_data_sg;
+ unsigned char *buf = NULL;
+
+ BUG_ON(!sgl);
+
+ buf = kmap_local_page(sg_page(sgl));
+ if (buf) {
+ memset(buf + sgl->offset, 0, sgl->length);
+ kunmap_local(buf);
+ }
+ }
+ }
+
if (!cmd->se_lun) {
dump_stack();
pr_err("cmd->se_lun is NULL\n");
@@ -1614,7 +1636,6 @@ int transport_handle_cdb_direct(
transport_generic_request_failure(cmd, ret);
return 0;
}
-EXPORT_SYMBOL(transport_handle_cdb_direct);
sense_reason_t
transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
@@ -1782,53 +1803,6 @@ generic_fail:
EXPORT_SYMBOL_GPL(target_submit_prep);
/**
- * target_submit - perform final initialization and submit cmd to LIO core
- * @se_cmd: command descriptor to submit
- *
- * target_submit_prep must have been called on the cmd, and this must be
- * called from process context.
- */
-void target_submit(struct se_cmd *se_cmd)
-{
- struct scatterlist *sgl = se_cmd->t_data_sg;
- unsigned char *buf = NULL;
-
- might_sleep();
-
- if (se_cmd->t_data_nents != 0) {
- BUG_ON(!sgl);
- /*
- * A work-around for tcm_loop as some userspace code via
- * scsi-generic do not memset their associated read buffers,
- * so go ahead and do that here for type non-data CDBs. Also
- * note that this is currently guaranteed to be a single SGL
- * for this case by target core in target_setup_cmd_from_cdb()
- * -> transport_generic_cmd_sequencer().
- */
- if (!(se_cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) &&
- se_cmd->data_direction == DMA_FROM_DEVICE) {
- if (sgl)
- buf = kmap(sg_page(sgl)) + sgl->offset;
-
- if (buf) {
- memset(buf, 0, sgl->length);
- kunmap(sg_page(sgl));
- }
- }
-
- }
-
- /*
- * Check if we need to delay processing because of ALUA
- * Active/NonOptimized primary access state..
- */
- core_alua_check_nonop_delay(se_cmd);
-
- transport_handle_cdb_direct(se_cmd);
-}
-EXPORT_SYMBOL_GPL(target_submit);
-
-/**
* target_submit_cmd - lookup unpacked lun and submit uninitialized se_cmd
*
* @se_cmd: command descriptor to submit
@@ -1923,7 +1897,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)
@@ -1934,7 +1908,7 @@ void target_queued_submit_work(struct work_struct *work)
* target_queue_submission - queue the cmd to run on the LIO workqueue
* @se_cmd: command descriptor to submit
*/
-void target_queue_submission(struct se_cmd *se_cmd)
+static void target_queue_submission(struct se_cmd *se_cmd)
{
struct se_device *se_dev = se_cmd->se_dev;
int cpu = se_cmd->cpuid;
@@ -1944,7 +1918,35 @@ void target_queue_submission(struct se_cmd *se_cmd)
llist_add(&se_cmd->se_cmd_list, &sq->cmd_list);
queue_work_on(cpu, target_submission_wq, &sq->work);
}
-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)
{
diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c
index 6ac3fc1a7d39bb..5ee03d1cba2bee 100644
--- a/drivers/target/tcm_fc/tfc_conf.c
+++ b/drivers/target/tcm_fc/tfc_conf.c
@@ -432,6 +432,9 @@ static const struct target_core_fabric_ops ft_fabric_ops = {
.tfc_wwn_attrs = ft_wwn_attrs,
.tfc_tpg_nacl_base_attrs = ft_nacl_base_attrs,
+
+ .default_submit_type = TARGET_DIRECT_SUBMIT,
+ .direct_submit_supp = 1,
};
static struct notifier_block ft_notifier = {