iscsi: Abort queued datain tasks before submitting abort task set to SCSI layer

This patch is for ABORT TASK SET and LUN RESET.

iSCSI layer doesn't have pending queue and hence if the target task
is read task and is queued in queued_datain_tasks, it must be
aborted before submitting ABORT TASK to SCSI layer.

Aborting the target task may not complete by an iteration because
submitted read tasks are limited. Hence use poller to complete abortion
by repetition.

Change-Id: Idabf4931d751ee698e9809eafd5c151b979f048b
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/436077
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Shuhei Matsumoto 2018-12-10 08:17:59 +09:00 committed by Ben Walker
parent 5124f87f4e
commit a207f575fb
2 changed files with 200 additions and 6 deletions

View File

@ -3229,6 +3229,31 @@ spdk_iscsi_conn_abort_queued_datain_task(struct spdk_iscsi_conn *conn,
return 0;
}
static int
spdk_iscsi_conn_abort_queued_datain_tasks(struct spdk_iscsi_conn *conn,
struct spdk_scsi_lun *lun,
struct spdk_iscsi_pdu *pdu)
{
struct spdk_iscsi_task *task, *task_tmp;
struct spdk_iscsi_pdu *pdu_tmp;
int rc;
assert(pdu != NULL);
TAILQ_FOREACH_SAFE(task, &conn->queued_datain_tasks, link, task_tmp) {
pdu_tmp = spdk_iscsi_task_get_pdu(task);
if ((lun == NULL || lun == task->scsi.lun) &&
(SN32_LT(pdu_tmp->cmd_sn, pdu->cmd_sn))) {
rc = _spdk_iscsi_conn_abort_queued_datain_task(conn, task);
if (rc != 0) {
return rc;
}
}
}
return 0;
}
static int
_spdk_iscsi_op_abort_task(void *arg)
{
@ -3254,6 +3279,30 @@ spdk_iscsi_op_abort_task(struct spdk_iscsi_task *task, uint32_t ref_task_tag)
task->mgmt_poller = spdk_poller_register(_spdk_iscsi_op_abort_task, task, 10);
}
static int
_spdk_iscsi_op_abort_task_set(void *arg)
{
struct spdk_iscsi_task *task = arg;
int rc;
rc = spdk_iscsi_conn_abort_queued_datain_tasks(task->conn, task->scsi.lun,
task->pdu);
if (rc != 0) {
return 0;
}
spdk_poller_unregister(&task->mgmt_poller);
spdk_iscsi_queue_mgmt_task(task->conn, task);
return 1;
}
static void
spdk_iscsi_op_abort_task_set(struct spdk_iscsi_task *task, uint8_t function)
{
task->scsi.function = function;
task->mgmt_poller = spdk_poller_register(_spdk_iscsi_op_abort_task_set, task, 10);
}
static int
spdk_iscsi_op_task(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
{
@ -3318,9 +3367,7 @@ spdk_iscsi_op_task(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
case ISCSI_TASK_FUNC_ABORT_TASK_SET:
SPDK_NOTICELOG("ABORT_TASK_SET\n");
task->scsi.function = SPDK_SCSI_TASK_FUNC_ABORT_TASK_SET;
spdk_iscsi_queue_mgmt_task(conn, task);
spdk_iscsi_op_abort_task_set(task, SPDK_SCSI_TASK_FUNC_ABORT_TASK_SET);
return SPDK_SUCCESS;
case ISCSI_TASK_FUNC_CLEAR_TASK_SET:
@ -3336,9 +3383,7 @@ spdk_iscsi_op_task(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
case ISCSI_TASK_FUNC_LOGICAL_UNIT_RESET:
SPDK_NOTICELOG("LOGICAL_UNIT_RESET\n");
task->scsi.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
spdk_iscsi_queue_mgmt_task(conn, task);
spdk_iscsi_op_abort_task_set(task, SPDK_SCSI_TASK_FUNC_LUN_RESET);
return SPDK_SUCCESS;
case ISCSI_TASK_FUNC_TARGET_WARM_RESET:

View File

@ -1070,6 +1070,153 @@ abort_queued_datain_task_test(void)
CU_ASSERT(TAILQ_EMPTY(&conn.queued_datain_tasks));
}
static bool
datain_task_is_queued(struct spdk_iscsi_conn *conn,
struct spdk_iscsi_task *task)
{
struct spdk_iscsi_task *tmp;
TAILQ_FOREACH(tmp, &conn->queued_datain_tasks, link) {
if (tmp == task) {
return true;
}
}
return false;
}
static void
abort_queued_datain_tasks_test(void)
{
struct spdk_iscsi_conn conn;
struct spdk_iscsi_task *task1, *task2, *task3, *task4, *task5, *task6;
struct spdk_iscsi_task *task, *tmp;
struct spdk_iscsi_pdu *pdu1, *pdu2, *pdu3, *pdu4, *pdu5, *pdu6;
struct spdk_iscsi_pdu *mgmt_pdu1, *mgmt_pdu2;
struct spdk_scsi_lun lun1, lun2;
uint32_t alloc_cmd_sn;
int rc;
TAILQ_INIT(&conn.queued_datain_tasks);
conn.data_in_cnt = 0;
alloc_cmd_sn = 88;
task1 = spdk_iscsi_task_get(&conn, NULL, NULL);
SPDK_CU_ASSERT_FATAL(task1 != NULL);
pdu1 = spdk_get_pdu();
SPDK_CU_ASSERT_FATAL(pdu1 != NULL);
pdu1->cmd_sn = alloc_cmd_sn;
alloc_cmd_sn++;
task1->current_datain_offset = 0;
task1->scsi.lun = &lun1;
spdk_iscsi_task_set_pdu(task1, pdu1);
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task1, link);
task2 = spdk_iscsi_task_get(&conn, NULL, NULL);
SPDK_CU_ASSERT_FATAL(task2 != NULL);
pdu2 = spdk_get_pdu();
SPDK_CU_ASSERT_FATAL(pdu2 != NULL);
pdu2->cmd_sn = alloc_cmd_sn;
alloc_cmd_sn++;
task2->current_datain_offset = 0;
task2->scsi.lun = &lun2;
spdk_iscsi_task_set_pdu(task2, pdu2);
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task2, link);
mgmt_pdu1 = spdk_get_pdu();
SPDK_CU_ASSERT_FATAL(mgmt_pdu1 != NULL);
mgmt_pdu1->cmd_sn = alloc_cmd_sn;
alloc_cmd_sn++;
task3 = spdk_iscsi_task_get(&conn, NULL, NULL);
SPDK_CU_ASSERT_FATAL(task3 != NULL);
pdu3 = spdk_get_pdu();
SPDK_CU_ASSERT_FATAL(pdu3 != NULL);
pdu3->cmd_sn = alloc_cmd_sn;
alloc_cmd_sn++;
task3->current_datain_offset = 0;
task3->scsi.lun = &lun1;
spdk_iscsi_task_set_pdu(task3, pdu3);
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task3, link);
task4 = spdk_iscsi_task_get(&conn, NULL, NULL);
SPDK_CU_ASSERT_FATAL(task4 != NULL);
pdu4 = spdk_get_pdu();
SPDK_CU_ASSERT_FATAL(pdu4 != NULL);
pdu4->cmd_sn = alloc_cmd_sn;
alloc_cmd_sn++;
task4->current_datain_offset = 0;
task4->scsi.lun = &lun2;
spdk_iscsi_task_set_pdu(task4, pdu4);
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task4, link);
task5 = spdk_iscsi_task_get(&conn, NULL, NULL);
SPDK_CU_ASSERT_FATAL(task5 != NULL);
pdu5 = spdk_get_pdu();
SPDK_CU_ASSERT_FATAL(pdu5 != NULL);
pdu5->cmd_sn = alloc_cmd_sn;
alloc_cmd_sn++;
task5->current_datain_offset = 0;
task5->scsi.lun = &lun1;
spdk_iscsi_task_set_pdu(task5, pdu5);
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task5, link);
mgmt_pdu2 = spdk_get_pdu();
SPDK_CU_ASSERT_FATAL(mgmt_pdu2 != NULL);
mgmt_pdu2->cmd_sn = alloc_cmd_sn;
alloc_cmd_sn++;
task6 = spdk_iscsi_task_get(&conn, NULL, NULL);
SPDK_CU_ASSERT_FATAL(task6 != NULL);
pdu6 = spdk_get_pdu();
SPDK_CU_ASSERT_FATAL(pdu6 != NULL);
pdu6->cmd_sn = alloc_cmd_sn;
alloc_cmd_sn++;
task6->current_datain_offset = 0;
task6->scsi.lun = &lun2;
spdk_iscsi_task_set_pdu(task6, pdu6);
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task6, link);
rc = spdk_iscsi_conn_abort_queued_datain_tasks(&conn, &lun1, mgmt_pdu1);
CU_ASSERT(rc == 0);
CU_ASSERT(!datain_task_is_queued(&conn, task1));
CU_ASSERT(datain_task_is_queued(&conn, task2));
CU_ASSERT(datain_task_is_queued(&conn, task3));
CU_ASSERT(datain_task_is_queued(&conn, task4));
CU_ASSERT(datain_task_is_queued(&conn, task5));
CU_ASSERT(datain_task_is_queued(&conn, task6));
rc = spdk_iscsi_conn_abort_queued_datain_tasks(&conn, &lun2, mgmt_pdu2);
CU_ASSERT(rc == 0);
CU_ASSERT(!datain_task_is_queued(&conn, task2));
CU_ASSERT(datain_task_is_queued(&conn, task3));
CU_ASSERT(!datain_task_is_queued(&conn, task4));
CU_ASSERT(datain_task_is_queued(&conn, task5));
CU_ASSERT(datain_task_is_queued(&conn, task6));
TAILQ_FOREACH_SAFE(task, &conn.queued_datain_tasks, link, tmp) {
TAILQ_REMOVE(&conn.queued_datain_tasks, task, link);
spdk_iscsi_task_cpl(&task->scsi);
}
spdk_put_pdu(mgmt_pdu2);
spdk_put_pdu(mgmt_pdu1);
spdk_put_pdu(pdu6);
spdk_put_pdu(pdu5);
spdk_put_pdu(pdu4);
spdk_put_pdu(pdu3);
spdk_put_pdu(pdu2);
spdk_put_pdu(pdu1);
}
int
main(int argc, char **argv)
{
@ -1104,6 +1251,8 @@ main(int argc, char **argv)
clear_all_transfer_tasks_test) == NULL
|| CU_add_test(suite, "abort_queued_datain_task_test",
abort_queued_datain_task_test) == NULL
|| CU_add_test(suite, "abort_queued_datain_tasks_test",
abort_queued_datain_tasks_test) == NULL
) {
CU_cleanup_registry();
return CU_get_error();