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 <ziye.yang@intel.com>
Change-Id: Ia15f56c606e4f97af019f91fa1118cc9cac5daa7
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/5719
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
This commit is contained in:
Ziye Yang 2020-12-29 01:08:27 +08:00 committed by Tomasz Zawadzki
parent 6238e1a2d3
commit 83a544c2a9
2 changed files with 45 additions and 12 deletions

View File

@ -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);
}
}
}

View File

@ -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;