diff --git a/lib/scsi/lun.c b/lib/scsi/lun.c index feb502882..799aac163 100644 --- a/lib/scsi/lun.c +++ b/lib/scsi/lun.c @@ -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; diff --git a/test/unit/lib/scsi/lun.c/lun_ut.c b/test/unit/lib/scsi/lun.c/lun_ut.c index cd1c049e7..d67d60861 100644 --- a/test/unit/lib/scsi/lun.c/lun_ut.c +++ b/test/unit/lib/scsi/lun.c/lun_ut.c @@ -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();