Commit 12e00e52 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Ben Walker
Browse files

ut/scsi: Add tests for improved LUN reset handling



This patch tests the following:
- Reset task will not complete until prior IO tasks complete.
- IO tasks will suspend until prior reset tasks complete.

Change-Id: I8ae27874e7eb34f866bbd4e057ee5d8c27d040e8
Signed-off-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/435433


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent d0e3f624
Loading
Loading
Loading
Loading
+136 −1
Original line number Diff line number Diff line
@@ -45,6 +45,11 @@ struct spdk_bdev {
	int x;
};

/* Unit test poller mockup */
struct spdk_poller {
	int y;
};

SPDK_LOG_REGISTER_COMPONENT("scsi", SPDK_LOG_SCSI)

struct spdk_scsi_globals g_spdk_scsi;
@@ -52,18 +57,22 @@ struct spdk_scsi_globals g_spdk_scsi;
static bool g_lun_execute_fail = false;
static int g_lun_execute_status = SPDK_SCSI_TASK_PENDING;
static uint32_t g_task_count = 0;
static struct spdk_poller g_lun_ut_poller;

struct spdk_poller *
spdk_poller_register(spdk_poller_fn fn,
		     void *arg,
		     uint64_t period_microseconds)
{
	return NULL;
	return &g_lun_ut_poller;
}

void
spdk_poller_unregister(struct spdk_poller **ppoller)
{
	if (ppoller != NULL) {
		*ppoller = NULL;
	}
}

void
@@ -548,6 +557,128 @@ lun_construct_success(void)
	CU_ASSERT_EQUAL(g_task_count, 0);
}

static void
lun_reset_task_wait_scsi_task_complete(void)
{
	struct spdk_scsi_lun *lun;
	struct spdk_scsi_task task = { 0 };
	struct spdk_scsi_task mgmt_task = { 0 };
	struct spdk_scsi_dev dev = { 0 };

	lun = lun_construct();
	lun->dev = &dev;

	ut_init_task(&task);
	task.lun = lun;

	g_lun_execute_fail = false;
	g_lun_execute_status = SPDK_SCSI_TASK_PENDING;

	ut_init_task(&mgmt_task);
	mgmt_task.lun = lun;
	mgmt_task.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;

	/* Append a task to the pending task list. */
	spdk_scsi_lun_append_task(lun, &task);

	CU_ASSERT(!TAILQ_EMPTY(&lun->pending_tasks));

	/* Execute the task but it is still in the task list. */
	spdk_scsi_lun_execute_tasks(lun);

	CU_ASSERT(TAILQ_EMPTY(&lun->pending_tasks));
	CU_ASSERT(!TAILQ_EMPTY(&lun->tasks));

	/* Append a reset task to the pending mgmt task list. */
	spdk_scsi_lun_append_mgmt_task(lun, &mgmt_task);

	CU_ASSERT(!TAILQ_EMPTY(&lun->pending_mgmt_tasks));

	/* Execute the reset task */
	spdk_scsi_lun_execute_mgmt_task(lun);

	/* The reset task should be still on the submitted mgmt task list and
	 * a poller is created because the task prior to the reset task is pending.
	 */
	CU_ASSERT(!TAILQ_EMPTY(&lun->mgmt_tasks));
	CU_ASSERT(lun->reset_poller != NULL);

	/* Execute the poller to check if the task prior to the reset task complete. */
	spdk_scsi_lun_reset_check_outstanding_tasks(&mgmt_task);

	CU_ASSERT(!TAILQ_EMPTY(&lun->mgmt_tasks));
	CU_ASSERT(lun->reset_poller != NULL);

	/* Complete the task. */
	spdk_scsi_lun_complete_task(lun, &task);

	CU_ASSERT(TAILQ_EMPTY(&lun->tasks));

	/* Execute the poller to check if the task prior to the reset task complete. */
	spdk_scsi_lun_reset_check_outstanding_tasks(&mgmt_task);

	CU_ASSERT(TAILQ_EMPTY(&lun->mgmt_tasks));
	CU_ASSERT(lun->reset_poller == NULL);
	CU_ASSERT_EQUAL(mgmt_task.status, SPDK_SCSI_STATUS_GOOD);
	CU_ASSERT_EQUAL(mgmt_task.response, SPDK_SCSI_TASK_MGMT_RESP_SUCCESS);

	lun_destruct(lun);

	CU_ASSERT_EQUAL(g_task_count, 0);
}

static void
lun_reset_task_suspend_scsi_task(void)
{
	struct spdk_scsi_lun *lun;
	struct spdk_scsi_task task = { 0 };
	struct spdk_scsi_task mgmt_task = { 0 };
	struct spdk_scsi_dev dev = { 0 };

	lun = lun_construct();
	lun->dev = &dev;

	ut_init_task(&task);
	task.lun = lun;

	g_lun_execute_fail = false;
	g_lun_execute_status = SPDK_SCSI_TASK_COMPLETE;

	ut_init_task(&mgmt_task);
	mgmt_task.lun = lun;
	mgmt_task.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;

	/* Append a reset task to the pending mgmt task list. */
	spdk_scsi_lun_append_mgmt_task(lun, &mgmt_task);

	CU_ASSERT(!TAILQ_EMPTY(&lun->pending_mgmt_tasks));

	/* Append a task to the pending task list. */
	spdk_scsi_lun_append_task(lun, &task);

	CU_ASSERT(!TAILQ_EMPTY(&lun->pending_tasks));

	/* Execute the task but it is still on the pending task list. */
	spdk_scsi_lun_execute_tasks(lun);

	CU_ASSERT(!TAILQ_EMPTY(&lun->pending_tasks));

	/* Execute the reset task. The task will be executed then. */
	spdk_scsi_lun_execute_mgmt_task(lun);

	CU_ASSERT(TAILQ_EMPTY(&lun->mgmt_tasks));
	CU_ASSERT(lun->reset_poller == NULL);
	CU_ASSERT_EQUAL(mgmt_task.status, SPDK_SCSI_STATUS_GOOD);
	CU_ASSERT_EQUAL(mgmt_task.response, SPDK_SCSI_TASK_MGMT_RESP_SUCCESS);

	CU_ASSERT(TAILQ_EMPTY(&lun->pending_tasks));
	CU_ASSERT(TAILQ_EMPTY(&lun->tasks));

	lun_destruct(lun);

	CU_ASSERT_EQUAL(g_task_count, 0);
}

int
main(int argc, char **argv)
{
@@ -586,6 +717,10 @@ main(int argc, char **argv)
		|| CU_add_test(suite, "destruct task - success", lun_destruct_success) == NULL
		|| CU_add_test(suite, "construct - null ctx", lun_construct_null_ctx) == NULL
		|| CU_add_test(suite, "construct - success", lun_construct_success) == NULL
		|| CU_add_test(suite, "reset task wait for prior task completion",
			       lun_reset_task_wait_scsi_task_complete) == NULL
		|| CU_add_test(suite, "reset task suspend subsequent scsi task",
			       lun_reset_task_suspend_scsi_task) == NULL
	) {
		CU_cleanup_registry();
		return CU_get_error();