From 24e012c0828a891e2b6072c0ac77a73f09969475 Mon Sep 17 00:00:00 2001 From: Changpeng Liu Date: Tue, 19 Mar 2019 18:05:38 +0800 Subject: [PATCH] UT/nvmf: add reservation filter check Unit test Change-Id: I16136f9a622c23dc232629981110a1ff07593035 Signed-off-by: Changpeng Liu Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/448346 Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Ben Walker --- test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c | 223 +++++++++++++++++++++++++- 1 file changed, 222 insertions(+), 1 deletion(-) diff --git a/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c b/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c index daae322d8..8b8aa5265 100644 --- a/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c +++ b/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c @@ -819,6 +819,221 @@ test_identify_ns(void) CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata))); } +/* + * Reservation Unit Test Configuration + * -------- -------- -------- + * | Host A | | Host B | | Host C | + * -------- -------- -------- + * / \ | | + * -------- -------- ------- ------- + * |Ctrlr1_A| |Ctrlr2_A| |Ctrlr_B| |Ctrlr_C| + * -------- -------- ------- ------- + * \ \ / / + * \ \ / / + * \ \ / / + * -------------------------------------- + * | NAMESPACE 1 | + * -------------------------------------- + */ + +static struct spdk_nvmf_ctrlr g_ctrlr1_A, g_ctrlr2_A, g_ctrlr_B, g_ctrlr_C; +struct spdk_nvmf_subsystem_pg_ns_info g_ns_info; + +static void +ut_reservation_init(enum spdk_nvme_reservation_type rtype) +{ + /* Host A has two controllers */ + spdk_uuid_generate(&g_ctrlr1_A.hostid); + spdk_uuid_copy(&g_ctrlr2_A.hostid, &g_ctrlr1_A.hostid); + + /* Host B has 1 controller */ + spdk_uuid_generate(&g_ctrlr_B.hostid); + + /* Host C has 1 controller */ + spdk_uuid_generate(&g_ctrlr_C.hostid); + + memset(&g_ns_info, 0, sizeof(g_ns_info)); + g_ns_info.rtype = rtype; + g_ns_info.reg_hostid[0] = g_ctrlr1_A.hostid; + g_ns_info.reg_hostid[1] = g_ctrlr_B.hostid; + g_ns_info.reg_hostid[2] = g_ctrlr_C.hostid; +} + +static void +test_reservation_write_exclusive(void) +{ + struct spdk_nvmf_request req = {}; + union nvmf_h2c_msg cmd = {}; + union nvmf_c2h_msg rsp = {}; + int rc; + + req.cmd = &cmd; + req.rsp = &rsp; + + /* Host A holds reservation with type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE */ + ut_reservation_init(SPDK_NVME_RESERVE_WRITE_EXCLUSIVE); + g_ns_info.holder_id = g_ctrlr1_A.hostid; + + /* Test Case: Issue a Read command from Host A and Host B */ + cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr1_A, &req); + SPDK_CU_ASSERT_FATAL(rc == 0); + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); + SPDK_CU_ASSERT_FATAL(rc == 0); + + /* Test Case: Issue a DSM Write command from Host A and Host B */ + cmd.nvme_cmd.opc = SPDK_NVME_OPC_DATASET_MANAGEMENT; + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr1_A, &req); + SPDK_CU_ASSERT_FATAL(rc == 0); + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); + SPDK_CU_ASSERT_FATAL(rc < 0); + SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); + + /* Test Case: Issue a Write command from Host C */ + cmd.nvme_cmd.opc = SPDK_NVME_OPC_WRITE; + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); + SPDK_CU_ASSERT_FATAL(rc < 0); + SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); + + /* Test Case: Issue a Read command from Host B */ + cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); + SPDK_CU_ASSERT_FATAL(rc == 0); + + /* Unregister Host C */ + memset(&g_ns_info.reg_hostid[2], 0, sizeof(struct spdk_uuid)); + + /* Test Case: Read and Write commands from non-registrant Host C */ + cmd.nvme_cmd.opc = SPDK_NVME_OPC_WRITE; + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); + SPDK_CU_ASSERT_FATAL(rc < 0); + SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); + cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); + SPDK_CU_ASSERT_FATAL(rc == 0); +} + +static void +test_reservation_exclusive_access(void) +{ + struct spdk_nvmf_request req = {}; + union nvmf_h2c_msg cmd = {}; + union nvmf_c2h_msg rsp = {}; + int rc; + + req.cmd = &cmd; + req.rsp = &rsp; + + /* Host A holds reservation with type SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS */ + ut_reservation_init(SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS); + g_ns_info.holder_id = g_ctrlr1_A.hostid; + + /* Test Case: Issue a Read command from Host B */ + cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); + SPDK_CU_ASSERT_FATAL(rc < 0); + SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); + + /* Test Case: Issue a Reservation Release command from a valid Registrant */ + cmd.nvme_cmd.opc = SPDK_NVME_OPC_RESERVATION_RELEASE; + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); + SPDK_CU_ASSERT_FATAL(rc == 0); +} + +static void +_test_reservation_write_exclusive_regs_only_and_all_regs(enum spdk_nvme_reservation_type rtype) +{ + struct spdk_nvmf_request req = {}; + union nvmf_h2c_msg cmd = {}; + union nvmf_c2h_msg rsp = {}; + int rc; + + req.cmd = &cmd; + req.rsp = &rsp; + + /* SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY and SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS */ + ut_reservation_init(rtype); + g_ns_info.holder_id = g_ctrlr1_A.hostid; + + /* Test Case: Issue a Read command from Host A and Host C */ + cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr1_A, &req); + SPDK_CU_ASSERT_FATAL(rc == 0); + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); + SPDK_CU_ASSERT_FATAL(rc == 0); + + /* Test Case: Issue a DSM Write command from Host A and Host C */ + cmd.nvme_cmd.opc = SPDK_NVME_OPC_DATASET_MANAGEMENT; + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr1_A, &req); + SPDK_CU_ASSERT_FATAL(rc == 0); + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); + SPDK_CU_ASSERT_FATAL(rc == 0); + + /* Unregister Host C */ + memset(&g_ns_info.reg_hostid[2], 0, sizeof(struct spdk_uuid)); + + /* Test Case: Read and Write commands from non-registrant Host C */ + cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); + SPDK_CU_ASSERT_FATAL(rc == 0); + cmd.nvme_cmd.opc = SPDK_NVME_OPC_WRITE; + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); + SPDK_CU_ASSERT_FATAL(rc < 0); + SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); +} + +static void +test_reservation_write_exclusive_regs_only_and_all_regs(void) +{ + _test_reservation_write_exclusive_regs_only_and_all_regs( + SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); + _test_reservation_write_exclusive_regs_only_and_all_regs( + SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); +} + +static void +_test_reservation_exclusive_access_regs_only_and_all_regs(enum spdk_nvme_reservation_type rtype) +{ + struct spdk_nvmf_request req = {}; + union nvmf_h2c_msg cmd = {}; + union nvmf_c2h_msg rsp = {}; + int rc; + + req.cmd = &cmd; + req.rsp = &rsp; + + /* SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY and SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS */ + ut_reservation_init(rtype); + g_ns_info.holder_id = g_ctrlr1_A.hostid; + + /* Test Case: Issue a Write command from Host B */ + cmd.nvme_cmd.opc = SPDK_NVME_OPC_WRITE; + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); + SPDK_CU_ASSERT_FATAL(rc == 0); + + /* Unregister Host B */ + memset(&g_ns_info.reg_hostid[1], 0, sizeof(struct spdk_uuid)); + + /* Test Case: Issue a Read command from Host B */ + cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); + SPDK_CU_ASSERT_FATAL(rc < 0); + SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); + cmd.nvme_cmd.opc = SPDK_NVME_OPC_WRITE; + rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); + SPDK_CU_ASSERT_FATAL(rc < 0); + SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); +} + +static void +test_reservation_exclusive_access_regs_only_and_all_regs(void) +{ + _test_reservation_exclusive_access_regs_only_and_all_regs( + SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY); + _test_reservation_exclusive_access_regs_only_and_all_regs( + SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS); +} + int main(int argc, char **argv) { CU_pSuite suite = NULL; @@ -839,7 +1054,13 @@ int main(int argc, char **argv) CU_add_test(suite, "process_fabrics_cmd", test_process_fabrics_cmd) == NULL || CU_add_test(suite, "connect", test_connect) == NULL || CU_add_test(suite, "get_ns_id_desc_list", test_get_ns_id_desc_list) == NULL || - CU_add_test(suite, "identify_ns", test_identify_ns) == NULL + CU_add_test(suite, "identify_ns", test_identify_ns) == NULL || + CU_add_test(suite, "reservation_write_exclusive", test_reservation_write_exclusive) == NULL || + CU_add_test(suite, "reservation_exclusive_access", test_reservation_exclusive_access) == NULL || + CU_add_test(suite, "reservation_write_exclusive_regs_only_and_all_regs", + test_reservation_write_exclusive_regs_only_and_all_regs) == NULL || + CU_add_test(suite, "reservation_exclusive_access_regs_only_and_all_regs", + test_reservation_exclusive_access_regs_only_and_all_regs) == NULL ) { CU_cleanup_registry(); return CU_get_error();