diff --git a/app/nvmf_tgt/conf.c b/app/nvmf_tgt/conf.c index 44dc7ee87..8c14f61b2 100644 --- a/app/nvmf_tgt/conf.c +++ b/app/nvmf_tgt/conf.c @@ -117,7 +117,7 @@ spdk_add_nvmf_discovery_subsystem(void) { struct nvmf_tgt_subsystem *app_subsys; - app_subsys = nvmf_tgt_create_subsystem(SPDK_NVMF_DISCOVERY_NQN, SPDK_NVMF_SUBTYPE_DISCOVERY, + app_subsys = nvmf_tgt_create_subsystem(SPDK_NVMF_DISCOVERY_NQN, SPDK_NVMF_SUBTYPE_DISCOVERY, 0, g_spdk_nvmf_tgt_conf.acceptor_lcore); if (app_subsys == NULL) { SPDK_ERRLOG("Failed creating discovery nvmf library subsystem\n"); @@ -392,7 +392,7 @@ spdk_nvmf_construct_subsystem(const char *name, int32_t lcore, lcore = spdk_nvmf_allocate_lcore(mask, lcore); g_last_core = lcore; - app_subsys = nvmf_tgt_create_subsystem(name, SPDK_NVMF_SUBTYPE_NVME, lcore); + app_subsys = nvmf_tgt_create_subsystem(name, SPDK_NVMF_SUBTYPE_NVME, num_devs, lcore); if (app_subsys == NULL) { SPDK_ERRLOG("Subsystem creation failed\n"); return -1; diff --git a/app/nvmf_tgt/nvmf_tgt.c b/app/nvmf_tgt/nvmf_tgt.c index 8670b703e..d78a07d89 100644 --- a/app/nvmf_tgt/nvmf_tgt.c +++ b/app/nvmf_tgt/nvmf_tgt.c @@ -185,7 +185,7 @@ nvmf_tgt_start_subsystem(struct nvmf_tgt_subsystem *app_subsys) } struct nvmf_tgt_subsystem * -nvmf_tgt_create_subsystem(const char *name, enum spdk_nvmf_subtype subtype, +nvmf_tgt_create_subsystem(const char *name, enum spdk_nvmf_subtype subtype, uint32_t num_ns, uint32_t lcore) { struct spdk_nvmf_subsystem *subsystem; @@ -202,7 +202,7 @@ nvmf_tgt_create_subsystem(const char *name, enum spdk_nvmf_subtype subtype, return NULL; } - subsystem = spdk_nvmf_create_subsystem(g_tgt, name, subtype, app_subsys, connect_cb, + subsystem = spdk_nvmf_create_subsystem(g_tgt, name, subtype, num_ns, app_subsys, connect_cb, disconnect_cb); if (subsystem == NULL) { SPDK_ERRLOG("Subsystem creation failed\n"); diff --git a/app/nvmf_tgt/nvmf_tgt.h b/app/nvmf_tgt/nvmf_tgt.h index e6c889f53..fd1726b3b 100644 --- a/app/nvmf_tgt/nvmf_tgt.h +++ b/app/nvmf_tgt/nvmf_tgt.h @@ -76,7 +76,7 @@ int spdk_nvmf_parse_conf(void); void nvmf_tgt_start_subsystem(struct nvmf_tgt_subsystem *subsystem); struct nvmf_tgt_subsystem *nvmf_tgt_create_subsystem(const char *name, - enum spdk_nvmf_subtype subtype, + enum spdk_nvmf_subtype subtype, uint32_t num_ns, uint32_t lcore); int diff --git a/include/spdk/nvmf.h b/include/spdk/nvmf.h index de75ea92b..df4ba709f 100644 --- a/include/spdk/nvmf.h +++ b/include/spdk/nvmf.h @@ -45,8 +45,6 @@ #include "spdk/nvmf_spec.h" #include "spdk/queue.h" -#define MAX_VIRTUAL_NAMESPACE 16 - struct spdk_nvmf_tgt; struct spdk_nvmf_tgt_opts { @@ -113,6 +111,7 @@ struct spdk_nvmf_listen_addr { struct spdk_nvmf_subsystem *spdk_nvmf_create_subsystem(struct spdk_nvmf_tgt *tgt, const char *nqn, enum spdk_nvmf_subtype type, + uint32_t num_ns, void *cb_ctx, spdk_nvmf_subsystem_connect_fn connect_cb, spdk_nvmf_subsystem_disconnect_fn disconnect_cb); diff --git a/lib/nvmf/nvmf_internal.h b/lib/nvmf/nvmf_internal.h index c95f2a449..a32b61bf3 100644 --- a/lib/nvmf/nvmf_internal.h +++ b/lib/nvmf/nvmf_internal.h @@ -90,8 +90,10 @@ struct spdk_nvmf_subsystem { char sn[SPDK_NVME_CTRLR_SN_LEN + 1]; - struct spdk_nvmf_ns ns[MAX_VIRTUAL_NAMESPACE]; + /* Array of namespaces of size max_nsid indexed by nsid - 1 */ + struct spdk_nvmf_ns *ns; uint32_t max_nsid; + uint32_t num_allocated_nsid; void *cb_ctx; spdk_nvmf_subsystem_connect_fn connect_cb; diff --git a/lib/nvmf/subsystem.c b/lib/nvmf/subsystem.c index a136ffb52..c6acc95ff 100644 --- a/lib/nvmf/subsystem.c +++ b/lib/nvmf/subsystem.c @@ -133,6 +133,7 @@ struct spdk_nvmf_subsystem * spdk_nvmf_create_subsystem(struct spdk_nvmf_tgt *tgt, const char *nqn, enum spdk_nvmf_subtype type, + uint32_t num_ns, void *cb_ctx, spdk_nvmf_subsystem_connect_fn connect_cb, spdk_nvmf_subsystem_disconnect_fn disconnect_cb) @@ -143,6 +144,11 @@ spdk_nvmf_create_subsystem(struct spdk_nvmf_tgt *tgt, return NULL; } + if (type == SPDK_NVMF_SUBTYPE_DISCOVERY && num_ns != 0) { + SPDK_ERRLOG("Discovery subsystem cannot have namespaces.\n"); + return NULL; + } + subsystem = calloc(1, sizeof(struct spdk_nvmf_subsystem)); if (subsystem == NULL) { return NULL; @@ -154,6 +160,8 @@ spdk_nvmf_create_subsystem(struct spdk_nvmf_tgt *tgt, subsystem->id = tgt->current_subsystem_id; subsystem->subtype = type; + subsystem->max_nsid = num_ns; + subsystem->num_allocated_nsid = 0; subsystem->cb_ctx = cb_ctx; subsystem->connect_cb = connect_cb; subsystem->disconnect_cb = disconnect_cb; @@ -162,6 +170,15 @@ spdk_nvmf_create_subsystem(struct spdk_nvmf_tgt *tgt, TAILQ_INIT(&subsystem->hosts); TAILQ_INIT(&subsystem->ctrlrs); + if (num_ns != 0) { + subsystem->ns = calloc(num_ns, sizeof(struct spdk_nvmf_ns)); + if (subsystem->ns == NULL) { + SPDK_ERRLOG("Namespace memory allocation failed\n"); + free(subsystem); + return NULL; + } + } + TAILQ_INSERT_TAIL(&tgt->subsystems, subsystem, entries); tgt->discovery_genctr++; @@ -198,6 +215,8 @@ spdk_nvmf_delete_subsystem(struct spdk_nvmf_subsystem *subsystem) spdk_nvmf_subsystem_bdev_detach(subsystem); + free(subsystem->ns); + TAILQ_REMOVE(&subsystem->tgt->subsystems, subsystem, entries); subsystem->tgt->discovery_genctr++; @@ -348,9 +367,37 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd uint32_t i; int rc; + if (nsid > subsystem->max_nsid || + (nsid == 0 && subsystem->num_allocated_nsid == subsystem->max_nsid)) { + struct spdk_nvmf_ns *new_ns_array; + uint32_t new_max_nsid; + + if (nsid > subsystem->max_nsid) { + new_max_nsid = nsid; + } else { + new_max_nsid = subsystem->max_nsid + 1; + } + + if (!TAILQ_EMPTY(&subsystem->ctrlrs)) { + SPDK_ERRLOG("Can't extend NSID range with active connections\n"); + return 0; + } + + new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns) * new_max_nsid); + if (new_ns_array == NULL) { + SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n"); + return 0; + } + + memset(new_ns_array + subsystem->max_nsid, 0, + sizeof(struct spdk_nvmf_ns) * (new_max_nsid - subsystem->max_nsid)); + subsystem->ns = new_ns_array; + subsystem->max_nsid = new_max_nsid; + } + if (nsid == 0) { /* NSID not specified - find a free index */ - for (i = 0; i < MAX_VIRTUAL_NAMESPACE; i++) { + for (i = 0; i < subsystem->max_nsid; i++) { if (_spdk_nvmf_subsystem_get_ns(subsystem, i + 1) == NULL) { nsid = i + 1; break; @@ -362,19 +409,13 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd } } else { /* Specific NSID requested */ - i = nsid - 1; - if (i >= MAX_VIRTUAL_NAMESPACE) { - SPDK_ERRLOG("Requested NSID %" PRIu32 " out of range\n", nsid); - return 0; - } - if (_spdk_nvmf_subsystem_get_ns(subsystem, nsid)) { SPDK_ERRLOG("Requested NSID %" PRIu32 " already in use\n", nsid); return 0; } } - ns = &subsystem->ns[i]; + ns = &subsystem->ns[nsid - 1]; memset(ns, 0, sizeof(*ns)); ns->bdev = bdev; ns->id = nsid; @@ -392,6 +433,7 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd nsid); subsystem->max_nsid = spdk_max(subsystem->max_nsid, nsid); + subsystem->num_allocated_nsid++; return nsid; } diff --git a/test/unit/lib/nvmf/ctrlr_discovery.c/ctrlr_discovery_ut.c b/test/unit/lib/nvmf/ctrlr_discovery.c/ctrlr_discovery_ut.c index 45bf49191..b82bc7b2c 100644 --- a/test/unit/lib/nvmf/ctrlr_discovery.c/ctrlr_discovery_ut.c +++ b/test/unit/lib/nvmf/ctrlr_discovery.c/ctrlr_discovery_ut.c @@ -196,7 +196,7 @@ test_discovery_log(void) /* Add one subsystem and verify that the discovery log contains it */ subsystem = spdk_nvmf_create_subsystem(&g_nvmf_tgt, "nqn.2016-06.io.spdk:subsystem1", - SPDK_NVMF_SUBTYPE_NVME, + SPDK_NVMF_SUBTYPE_NVME, 0, NULL, NULL, NULL); SPDK_CU_ASSERT_FATAL(subsystem != NULL); diff --git a/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c b/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c index fd1f95f53..74c17f4c6 100644 --- a/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c +++ b/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c @@ -190,7 +190,7 @@ test_spdk_nvmf_subsystem_add_ns(void) { struct spdk_nvmf_subsystem subsystem = { .max_nsid = 0, - .ns = {}, + .ns = NULL, }; struct spdk_bdev bdev1 = {}, bdev2 = {}; uint32_t nsid; @@ -212,6 +212,8 @@ test_spdk_nvmf_subsystem_add_ns(void) nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev2, 5); CU_ASSERT(nsid == 0); CU_ASSERT(subsystem.max_nsid == 5); + + free(subsystem.ns); } static void @@ -223,7 +225,7 @@ nvmf_test_create_subsystem(void) TAILQ_INIT(&tgt.subsystems); strncpy(nqn, "nqn.2016-06.io.spdk:subsystem1", sizeof(nqn)); - subsystem = spdk_nvmf_create_subsystem(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, + subsystem = spdk_nvmf_create_subsystem(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0, NULL, NULL, NULL); SPDK_CU_ASSERT_FATAL(subsystem != NULL); CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); @@ -234,7 +236,7 @@ nvmf_test_create_subsystem(void) memset(nqn + strlen(nqn), 'a', 223 - strlen(nqn)); nqn[223] = '\0'; CU_ASSERT(strlen(nqn) == 223); - subsystem = spdk_nvmf_create_subsystem(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, + subsystem = spdk_nvmf_create_subsystem(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0, NULL, NULL, NULL); SPDK_CU_ASSERT_FATAL(subsystem != NULL); CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); @@ -245,7 +247,7 @@ nvmf_test_create_subsystem(void) memset(nqn + strlen(nqn), 'a', 224 - strlen(nqn)); nqn[224] = '\0'; CU_ASSERT(strlen(nqn) == 224); - subsystem = spdk_nvmf_create_subsystem(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, + subsystem = spdk_nvmf_create_subsystem(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0, NULL, NULL, NULL); CU_ASSERT(subsystem == NULL); }