diff --git a/lib/nvmf/ctrlr.c b/lib/nvmf/ctrlr.c index 470df0b24..b361dee0b 100644 --- a/lib/nvmf/ctrlr.c +++ b/lib/nvmf/ctrlr.c @@ -1200,10 +1200,23 @@ spdk_nvmf_ctrlr_identify_ns(struct spdk_nvmf_subsystem *subsystem, { struct spdk_nvmf_ns *ns; + if (cmd->nsid == 0 || cmd->nsid > subsystem->max_nsid) { + SPDK_ERRLOG("Identify Namespace for invalid NSID %u\n", cmd->nsid); + rsp->status.sct = SPDK_NVME_SCT_GENERIC; + rsp->status.sc = SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT; + return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; + } + ns = _spdk_nvmf_subsystem_get_ns(subsystem, cmd->nsid); if (ns == NULL || ns->bdev == NULL) { - SPDK_ERRLOG("Identify Namespace for invalid NSID %u\n", cmd->nsid); - rsp->status.sc = SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT; + /* + * Inactive namespaces should return a zero filled data structure. + * The data buffer is already zeroed by spdk_nvmf_ctrlr_process_admin_cmd(), + * so we can just return early here. + */ + SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Identify Namespace for inactive NSID %u\n", cmd->nsid); + rsp->status.sct = SPDK_NVME_SCT_GENERIC; + rsp->status.sc = SPDK_NVME_SC_SUCCESS; return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; } diff --git a/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c b/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c index bb54dda85..559372edb 100644 --- a/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c +++ b/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c @@ -42,6 +42,7 @@ SPDK_LOG_REGISTER_COMPONENT("nvmf", SPDK_LOG_NVMF) struct spdk_bdev { int ut_mock; + uint64_t blockcnt; }; DEFINE_STUB(spdk_nvmf_tgt_find_subsystem, @@ -118,11 +119,6 @@ DEFINE_STUB(spdk_nvmf_ctrlr_write_zeroes_supported, (struct spdk_nvmf_ctrlr *ctrlr), false); -DEFINE_STUB(spdk_nvmf_bdev_ctrlr_identify_ns, - int, - (struct spdk_nvmf_ns *ns, struct spdk_nvme_ns_data *nsdata), - -1); - DEFINE_STUB_V(spdk_nvmf_get_discovery_log_page, (struct spdk_nvmf_tgt *tgt, void *buffer, uint64_t offset, uint32_t length)); @@ -136,6 +132,23 @@ DEFINE_STUB(spdk_nvmf_request_abort, (struct spdk_nvmf_request *req), -1); +int +spdk_nvmf_bdev_ctrlr_identify_ns(struct spdk_nvmf_ns *ns, struct spdk_nvme_ns_data *nsdata) +{ + uint64_t num_blocks; + + SPDK_CU_ASSERT_FATAL(ns->bdev != NULL); + num_blocks = ns->bdev->blockcnt; + nsdata->nsze = num_blocks; + nsdata->ncap = num_blocks; + nsdata->nuse = num_blocks; + nsdata->nlbaf = 0; + nsdata->flbas.format = 0; + nsdata->lbaf[0].lbads = spdk_u32log2(512); + + return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; +} + static void test_get_log_page(void) { @@ -665,6 +678,81 @@ test_get_ns_id_desc_list(void) CU_ASSERT(buf[53] == 0); } +static void +test_identify_ns(void) +{ + struct spdk_nvmf_subsystem subsystem = {}; + struct spdk_nvme_cmd cmd = {}; + struct spdk_nvme_cpl rsp = {}; + struct spdk_nvme_ns_data nsdata = {}; + struct spdk_bdev bdev[3] = {{.blockcnt = 1234}, {.blockcnt = 0}, {.blockcnt = 5678}}; + struct spdk_nvmf_ns ns[3] = {{.bdev = &bdev[0]}, {.bdev = NULL}, {.bdev = &bdev[2]}}; + struct spdk_nvmf_ns *ns_arr[3] = {&ns[0], NULL, &ns[2]}; + + subsystem.ns = ns_arr; + subsystem.max_nsid = SPDK_COUNTOF(ns_arr); + + /* Invalid NSID 0 */ + cmd.nsid = 0; + memset(&nsdata, 0, sizeof(nsdata)); + memset(&rsp, 0, sizeof(rsp)); + CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&subsystem, &cmd, &rsp, + &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); + CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); + CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT); + CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata))); + + /* Valid NSID 1 */ + cmd.nsid = 1; + memset(&nsdata, 0, sizeof(nsdata)); + memset(&rsp, 0, sizeof(rsp)); + CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&subsystem, &cmd, &rsp, + &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); + CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); + CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS); + CU_ASSERT(nsdata.nsze == 1234); + + /* Valid but inactive NSID 2 */ + cmd.nsid = 2; + memset(&nsdata, 0, sizeof(nsdata)); + memset(&rsp, 0, sizeof(rsp)); + CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&subsystem, &cmd, &rsp, + &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); + CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); + CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS); + CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata))); + + /* Valid NSID 3 */ + cmd.nsid = 3; + memset(&nsdata, 0, sizeof(nsdata)); + memset(&rsp, 0, sizeof(rsp)); + CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&subsystem, &cmd, &rsp, + &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); + CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); + CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS); + CU_ASSERT(nsdata.nsze == 5678); + + /* Invalid NSID 4 */ + cmd.nsid = 4; + memset(&nsdata, 0, sizeof(nsdata)); + memset(&rsp, 0, sizeof(rsp)); + CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&subsystem, &cmd, &rsp, + &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); + CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); + CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT); + CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata))); + + /* Invalid NSID 0xFFFFFFFF (NS management not supported) */ + cmd.nsid = 0xFFFFFFFF; + memset(&nsdata, 0, sizeof(nsdata)); + memset(&rsp, 0, sizeof(rsp)); + CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&subsystem, &cmd, &rsp, + &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); + CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); + CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT); + CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata))); +} + int main(int argc, char **argv) { CU_pSuite suite = NULL; @@ -684,7 +772,8 @@ int main(int argc, char **argv) CU_add_test(suite, "get_log_page", test_get_log_page) == NULL || 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, "get_ns_id_desc_list", test_get_ns_id_desc_list) == NULL || + CU_add_test(suite, "identify_ns", test_identify_ns) == NULL ) { CU_cleanup_registry(); return CU_get_error();