Commit 39037ac5 authored by Joel Cunningham's avatar Joel Cunningham Committed by Tomasz Zawadzki
Browse files

test/unit/nvmf: add test for preempt self



Add unit test for a host preempting itself after acquiring a
reservation.

For preempt-and-abort, validate we don't self-abort

Change-Id: I4754da802a39ecab47d40fecba7c459e65bcfcc6
Signed-off-by: default avatarJoel Cunningham <joel.cunningham@oracle.com>
Reviewed-on: https://review.spdk.io/c/spdk/spdk/+/26675


Tested-by: default avatarSPDK Automated Test System <spdkbot@gmail.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarChangpeng Liu <changpeliu@tencent.com>
Reviewed-by: default avatarJim Harris <jim.harris@nvidia.com>
parent 890c91a2
Loading
Loading
Loading
Loading
+109 −0
Original line number Diff line number Diff line
@@ -1345,6 +1345,113 @@ test_reservation_acquire_preempt_no_holder(enum spdk_nvme_reservation_acquire_ac
	ut_reservation_deinit();
}

static void
test_reservation_acquire_preempt_self(enum spdk_nvme_reservation_acquire_action preempt_type)
{
	struct spdk_nvmf_request *req;
	struct spdk_nvme_cpl *rsp;
	struct spdk_nvmf_registrant *reg;
	uint32_t gen;
	bool is_abort = (preempt_type == SPDK_NVME_RESERVE_PREEMPT_ABORT);
	uint64_t akey = 0xa1;
	uint64_t bkey = 0xb1;

	printf("Executing test: %s with acquire type: %d\n", __func__, preempt_type);

	ut_reservation_init();

	req = ut_reservation_build_req(16);
	rsp = &req->rsp->nvme_cpl;
	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
	SPDK_CU_ASSERT_FATAL(req != NULL);

	ut_reservation_build_registrants();

	/* A acquire */
	gen = g_ns.gen;
	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, akey, 0x0);
	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
	SPDK_CU_ASSERT_FATAL(g_ns.crkey == akey);
	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
	SPDK_CU_ASSERT_FATAL(g_ns.preempt_abort == NULL);

	/* A premepts self */
	ut_reservation_build_acquire_request(req, preempt_type, 0,
					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, akey, akey);
	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
	/* Registration is maintained and reservation updated */
	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
	SPDK_CU_ASSERT_FATAL(reg != NULL);
	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
	if (is_abort) {
		/* We won't self-abort, so no hostid */
		SPDK_CU_ASSERT_FATAL(g_ns.preempt_abort);
		SPDK_CU_ASSERT_FATAL(g_ns.preempt_abort->hostids_cnt == 0);
		SPDK_CU_ASSERT_FATAL(g_ns.preempt_abort->hostids_gen == 1);
	} else {
		SPDK_CU_ASSERT_FATAL(g_ns.preempt_abort == NULL);
	}

	/* B preempts A with WRITE_EXCLUSIVE */
	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
	gen = g_ns.gen;
	ut_reservation_build_acquire_request(req, preempt_type, 0,
					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, bkey, akey);
	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
	/* B maintains registration and preempts */
	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
	SPDK_CU_ASSERT_FATAL(reg != NULL);
	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
	/* A will lose reservation and registration */
	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
	SPDK_CU_ASSERT_FATAL(reg == NULL);
	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
	SPDK_CU_ASSERT_FATAL(g_ns.gen - gen == 1);
	if (is_abort) {
		SPDK_CU_ASSERT_FATAL(g_ns.preempt_abort);
		SPDK_CU_ASSERT_FATAL(g_ns.preempt_abort->hostids_cnt == 1);
		SPDK_CU_ASSERT_FATAL(g_ns.preempt_abort->hostids_gen == 2);
		SPDK_CU_ASSERT_FATAL(hostid_list_contains_id(g_ns.preempt_abort->hostids,
				     g_ns.preempt_abort->hostids_cnt, &g_ctrlr1_A.hostid));
	} else {
		SPDK_CU_ASSERT_FATAL(g_ns.preempt_abort == NULL);
	}

	/* B premepts self */
	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
	gen = g_ns.gen;
	ut_reservation_build_acquire_request(req, preempt_type, 0,
					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, bkey, bkey);
	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
	/* Registration is maintained and reservation updated */
	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
	SPDK_CU_ASSERT_FATAL(reg != NULL);
	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
	if (is_abort) {
		/* We won't self-abort, so no hostid */
		SPDK_CU_ASSERT_FATAL(g_ns.preempt_abort);
		SPDK_CU_ASSERT_FATAL(g_ns.preempt_abort->hostids_cnt == 0);
		SPDK_CU_ASSERT_FATAL(g_ns.preempt_abort->hostids_gen == 3);
	} else {
		SPDK_CU_ASSERT_FATAL(g_ns.preempt_abort == NULL);
	}

	ut_reservation_free_req(req);
	ut_reservation_deinit();
}

static void
test_reservation_acquire_preempt(void)
{
@@ -1355,6 +1462,8 @@ test_reservation_acquire_preempt(void)
	test_reservation_acquire_preempt_basic(SPDK_NVME_RESERVE_PREEMPT_ABORT);
	test_reservation_acquire_preempt_no_holder(SPDK_NVME_RESERVE_PREEMPT);
	test_reservation_acquire_preempt_no_holder(SPDK_NVME_RESERVE_PREEMPT_ABORT);
	test_reservation_acquire_preempt_self(SPDK_NVME_RESERVE_PREEMPT);
	test_reservation_acquire_preempt_self(SPDK_NVME_RESERVE_PREEMPT_ABORT);
}

static void