From c3080c5aa67b24825278aa742ac83c088eb1005f Mon Sep 17 00:00:00 2001 From: Ben Walker Date: Mon, 20 Nov 2017 10:45:39 -0700 Subject: [PATCH] nvmf: Update poll group channel maps when a new namespace is added. There isn't a way to remove a namespace just yet, but at least adding one works. Change-Id: I99416d1bc9cbc0e2303c16040d2311a07829cbea Signed-off-by: Ben Walker Reviewed-on: https://review.gerrithub.io/388293 Tested-by: SPDK Automated Test System Reviewed-by: Jim Harris Reviewed-by: Daniel Verkamp --- lib/nvmf/nvmf.c | 55 ++++++++++++++++++- lib/nvmf/nvmf_internal.h | 3 + lib/nvmf/subsystem.c | 44 +++++++++++++++ .../ctrlr_discovery.c/ctrlr_discovery_ut.c | 8 +++ test/unit/lib/nvmf/subsystem.c/subsystem_ut.c | 8 +++ 5 files changed, 116 insertions(+), 2 deletions(-) diff --git a/lib/nvmf/nvmf.c b/lib/nvmf/nvmf.c index 6817ae4be..30c3d9dca 100644 --- a/lib/nvmf/nvmf.c +++ b/lib/nvmf/nvmf.c @@ -416,11 +416,18 @@ spdk_nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group, if (subsystem->id >= group->num_sgroups) { void *buf; - group->num_sgroups = subsystem->id + 1; - buf = realloc(group->sgroups, group->num_sgroups * sizeof(*sgroup)); + + buf = realloc(group->sgroups, (subsystem->id + 1) * sizeof(*sgroup)); if (!buf) { return -ENOMEM; } + + /* Zero out the newly allocated memory */ + memset(&group->sgroups[group->num_sgroups], + 0, + (subsystem->id + 1 - group->num_sgroups) * sizeof(struct spdk_io_channel *)); + + group->num_sgroups = subsystem->id + 1; group->sgroups = buf; } @@ -468,6 +475,50 @@ spdk_nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group, return 0; } +int +spdk_nvmf_poll_group_add_ns(struct spdk_nvmf_poll_group *group, + struct spdk_nvmf_subsystem *subsystem, + struct spdk_nvmf_ns *ns) +{ + struct spdk_nvmf_subsystem_poll_group *sgroup; + uint32_t ns_idx; + + sgroup = &group->sgroups[subsystem->id]; + + /* The index into the channels array is (nsid - 1) */ + ns_idx = ns->id - 1; + + if (ns_idx >= sgroup->num_channels) { + void *buf; + + buf = realloc(sgroup->channels, + ns->id * sizeof(struct spdk_io_channel *)); + if (!buf) { + return -ENOMEM; + } + + /* Zero out the newly allocated memory */ + memset(&sgroup->channels[sgroup->num_channels], + 0, + (ns->id - sgroup->num_channels) * sizeof(struct spdk_io_channel *)); + + sgroup->num_channels = ns->id; + sgroup->channels = buf; + } + + /* The channel could have been created in response to a subsystem creation + * event already propagating through the system */ + if (sgroup->channels[ns_idx] == NULL) { + sgroup->channels[ns_idx] = spdk_bdev_get_io_channel(ns->desc); + } + + if (sgroup->channels[ns_idx] == NULL) { + return -1; + } + + return 0; +} + SPDK_TRACE_REGISTER_FN(nvmf_trace) { spdk_trace_register_object(OBJECT_NVMF_IO, 'r'); diff --git a/lib/nvmf/nvmf_internal.h b/lib/nvmf/nvmf_internal.h index ce0b99143..ce0499b2c 100644 --- a/lib/nvmf/nvmf_internal.h +++ b/lib/nvmf/nvmf_internal.h @@ -223,6 +223,9 @@ int spdk_nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group, struct spdk_nvmf_subsystem *subsystem); int spdk_nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group, struct spdk_nvmf_subsystem *subsystem); +int spdk_nvmf_poll_group_add_ns(struct spdk_nvmf_poll_group *group, + struct spdk_nvmf_subsystem *subsystem, + struct spdk_nvmf_ns *ns); void spdk_nvmf_request_exec(struct spdk_nvmf_request *req); int spdk_nvmf_request_complete(struct spdk_nvmf_request *req); diff --git a/lib/nvmf/subsystem.c b/lib/nvmf/subsystem.c index 1f2714268..588b29aa7 100644 --- a/lib/nvmf/subsystem.c +++ b/lib/nvmf/subsystem.c @@ -393,11 +393,36 @@ spdk_nvmf_listener_get_trid(struct spdk_nvmf_listener *listener) return &listener->trid; } +struct spdk_nvmf_subsystem_add_ns_ctx { + struct spdk_nvmf_subsystem *subsystem; + struct spdk_nvmf_ns *ns; +}; + +static void +spdk_nvmf_subsystem_add_ns_done(void *io_device, void *ctx, int status) +{ + free(ctx); +} + +static int +spdk_nvmf_subsystem_ns_update_poll_group(void *io_device, + struct spdk_io_channel *ch, + void *c) +{ + struct spdk_nvmf_poll_group *group; + struct spdk_nvmf_subsystem_add_ns_ctx *ctx = c; + + group = spdk_io_channel_get_ctx(ch); + + return spdk_nvmf_poll_group_add_ns(group, ctx->subsystem, ctx->ns); +} + uint32_t spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bdev *bdev, uint32_t nsid) { struct spdk_nvmf_ns *ns; + struct spdk_nvmf_subsystem_add_ns_ctx *ctx; uint32_t i; int rc; @@ -473,6 +498,25 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd subsystem->max_nsid = spdk_max(subsystem->max_nsid, nsid); subsystem->num_allocated_nsid++; + + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) { + return -ENOMEM; + } + ctx->subsystem = subsystem; + ctx->ns = ns; + + /* Send a message to each poll group to notify it that a new namespace + * is available. + * TODO: This call does not currently allow the user to wait for these + * messages to propagate. It also does not protect against two calls + * to this function overlapping + */ + spdk_for_each_channel(subsystem->tgt, + spdk_nvmf_subsystem_ns_update_poll_group, + ctx, + spdk_nvmf_subsystem_add_ns_done); + 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 96f42d005..a785f5104 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 @@ -136,6 +136,14 @@ spdk_nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group, return 0; } +int +spdk_nvmf_poll_group_add_ns(struct spdk_nvmf_poll_group *group, + struct spdk_nvmf_subsystem *subsystem, + struct spdk_nvmf_ns *ns) +{ + return 0; +} + int spdk_nvmf_subsystem_bdev_attach(struct spdk_nvmf_subsystem *subsystem) { diff --git a/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c b/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c index a189b5a24..6a4e9e48b 100644 --- a/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c +++ b/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c @@ -109,6 +109,14 @@ spdk_nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group, return 0; } +int +spdk_nvmf_poll_group_add_ns(struct spdk_nvmf_poll_group *group, + struct spdk_nvmf_subsystem *subsystem, + struct spdk_nvmf_ns *ns) +{ + return 0; +} + int spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str) {