nvmf: Statically size the subsystems arrays

The realloc breaks TAILQs inside the structures, which causes
subtle bugs. Instead, statically allocate all of the subsystem
arrays. This sets up the maximum number of subsystems to be
configurable, but does not actually expose it through the
config file yet.

Change-Id: I7347b6002b6babc0678ce59cd218a454fe3a6f88
Signed-off-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.gerrithub.io/410521
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Ben Walker 2018-05-08 16:05:28 -07:00
parent bfb73837de
commit 16d0fbd0d6
7 changed files with 35 additions and 44 deletions

View File

@ -66,6 +66,7 @@ struct spdk_nvmf_tgt_opts {
uint16_t max_qpairs_per_ctrlr;
uint32_t in_capsule_data_size;
uint32_t max_io_size;
uint32_t max_subsystems;
};
/**
* Initialize the default value of opts.

View File

@ -69,7 +69,7 @@ nvmf_update_discovery_log(struct spdk_nvmf_tgt *tgt)
return;
}
for (sid = 0; sid < tgt->max_sid; sid++) {
for (sid = 0; sid < tgt->opts.max_subsystems; sid++) {
subsystem = tgt->subsystems[sid];
if (subsystem == NULL) {
continue;

View File

@ -46,12 +46,11 @@
SPDK_LOG_REGISTER_COMPONENT("nvmf", SPDK_LOG_NVMF)
#define MAX_SUBSYSTEMS 4
#define SPDK_NVMF_DEFAULT_MAX_QUEUE_DEPTH 128
#define SPDK_NVMF_DEFAULT_MAX_QPAIRS_PER_CTRLR 64
#define SPDK_NVMF_DEFAULT_IN_CAPSULE_DATA_SIZE 4096
#define SPDK_NVMF_DEFAULT_MAX_IO_SIZE 131072
#define SPDK_NVMF_DEFAULT_MAX_SUBSYSTEMS 1024
void
spdk_nvmf_tgt_opts_init(struct spdk_nvmf_tgt_opts *opts)
@ -60,6 +59,7 @@ spdk_nvmf_tgt_opts_init(struct spdk_nvmf_tgt_opts *opts)
opts->max_qpairs_per_ctrlr = SPDK_NVMF_DEFAULT_MAX_QPAIRS_PER_CTRLR;
opts->in_capsule_data_size = SPDK_NVMF_DEFAULT_IN_CAPSULE_DATA_SIZE;
opts->max_io_size = SPDK_NVMF_DEFAULT_MAX_IO_SIZE;
opts->max_subsystems = SPDK_NVMF_DEFAULT_MAX_SUBSYSTEMS;
}
static int
@ -95,13 +95,13 @@ spdk_nvmf_tgt_create_poll_group(void *io_device, void *ctx_buf)
spdk_nvmf_poll_group_add_transport(group, transport);
}
group->num_sgroups = tgt->max_sid;
group->sgroups = calloc(group->num_sgroups, sizeof(struct spdk_nvmf_subsystem_poll_group));
group->num_sgroups = tgt->opts.max_subsystems;
group->sgroups = calloc(tgt->opts.max_subsystems, sizeof(struct spdk_nvmf_subsystem_poll_group));
if (!group->sgroups) {
return -1;
}
for (sid = 0; sid < group->num_sgroups; sid++) {
for (sid = 0; sid < tgt->opts.max_subsystems; sid++) {
struct spdk_nvmf_subsystem *subsystem;
subsystem = tgt->subsystems[sid];
@ -168,10 +168,14 @@ spdk_nvmf_tgt_create(struct spdk_nvmf_tgt_opts *opts)
tgt->discovery_genctr = 0;
tgt->discovery_log_page = NULL;
tgt->discovery_log_page_size = 0;
tgt->subsystems = NULL;
tgt->max_sid = 0;
TAILQ_INIT(&tgt->transports);
tgt->subsystems = calloc(tgt->opts.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
if (!tgt->subsystems) {
free(tgt);
return NULL;
}
spdk_io_device_register(tgt,
spdk_nvmf_tgt_create_poll_group,
spdk_nvmf_tgt_destroy_poll_group,
@ -198,7 +202,7 @@ spdk_nvmf_tgt_destroy(struct spdk_nvmf_tgt *tgt)
}
if (tgt->subsystems) {
for (i = 0; i < tgt->max_sid; i++) {
for (i = 0; i < tgt->opts.max_subsystems; i++) {
if (tgt->subsystems[i]) {
spdk_nvmf_subsystem_destroy(tgt->subsystems[i]);
}
@ -311,7 +315,7 @@ spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn)
return NULL;
}
for (sid = 0; sid < tgt->max_sid; sid++) {
for (sid = 0; sid < tgt->opts.max_subsystems; sid++) {
subsystem = tgt->subsystems[sid];
if (subsystem == NULL) {
continue;
@ -445,21 +449,7 @@ poll_group_update_subsystem(struct spdk_nvmf_poll_group *group,
/* Make sure our poll group has memory for this subsystem allocated */
if (subsystem->id >= group->num_sgroups) {
void *buf;
buf = realloc(group->sgroups, (subsystem->id + 1) * sizeof(*sgroup));
if (!buf) {
return -ENOMEM;
}
group->sgroups = buf;
/* Zero out the newly allocated memory */
memset(&group->sgroups[group->num_sgroups],
0,
(subsystem->id + 1 - group->num_sgroups) * sizeof(group->sgroups[0]));
group->num_sgroups = subsystem->id + 1;
return -ENOMEM;
}
sgroup = &group->sgroups[subsystem->id];
@ -630,10 +620,6 @@ spdk_nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group,
return rc;
}
/* poll_group_update_subsystem may realloc the sgroups array. We need
* to do a new lookup to get the correct pointer. */
sgroup = &group->sgroups[subsystem->id];
sgroup->state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
/* Release all queued requests */

View File

@ -60,9 +60,8 @@ struct spdk_nvmf_tgt {
uint64_t discovery_genctr;
/* Array of subsystem pointers of size max_sid indexed by sid */
/* Array of subsystem pointers of size max_subsystems indexed by sid */
struct spdk_nvmf_subsystem **subsystems;
uint32_t max_sid;
struct spdk_nvmf_discovery_log_page *discovery_log_page;
size_t discovery_log_page_size;

View File

@ -253,21 +253,13 @@ spdk_nvmf_subsystem_create(struct spdk_nvmf_tgt *tgt,
}
/* Find a free subsystem id (sid) */
for (sid = 0; sid < tgt->max_sid; sid++) {
for (sid = 0; sid < tgt->opts.max_subsystems; sid++) {
if (tgt->subsystems[sid] == NULL) {
break;
}
}
if (sid == tgt->max_sid) {
struct spdk_nvmf_subsystem **subsys_array;
/* No free slots. Add more. */
tgt->max_sid++;
subsys_array = realloc(tgt->subsystems, tgt->max_sid * sizeof(struct spdk_nvmf_subsystem *));
if (!subsys_array) {
tgt->max_sid--;
return NULL;
}
tgt->subsystems = subsys_array;
if (sid >= tgt->opts.max_subsystems) {
return NULL;
}
subsystem = calloc(1, sizeof(struct spdk_nvmf_subsystem));
@ -560,7 +552,7 @@ spdk_nvmf_subsystem_get_first(struct spdk_nvmf_tgt *tgt)
struct spdk_nvmf_subsystem *subsystem;
uint32_t sid;
for (sid = 0; sid < tgt->max_sid; sid++) {
for (sid = 0; sid < tgt->opts.max_subsystems; sid++) {
subsystem = tgt->subsystems[sid];
if (subsystem) {
return subsystem;
@ -582,7 +574,7 @@ spdk_nvmf_subsystem_get_next(struct spdk_nvmf_subsystem *subsystem)
tgt = subsystem->tgt;
for (sid = subsystem->id + 1; sid < tgt->max_sid; sid++) {
for (sid = subsystem->id + 1; sid < tgt->opts.max_subsystems; sid++) {
subsystem = tgt->subsystems[sid];
if (subsystem) {
return subsystem;

View File

@ -208,6 +208,10 @@ test_discovery_log(void)
struct spdk_nvmf_discovery_log_page_entry *entry;
struct spdk_nvme_transport_id trid = {};
tgt.opts.max_subsystems = 1024;
tgt.subsystems = calloc(tgt.opts.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
/* Add one subsystem and verify that the discovery log contains it */
subsystem = spdk_nvmf_subsystem_create(&tgt, "nqn.2016-06.io.spdk:subsystem1",
SPDK_NVMF_SUBTYPE_NVME, 0);

View File

@ -243,6 +243,10 @@ test_spdk_nvmf_subsystem_add_ns(void)
struct spdk_nvmf_ns_opts ns_opts;
uint32_t nsid;
tgt.opts.max_subsystems = 1024;
tgt.subsystems = calloc(tgt.opts.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
/* Allow NSID to be assigned automatically */
spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev1, &ns_opts, sizeof(ns_opts));
@ -280,6 +284,7 @@ test_spdk_nvmf_subsystem_add_ns(void)
spdk_nvmf_subsystem_remove_ns(&subsystem, 5, subsystem_ns_remove_cb, NULL);
free(subsystem.ns);
free(tgt.subsystems);
}
static void
@ -289,6 +294,10 @@ nvmf_test_create_subsystem(void)
char nqn[256];
struct spdk_nvmf_subsystem *subsystem;
tgt.opts.max_subsystems = 1024;
tgt.subsystems = calloc(tgt.opts.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
SPDK_CU_ASSERT_FATAL(subsystem != NULL);