nvmf: dynamically allocate ns array

This allows the user to configure an arbitrarily large number of
namespaces instead of the current hard-coded limit of 16.

Change-Id: I3a29b0de10eafd682b12c54e12411d1f9d41ce85
Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-on: https://review.gerrithub.io/375636
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Daniel Verkamp 2017-08-24 13:48:59 -07:00
parent db24ff75fe
commit 02f088bb95
8 changed files with 66 additions and 21 deletions

View File

@ -117,7 +117,7 @@ spdk_add_nvmf_discovery_subsystem(void)
{ {
struct nvmf_tgt_subsystem *app_subsys; 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); g_spdk_nvmf_tgt_conf.acceptor_lcore);
if (app_subsys == NULL) { if (app_subsys == NULL) {
SPDK_ERRLOG("Failed creating discovery nvmf library subsystem\n"); 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); lcore = spdk_nvmf_allocate_lcore(mask, lcore);
g_last_core = 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) { if (app_subsys == NULL) {
SPDK_ERRLOG("Subsystem creation failed\n"); SPDK_ERRLOG("Subsystem creation failed\n");
return -1; return -1;

View File

@ -185,7 +185,7 @@ nvmf_tgt_start_subsystem(struct nvmf_tgt_subsystem *app_subsys)
} }
struct nvmf_tgt_subsystem * 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) uint32_t lcore)
{ {
struct spdk_nvmf_subsystem *subsystem; struct spdk_nvmf_subsystem *subsystem;
@ -202,7 +202,7 @@ nvmf_tgt_create_subsystem(const char *name, enum spdk_nvmf_subtype subtype,
return NULL; 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); disconnect_cb);
if (subsystem == NULL) { if (subsystem == NULL) {
SPDK_ERRLOG("Subsystem creation failed\n"); SPDK_ERRLOG("Subsystem creation failed\n");

View File

@ -76,7 +76,7 @@ int spdk_nvmf_parse_conf(void);
void nvmf_tgt_start_subsystem(struct nvmf_tgt_subsystem *subsystem); void nvmf_tgt_start_subsystem(struct nvmf_tgt_subsystem *subsystem);
struct nvmf_tgt_subsystem *nvmf_tgt_create_subsystem(const char *name, 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); uint32_t lcore);
int int

View File

@ -45,8 +45,6 @@
#include "spdk/nvmf_spec.h" #include "spdk/nvmf_spec.h"
#include "spdk/queue.h" #include "spdk/queue.h"
#define MAX_VIRTUAL_NAMESPACE 16
struct spdk_nvmf_tgt; struct spdk_nvmf_tgt;
struct spdk_nvmf_tgt_opts { 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, struct spdk_nvmf_subsystem *spdk_nvmf_create_subsystem(struct spdk_nvmf_tgt *tgt,
const char *nqn, const char *nqn,
enum spdk_nvmf_subtype type, enum spdk_nvmf_subtype type,
uint32_t num_ns,
void *cb_ctx, void *cb_ctx,
spdk_nvmf_subsystem_connect_fn connect_cb, spdk_nvmf_subsystem_connect_fn connect_cb,
spdk_nvmf_subsystem_disconnect_fn disconnect_cb); spdk_nvmf_subsystem_disconnect_fn disconnect_cb);

View File

@ -90,8 +90,10 @@ struct spdk_nvmf_subsystem {
char sn[SPDK_NVME_CTRLR_SN_LEN + 1]; 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 max_nsid;
uint32_t num_allocated_nsid;
void *cb_ctx; void *cb_ctx;
spdk_nvmf_subsystem_connect_fn connect_cb; spdk_nvmf_subsystem_connect_fn connect_cb;

View File

@ -133,6 +133,7 @@ struct spdk_nvmf_subsystem *
spdk_nvmf_create_subsystem(struct spdk_nvmf_tgt *tgt, spdk_nvmf_create_subsystem(struct spdk_nvmf_tgt *tgt,
const char *nqn, const char *nqn,
enum spdk_nvmf_subtype type, enum spdk_nvmf_subtype type,
uint32_t num_ns,
void *cb_ctx, void *cb_ctx,
spdk_nvmf_subsystem_connect_fn connect_cb, spdk_nvmf_subsystem_connect_fn connect_cb,
spdk_nvmf_subsystem_disconnect_fn disconnect_cb) spdk_nvmf_subsystem_disconnect_fn disconnect_cb)
@ -143,6 +144,11 @@ spdk_nvmf_create_subsystem(struct spdk_nvmf_tgt *tgt,
return NULL; 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)); subsystem = calloc(1, sizeof(struct spdk_nvmf_subsystem));
if (subsystem == NULL) { if (subsystem == NULL) {
return NULL; return NULL;
@ -154,6 +160,8 @@ spdk_nvmf_create_subsystem(struct spdk_nvmf_tgt *tgt,
subsystem->id = tgt->current_subsystem_id; subsystem->id = tgt->current_subsystem_id;
subsystem->subtype = type; subsystem->subtype = type;
subsystem->max_nsid = num_ns;
subsystem->num_allocated_nsid = 0;
subsystem->cb_ctx = cb_ctx; subsystem->cb_ctx = cb_ctx;
subsystem->connect_cb = connect_cb; subsystem->connect_cb = connect_cb;
subsystem->disconnect_cb = disconnect_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->hosts);
TAILQ_INIT(&subsystem->ctrlrs); 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); TAILQ_INSERT_TAIL(&tgt->subsystems, subsystem, entries);
tgt->discovery_genctr++; tgt->discovery_genctr++;
@ -198,6 +215,8 @@ spdk_nvmf_delete_subsystem(struct spdk_nvmf_subsystem *subsystem)
spdk_nvmf_subsystem_bdev_detach(subsystem); spdk_nvmf_subsystem_bdev_detach(subsystem);
free(subsystem->ns);
TAILQ_REMOVE(&subsystem->tgt->subsystems, subsystem, entries); TAILQ_REMOVE(&subsystem->tgt->subsystems, subsystem, entries);
subsystem->tgt->discovery_genctr++; subsystem->tgt->discovery_genctr++;
@ -348,9 +367,37 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd
uint32_t i; uint32_t i;
int rc; 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) { if (nsid == 0) {
/* NSID not specified - find a free index */ /* 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) { if (_spdk_nvmf_subsystem_get_ns(subsystem, i + 1) == NULL) {
nsid = i + 1; nsid = i + 1;
break; break;
@ -362,19 +409,13 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd
} }
} else { } else {
/* Specific NSID requested */ /* 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)) { if (_spdk_nvmf_subsystem_get_ns(subsystem, nsid)) {
SPDK_ERRLOG("Requested NSID %" PRIu32 " already in use\n", nsid); SPDK_ERRLOG("Requested NSID %" PRIu32 " already in use\n", nsid);
return 0; return 0;
} }
} }
ns = &subsystem->ns[i]; ns = &subsystem->ns[nsid - 1];
memset(ns, 0, sizeof(*ns)); memset(ns, 0, sizeof(*ns));
ns->bdev = bdev; ns->bdev = bdev;
ns->id = nsid; ns->id = nsid;
@ -392,6 +433,7 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd
nsid); nsid);
subsystem->max_nsid = spdk_max(subsystem->max_nsid, nsid); subsystem->max_nsid = spdk_max(subsystem->max_nsid, nsid);
subsystem->num_allocated_nsid++;
return nsid; return nsid;
} }

View File

@ -196,7 +196,7 @@ test_discovery_log(void)
/* Add one subsystem and verify that the discovery log contains it */ /* 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", 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); NULL, NULL, NULL);
SPDK_CU_ASSERT_FATAL(subsystem != NULL); SPDK_CU_ASSERT_FATAL(subsystem != NULL);

View File

@ -190,7 +190,7 @@ test_spdk_nvmf_subsystem_add_ns(void)
{ {
struct spdk_nvmf_subsystem subsystem = { struct spdk_nvmf_subsystem subsystem = {
.max_nsid = 0, .max_nsid = 0,
.ns = {}, .ns = NULL,
}; };
struct spdk_bdev bdev1 = {}, bdev2 = {}; struct spdk_bdev bdev1 = {}, bdev2 = {};
uint32_t nsid; uint32_t nsid;
@ -212,6 +212,8 @@ test_spdk_nvmf_subsystem_add_ns(void)
nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev2, 5); nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev2, 5);
CU_ASSERT(nsid == 0); CU_ASSERT(nsid == 0);
CU_ASSERT(subsystem.max_nsid == 5); CU_ASSERT(subsystem.max_nsid == 5);
free(subsystem.ns);
} }
static void static void
@ -223,7 +225,7 @@ nvmf_test_create_subsystem(void)
TAILQ_INIT(&tgt.subsystems); TAILQ_INIT(&tgt.subsystems);
strncpy(nqn, "nqn.2016-06.io.spdk:subsystem1", sizeof(nqn)); 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); NULL, NULL, NULL);
SPDK_CU_ASSERT_FATAL(subsystem != NULL); SPDK_CU_ASSERT_FATAL(subsystem != NULL);
CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
@ -234,7 +236,7 @@ nvmf_test_create_subsystem(void)
memset(nqn + strlen(nqn), 'a', 223 - strlen(nqn)); memset(nqn + strlen(nqn), 'a', 223 - strlen(nqn));
nqn[223] = '\0'; nqn[223] = '\0';
CU_ASSERT(strlen(nqn) == 223); 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); NULL, NULL, NULL);
SPDK_CU_ASSERT_FATAL(subsystem != NULL); SPDK_CU_ASSERT_FATAL(subsystem != NULL);
CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
@ -245,7 +247,7 @@ nvmf_test_create_subsystem(void)
memset(nqn + strlen(nqn), 'a', 224 - strlen(nqn)); memset(nqn + strlen(nqn), 'a', 224 - strlen(nqn));
nqn[224] = '\0'; nqn[224] = '\0';
CU_ASSERT(strlen(nqn) == 224); 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); NULL, NULL, NULL);
CU_ASSERT(subsystem == NULL); CU_ASSERT(subsystem == NULL);
} }