lib/iscsi: Stop splitting immediately when aborting SCSI read I/O

We changed read I/O submission to stop splitting when detecting LUN
hotplug very recently. We can do the same refinement for read I/O
abortion.

In _iscsi_conn_abort_queued_datain_task(), set all remaining length
to the new task and complete it immediately. We keep the code to
process the case that queued_datain_task completed but is still in
queue, but we can change its if condition to assert.

Simplify the corresponding unit tests accordingly, and set
task->scsi.transfer_len in abort_queued_datain_tasks_test() to
exercise the changed paths.

In iscsi_pdu_payload_po_scsi_read(), if task->scsi.transfer_len is not
larger than SPDK_BDEV_LARGE_BUF_MAX_SIZE, no minimum calculation is
necessary and we can substitute task->scsi.transfer_len to
task->scsi.length simply.  This change is too small to be an independent
patch and is done together.

Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: Iea93e51b103eae141a007a0abdaf13cbe6d5287f
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/476984
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Community-CI: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Shuhei Matsumoto 2019-12-10 19:20:31 -05:00 committed by Tomasz Zawadzki
parent bed4cdf6c7
commit 19eb63fcad
2 changed files with 40 additions and 74 deletions

View File

@ -3260,7 +3260,7 @@ iscsi_pdu_payload_op_scsi_read(struct spdk_iscsi_conn *conn, struct spdk_iscsi_t
if (task->scsi.transfer_len <= SPDK_BDEV_LARGE_BUF_MAX_SIZE) {
task->parent = NULL;
task->scsi.offset = 0;
task->scsi.length = DMIN32(SPDK_BDEV_LARGE_BUF_MAX_SIZE, task->scsi.transfer_len);
task->scsi.length = task->scsi.transfer_len;
spdk_scsi_task_set_data(&task->scsi, NULL, 0);
iscsi_queue_task(conn, task);
@ -3562,15 +3562,18 @@ _iscsi_conn_abort_queued_datain_task(struct spdk_iscsi_conn *conn,
struct spdk_iscsi_task *subtask;
uint32_t remaining_size;
while (conn->data_in_cnt < MAX_LARGE_DATAIN_PER_CONNECTION) {
if (conn->data_in_cnt >= MAX_LARGE_DATAIN_PER_CONNECTION) {
return -1;
}
assert(task->current_datain_offset <= task->scsi.transfer_len);
/* If any IO is submitted already, abort all subtasks by repetition. */
/* Stop split and abort read I/O for remaining data. */
if (task->current_datain_offset < task->scsi.transfer_len) {
remaining_size = task->scsi.transfer_len - task->current_datain_offset;
subtask = spdk_iscsi_task_get(conn, task, spdk_iscsi_task_cpl);
assert(subtask != NULL);
subtask->scsi.offset = task->current_datain_offset;
subtask->scsi.length = DMIN32(SPDK_BDEV_LARGE_BUF_MAX_SIZE, remaining_size);
subtask->scsi.length = remaining_size;
spdk_scsi_task_set_data(&subtask->scsi, NULL, 0);
task->current_datain_offset += subtask->scsi.length;
@ -3579,15 +3582,13 @@ _iscsi_conn_abort_queued_datain_task(struct spdk_iscsi_conn *conn,
spdk_iscsi_task_cpl(&subtask->scsi);
}
/* Remove the primary task from the list if this is the last subtask */
if (task->current_datain_offset == task->scsi.transfer_len) {
/* Remove the primary task from the list because all subtasks are submitted
* or aborted.
*/
assert(task->current_datain_offset == task->scsi.transfer_len);
TAILQ_REMOVE(&conn->queued_datain_tasks, task, link);
return 0;
}
}
return -1;
}
static int
iscsi_conn_abort_queued_datain_task(struct spdk_iscsi_conn *conn,

View File

@ -1105,7 +1105,7 @@ static void
abort_queued_datain_task_test(void)
{
struct spdk_iscsi_conn conn = {};
struct spdk_iscsi_task *task, *task2, *task3;
struct spdk_iscsi_task *task;
int rc;
TAILQ_INIT(&conn.queued_datain_tasks);
@ -1124,18 +1124,17 @@ abort_queued_datain_task_test(void)
rc = _iscsi_conn_abort_queued_datain_task(&conn, task);
CU_ASSERT(rc != 0);
CU_ASSERT(!TAILQ_EMPTY(&conn.queued_datain_tasks));
assert(conn.data_in_cnt == MAX_LARGE_DATAIN_PER_CONNECTION);
/* havs slots for sub read tasks */
conn.data_in_cnt = 0;
rc = _iscsi_conn_abort_queued_datain_task(&conn, task);
CU_ASSERT(rc == 0);
CU_ASSERT(TAILQ_EMPTY(&conn.queued_datain_tasks));
assert(conn.data_in_cnt == 0);
CU_ASSERT(task->current_datain_offset == SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3);
/* Case2: Queue one task, and this task is partially executed,
* and the slot of sub read tasks are full
*/
/* Case2: Queue one task, and this task is partially executed */
/* No slots for sub read tasks */
conn.data_in_cnt = MAX_LARGE_DATAIN_PER_CONNECTION;
task->scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3;
task->current_datain_offset = SPDK_BDEV_LARGE_BUF_MAX_SIZE;
@ -1143,55 +1142,15 @@ abort_queued_datain_task_test(void)
rc = _iscsi_conn_abort_queued_datain_task(&conn, task);
CU_ASSERT(rc != 0);
CU_ASSERT(!TAILQ_EMPTY(&conn.queued_datain_tasks));
/* Case3: Queue one task, and this task is partially executed,
* and the slot of sub read tasks is not full.
*/
conn.data_in_cnt = MAX_LARGE_DATAIN_PER_CONNECTION - 2;
/* have slots for sub read tasks */
conn.data_in_cnt = 0;
rc = _iscsi_conn_abort_queued_datain_task(&conn, task);
CU_ASSERT(rc == 0);
assert(conn.data_in_cnt == MAX_LARGE_DATAIN_PER_CONNECTION - 2);
CU_ASSERT(TAILQ_EMPTY(&conn.queued_datain_tasks));
/* Case4: Queue three tasks and abort each task sequentially */
conn.data_in_cnt = 0;
task->tag = 1;
task->scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3;
task->current_datain_offset = 0;
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task, link);
task2 = spdk_iscsi_task_get(&conn, NULL, NULL);
SPDK_CU_ASSERT_FATAL(task2 != NULL);
task2->tag = 2;
task2->scsi.dxfer_dir = SPDK_SCSI_DIR_FROM_DEV;
task2->scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 4;
task2->current_datain_offset = SPDK_BDEV_LARGE_BUF_MAX_SIZE;
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task2, link);
task3 = spdk_iscsi_task_get(&conn, NULL, NULL);
SPDK_CU_ASSERT_FATAL(task3 != NULL);
task3->tag = 3;
task3->scsi.dxfer_dir = SPDK_SCSI_DIR_FROM_DEV;
task3->scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 5;
task3->current_datain_offset = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 2;
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task3, link);
rc = iscsi_conn_abort_queued_datain_task(&conn, 1);
CU_ASSERT(rc == 0);
rc = iscsi_conn_abort_queued_datain_task(&conn, 2);
CU_ASSERT(rc == 0);
rc = iscsi_conn_abort_queued_datain_task(&conn, 3);
CU_ASSERT(rc == 0);
CU_ASSERT(TAILQ_EMPTY(&conn.queued_datain_tasks));
assert(conn.data_in_cnt == 0);
CU_ASSERT(task->current_datain_offset == SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3);
spdk_iscsi_task_cpl(&task->scsi);
spdk_iscsi_task_cpl(&task2->scsi);
spdk_iscsi_task_cpl(&task3->scsi);
}
static bool
@ -1233,6 +1192,7 @@ abort_queued_datain_tasks_test(void)
pdu1->cmd_sn = alloc_cmd_sn;
alloc_cmd_sn++;
task1->current_datain_offset = 0;
task1->scsi.transfer_len = 512;
task1->scsi.lun = &lun1;
spdk_iscsi_task_set_pdu(task1, pdu1);
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task1, link);
@ -1245,6 +1205,7 @@ abort_queued_datain_tasks_test(void)
pdu2->cmd_sn = alloc_cmd_sn;
alloc_cmd_sn++;
task2->current_datain_offset = 0;
task2->scsi.transfer_len = 512;
task2->scsi.lun = &lun2;
spdk_iscsi_task_set_pdu(task2, pdu2);
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task2, link);
@ -1263,6 +1224,7 @@ abort_queued_datain_tasks_test(void)
pdu3->cmd_sn = alloc_cmd_sn;
alloc_cmd_sn++;
task3->current_datain_offset = 0;
task3->scsi.transfer_len = 512;
task3->scsi.lun = &lun1;
spdk_iscsi_task_set_pdu(task3, pdu3);
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task3, link);
@ -1275,6 +1237,7 @@ abort_queued_datain_tasks_test(void)
pdu4->cmd_sn = alloc_cmd_sn;
alloc_cmd_sn++;
task4->current_datain_offset = 0;
task4->scsi.transfer_len = 512;
task4->scsi.lun = &lun2;
spdk_iscsi_task_set_pdu(task4, pdu4);
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task4, link);
@ -1287,6 +1250,7 @@ abort_queued_datain_tasks_test(void)
pdu5->cmd_sn = alloc_cmd_sn;
alloc_cmd_sn++;
task5->current_datain_offset = 0;
task5->scsi.transfer_len = 512;
task5->scsi.lun = &lun1;
spdk_iscsi_task_set_pdu(task5, pdu5);
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task5, link);
@ -1305,6 +1269,7 @@ abort_queued_datain_tasks_test(void)
pdu6->cmd_sn = alloc_cmd_sn;
alloc_cmd_sn++;
task6->current_datain_offset = 0;
task6->scsi.transfer_len = 512;
task6->scsi.lun = &lun2;
spdk_iscsi_task_set_pdu(task6, pdu6);
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task6, link);