From 83a544c2a961c1e802a51e5a29a80bac957f30f2 Mon Sep 17 00:00:00 2001 From: Ziye Yang Date: Tue, 29 Dec 2020 01:08:27 +0800 Subject: [PATCH] lib/iscsi: Support the Datain pdu sending in out of order case. According to 12.19 in iSCSI 3720. "If DataSequenceInOrder is set to No, Data PDU sequences may be transferred in any order." So if the DataSequence is negotiated with "No", then we can send Datainpdu in out of order manner. And the initiator will handle this case. Signed-off-by: Ziye Yang Change-Id: Ia15f56c606e4f97af019f91fa1118cc9cac5daa7 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/5719 Reviewed-by: Shuhei Matsumoto Reviewed-by: Changpeng Liu Tested-by: SPDK CI Jenkins Community-CI: Mellanox Build Bot --- lib/iscsi/conn.c | 16 ++++++++--- test/unit/lib/iscsi/conn.c/conn_ut.c | 41 ++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/lib/iscsi/conn.c b/lib/iscsi/conn.c index 4b12e56ccb..b303771cb3 100644 --- a/lib/iscsi/conn.c +++ b/lib/iscsi/conn.c @@ -1096,8 +1096,8 @@ iscsi_task_copy_from_rsp_scsi_status(struct spdk_scsi_task *task, } static void -process_completed_read_subtask_list(struct spdk_iscsi_conn *conn, - struct spdk_iscsi_task *primary) +process_completed_read_subtask_list_in_order(struct spdk_iscsi_conn *conn, + struct spdk_iscsi_task *primary) { struct spdk_iscsi_task *subtask, *tmp; @@ -1105,7 +1105,7 @@ process_completed_read_subtask_list(struct spdk_iscsi_conn *conn, if (subtask->scsi.offset == primary->bytes_completed) { TAILQ_REMOVE(&primary->subtask_list, subtask, subtask_link); primary->bytes_completed += subtask->scsi.length; - if (primary->bytes_completed == primary->scsi.transfer_len) { + if (primary->bytes_completed == primary->scsi.transfer_len) { iscsi_task_put(primary); } iscsi_task_response(conn, subtask); @@ -1148,7 +1148,15 @@ process_read_task_completion(struct spdk_iscsi_conn *conn, assert(primary->bytes_completed == task->scsi.transfer_len); iscsi_task_response(conn, task); iscsi_task_put(task); + } else if (!conn->sess->DataSequenceInOrder) { + primary->bytes_completed += task->scsi.length; + if (primary->bytes_completed == primary->scsi.transfer_len) { + iscsi_task_put(primary); + } + iscsi_task_response(conn, task); + iscsi_task_put(task); } else { + if (task->scsi.offset != primary->bytes_completed) { TAILQ_FOREACH(tmp, &primary->subtask_list, subtask_link) { if (task->scsi.offset < tmp->scsi.offset) { @@ -1160,7 +1168,7 @@ process_read_task_completion(struct spdk_iscsi_conn *conn, TAILQ_INSERT_TAIL(&primary->subtask_list, task, subtask_link); } else { TAILQ_INSERT_HEAD(&primary->subtask_list, task, subtask_link); - process_completed_read_subtask_list(conn, primary); + process_completed_read_subtask_list_in_order(conn, primary); } } } diff --git a/test/unit/lib/iscsi/conn.c/conn_ut.c b/test/unit/lib/iscsi/conn.c/conn_ut.c index 5e92df2a81..c9979fc5fb 100644 --- a/test/unit/lib/iscsi/conn.c/conn_ut.c +++ b/test/unit/lib/iscsi/conn.c/conn_ut.c @@ -308,6 +308,11 @@ read_task_split_in_order_case(void) { struct spdk_iscsi_task primary = {}; struct spdk_iscsi_task *task, *tmp; + struct spdk_iscsi_conn conn = {}; + struct spdk_iscsi_sess sess = {}; + + conn.sess = &sess; + conn.sess->DataSequenceInOrder = true; primary.scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 8; TAILQ_INIT(&primary.subtask_list); @@ -320,7 +325,7 @@ read_task_split_in_order_case(void) TAILQ_FOREACH(task, &g_ut_read_tasks, link) { CU_ASSERT(&primary == iscsi_task_get_primary(task)); - process_read_task_completion(NULL, task, &primary); + process_read_task_completion(&conn, task, &primary); } CU_ASSERT(primary.bytes_completed == primary.scsi.transfer_len); @@ -339,6 +344,11 @@ read_task_split_reverse_order_case(void) { struct spdk_iscsi_task primary = {}; struct spdk_iscsi_task *task, *tmp; + struct spdk_iscsi_conn conn = {}; + struct spdk_iscsi_sess sess = {}; + + conn.sess = &sess; + conn.sess->DataSequenceInOrder = true; primary.scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 8; TAILQ_INIT(&primary.subtask_list); @@ -351,7 +361,7 @@ read_task_split_reverse_order_case(void) TAILQ_FOREACH_REVERSE(task, &g_ut_read_tasks, read_tasks_head, link) { CU_ASSERT(&primary == iscsi_task_get_primary(task)); - process_read_task_completion(NULL, task, &primary); + process_read_task_completion(&conn, task, &primary); } CU_ASSERT(primary.bytes_completed == primary.scsi.transfer_len); @@ -370,6 +380,12 @@ propagate_scsi_error_status_for_split_read_tasks(void) struct spdk_iscsi_task primary = {}; struct spdk_iscsi_task task1 = {}, task2 = {}, task3 = {}, task4 = {}, task5 = {}, task6 = {}; + struct spdk_iscsi_conn conn = {}; + struct spdk_iscsi_sess sess = {}; + + conn.sess = &sess; + conn.sess->DataSequenceInOrder = true; + primary.scsi.transfer_len = 512 * 6; primary.rsp_scsi_status = SPDK_SCSI_STATUS_GOOD; TAILQ_INIT(&primary.subtask_list); @@ -415,12 +431,12 @@ propagate_scsi_error_status_for_split_read_tasks(void) * status is propagated to remaining tasks correctly when these tasks complete * by the following order, task4, task3, task2, task1, primary, task5, and task6. */ - process_read_task_completion(NULL, &task4, &primary); - process_read_task_completion(NULL, &task3, &primary); - process_read_task_completion(NULL, &task2, &primary); - process_read_task_completion(NULL, &task1, &primary); - process_read_task_completion(NULL, &task5, &primary); - process_read_task_completion(NULL, &task6, &primary); + process_read_task_completion(&conn, &task4, &primary); + process_read_task_completion(&conn, &task3, &primary); + process_read_task_completion(&conn, &task2, &primary); + process_read_task_completion(&conn, &task1, &primary); + process_read_task_completion(&conn, &task5, &primary); + process_read_task_completion(&conn, &task6, &primary); CU_ASSERT(primary.rsp_scsi_status == SPDK_SCSI_STATUS_CHECK_CONDITION); CU_ASSERT(task1.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION); @@ -725,6 +741,11 @@ abort_queued_datain_task_test(void) struct iscsi_bhs_scsi_req *scsi_req; int rc; + struct spdk_iscsi_sess sess = {}; + + conn.sess = &sess; + conn.sess->DataSequenceInOrder = true; + TAILQ_INIT(&conn.queued_datain_tasks); task.scsi.ref = 1; task.scsi.dxfer_dir = SPDK_SCSI_DIR_FROM_DEV; @@ -808,10 +829,14 @@ abort_queued_datain_tasks_test(void) uint32_t alloc_cmd_sn; struct iscsi_bhs_scsi_req *scsi_req; int rc; + struct spdk_iscsi_sess sess = {}; TAILQ_INIT(&conn.queued_datain_tasks); conn.data_in_cnt = 0; + conn.sess = &sess; + conn.sess->DataSequenceInOrder = true; + g_new_task = &subtask; alloc_cmd_sn = 88;