lib/scsi: Abort management tasks being queued when removing LUN

SCSI management task is for SCSI tasks which is submitted after it,
and all such SCSI tasks are aborted by the last patch when we
remove LUN dynamically. Hence we can abort all SCSI management tasks
being queued when removing LUN.

Add simple unit tests too.

Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: I9be3f910ab4bbb99cd399f71dc716a7c40f34fe5
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/474022
Tested-by: SPDK CI Jenkins <sys_sgci@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 2019-11-13 08:34:44 +09:00 committed by Tomasz Zawadzki
parent db91cfe045
commit 8287ae7814
2 changed files with 75 additions and 0 deletions

View File

@ -119,6 +119,12 @@ _scsi_lun_execute_mgmt_task(struct spdk_scsi_lun *lun,
{
TAILQ_INSERT_TAIL(&lun->mgmt_tasks, task, scsi_link);
if (lun->removed) {
task->response = SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN;
scsi_lun_complete_mgmt_task(lun, task);
return;
}
switch (task->function) {
case SPDK_SCSI_TASK_FUNC_ABORT_TASK:
task->response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED;

View File

@ -666,6 +666,73 @@ lun_check_pending_tasks_only_for_specific_initiator(void)
scsi_lun_remove(lun);
}
static void
abort_pending_mgmt_tasks_when_lun_is_removed(void)
{
struct spdk_bdev bdev = {};
struct spdk_scsi_lun *lun;
struct spdk_scsi_task task1, task2, task3;
lun = spdk_scsi_lun_construct(&bdev, NULL, NULL);
/* Normal case */
ut_init_task(&task1);
ut_init_task(&task2);
ut_init_task(&task3);
task1.lun = lun;
task2.lun = lun;
task3.lun = lun;
task1.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
task2.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
task3.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
CU_ASSERT(g_task_count == 3);
spdk_scsi_lun_append_mgmt_task(lun, &task1);
spdk_scsi_lun_append_mgmt_task(lun, &task2);
spdk_scsi_lun_append_mgmt_task(lun, &task3);
CU_ASSERT(!TAILQ_EMPTY(&lun->pending_mgmt_tasks));
spdk_scsi_lun_execute_mgmt_task(lun);
CU_ASSERT(TAILQ_EMPTY(&lun->pending_mgmt_tasks));
CU_ASSERT(TAILQ_EMPTY(&lun->mgmt_tasks));
CU_ASSERT(g_task_count == 0);
CU_ASSERT(task1.response == SPDK_SCSI_TASK_MGMT_RESP_SUCCESS);
CU_ASSERT(task2.response == SPDK_SCSI_TASK_MGMT_RESP_SUCCESS);
CU_ASSERT(task3.response == SPDK_SCSI_TASK_MGMT_RESP_SUCCESS);
/* LUN hotplug case */
ut_init_task(&task1);
ut_init_task(&task2);
ut_init_task(&task3);
task1.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
task2.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
task3.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
CU_ASSERT(g_task_count == 3);
spdk_scsi_lun_append_mgmt_task(lun, &task1);
spdk_scsi_lun_append_mgmt_task(lun, &task2);
spdk_scsi_lun_append_mgmt_task(lun, &task3);
CU_ASSERT(!TAILQ_EMPTY(&lun->pending_mgmt_tasks));
lun->removed = true;
spdk_scsi_lun_execute_mgmt_task(lun);
CU_ASSERT(TAILQ_EMPTY(&lun->pending_mgmt_tasks));
CU_ASSERT(TAILQ_EMPTY(&lun->mgmt_tasks));
CU_ASSERT(g_task_count == 0);
CU_ASSERT(task1.response == SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN);
CU_ASSERT(task2.response == SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN);
CU_ASSERT(task3.response == SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN);
scsi_lun_remove(lun);
}
int
main(int argc, char **argv)
{
@ -710,6 +777,8 @@ main(int argc, char **argv)
lun_reset_task_suspend_scsi_task) == NULL
|| CU_add_test(suite, "check pending tasks only for specific initiator",
lun_check_pending_tasks_only_for_specific_initiator) == NULL
|| CU_add_test(suite, "abort_pending_mgmt_tasks_when_lun_is_removed",
abort_pending_mgmt_tasks_when_lun_is_removed) == NULL
) {
CU_cleanup_registry();
return CU_get_error();