summaryrefslogtreecommitdiff
path: root/drivers/target/target_core_transport.c
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2023-10-13 22:56:37 +0300
committerMartin K. Petersen <martin.petersen@oracle.com>2023-10-13 22:56:37 +0300
commit1caddfc5816e4bf55cf7962775e6ed509ddfdf9b (patch)
treee6d5b7166dc0c320a939825b2cfcda58d20d5d27 /drivers/target/target_core_transport.c
parent9f4c887fe64e27413509979b5be3fb2630d813ba (diff)
parent6dbc829d101d9edb41081de01968792a009c9a78 (diff)
downloadlinux-1caddfc5816e4bf55cf7962775e6ed509ddfdf9b.tar.xz
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/target_core_transport.c')
-rw-r--r--drivers/target/target_core_transport.c116
1 files changed, 59 insertions, 57 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 0686882bcbda..c81def3c96df 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)
{