Commit 8287ae78 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Tomasz Zawadzki
Browse files

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: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: I9be3f910ab4bbb99cd399f71dc716a7c40f34fe5
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/474022


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent db91cfe0
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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;
+69 −0
Original line number Diff line number Diff line
@@ -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();