bdev/nvme: make nvme_ctrlr_populate_namespaces asynchronous

Some namespace types such as OCSSD need to do some additional
operations before being ready to populate bdevs for a namespace.

Signed-off-by: Jim Harris <james.r.harris@intel.com>
Change-Id: I67a56f1238e70b8d6fa8c4452fec7df3b7fddb03

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/475924
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
This commit is contained in:
Jim Harris 2019-11-26 11:11:29 -07:00 committed by Tomasz Zawadzki
parent 169e19c320
commit 0cdcf62a65
2 changed files with 50 additions and 19 deletions

View File

@ -127,6 +127,7 @@ static char *g_nvme_hostnqn = NULL;
static void nvme_ctrlr_populate_namespaces(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr,
struct nvme_async_probe_ctx *ctx);
static void nvme_ctrlr_populate_namespaces_done(struct nvme_async_probe_ctx *ctx);
static int bdev_nvme_library_init(void);
static void bdev_nvme_library_fini(void);
static int bdev_nvme_readv(struct nvme_bdev *nbdev, struct spdk_io_channel *ch,
@ -149,11 +150,11 @@ static int bdev_nvme_io_passthru_md(struct nvme_bdev *nbdev, struct spdk_io_chan
struct spdk_nvme_cmd *cmd, void *buf, size_t nbytes, void *md_buf, size_t md_len);
static int bdev_nvme_reset(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr, struct nvme_bdev_io *bio);
typedef int (*populate_namespace_fn)(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr,
struct nvme_bdev_ns *nvme_ns, struct nvme_async_probe_ctx *ctx);
static int nvme_ctrlr_populate_standard_namespace(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr,
typedef void (*populate_namespace_fn)(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr,
struct nvme_bdev_ns *nvme_ns, struct nvme_async_probe_ctx *ctx);
static void nvme_ctrlr_populate_standard_namespace(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr,
struct nvme_bdev_ns *nvme_ns, struct nvme_async_probe_ctx *ctx);
static int nvme_ctrlr_populate_ocssd_namespace(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr,
static void nvme_ctrlr_populate_ocssd_namespace(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr,
struct nvme_bdev_ns *nvme_ns, struct nvme_async_probe_ctx *ctx);
static populate_namespace_fn g_populate_namespace_fn[] = {
@ -793,7 +794,7 @@ static const struct spdk_bdev_fn_table nvmelib_fn_table = {
.get_spin_time = bdev_nvme_get_spin_time,
};
static int
static void
nvme_ctrlr_populate_standard_namespace(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr,
struct nvme_bdev_ns *nvme_ns, struct nvme_async_probe_ctx *ctx)
{
@ -810,13 +811,15 @@ nvme_ctrlr_populate_standard_namespace(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr,
ns = spdk_nvme_ctrlr_get_ns(ctrlr, nvme_ns->id);
if (!ns) {
SPDK_DEBUGLOG(SPDK_LOG_BDEV_NVME, "Invalid NS %d\n", nvme_ns->id);
return -EINVAL;
nvme_ctrlr_populate_namespace_done(ctx, nvme_ns, -EINVAL);
return;
}
bdev = calloc(1, sizeof(*bdev));
if (!bdev) {
SPDK_ERRLOG("bdev calloc() failed\n");
return -ENOMEM;
nvme_ctrlr_populate_namespace_done(ctx, nvme_ns, -ENOMEM);
return;
}
bdev->nvme_bdev_ctrlr = nvme_bdev_ctrlr;
@ -826,7 +829,8 @@ nvme_ctrlr_populate_standard_namespace(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr,
bdev->disk.name = spdk_sprintf_alloc("%sn%d", nvme_bdev_ctrlr->name, spdk_nvme_ns_get_id(ns));
if (!bdev->disk.name) {
free(bdev);
return -ENOMEM;
nvme_ctrlr_populate_namespace_done(ctx, nvme_ns, -ENOMEM);
return;
}
bdev->disk.product_name = "NVMe disk";
@ -862,19 +866,19 @@ nvme_ctrlr_populate_standard_namespace(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr,
if (rc) {
free(bdev->disk.name);
free(bdev);
return rc;
nvme_ctrlr_populate_namespace_done(ctx, nvme_ns, rc);
return;
}
nvme_bdev_attach_bdev_to_ns(nvme_ns, bdev);
return 0;
nvme_ctrlr_populate_namespace_done(ctx, nvme_ns, 0);
}
static int
static void
nvme_ctrlr_populate_ocssd_namespace(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr,
struct nvme_bdev_ns *nvme_ns, struct nvme_async_probe_ctx *ctx)
{
return 0;
nvme_ctrlr_populate_namespace_done(ctx, nvme_ns, 0);
}
static bool
@ -1019,10 +1023,10 @@ nvme_ctrlr_depopulate_ocssd_namespace(struct nvme_bdev_ns *ns)
{
}
static int nvme_ctrlr_populate_namespace(struct nvme_bdev_ctrlr *ctrlr, struct nvme_bdev_ns *ns,
static void nvme_ctrlr_populate_namespace(struct nvme_bdev_ctrlr *ctrlr, struct nvme_bdev_ns *ns,
struct nvme_async_probe_ctx *ctx)
{
return g_populate_namespace_fn[ns->type](ctrlr, ns, ctx);
g_populate_namespace_fn[ns->type](ctrlr, ns, ctx);
}
static void nvme_ctrlr_depopulate_namespace(struct nvme_bdev_ctrlr *ctrlr, struct nvme_bdev_ns *ns)
@ -1039,6 +1043,13 @@ nvme_ctrlr_populate_namespace_done(struct nvme_async_probe_ctx *ctx,
} else {
memset(ns, 0, sizeof(*ns));
}
if (ctx) {
ctx->populates_in_progress--;
if (ctx->populates_in_progress == 0) {
nvme_ctrlr_populate_namespaces_done(ctx);
}
}
}
static void
@ -1048,7 +1059,13 @@ nvme_ctrlr_populate_namespaces(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr,
struct spdk_nvme_ctrlr *ctrlr = nvme_bdev_ctrlr->ctrlr;
struct nvme_bdev_ns *ns;
uint32_t i;
int rc;
if (ctx) {
/* Initialize this count to 1 to handle the populate functions
* calling nvme_ctrlr_populate_namespace_done() immediately.
*/
ctx->populates_in_progress = 1;
}
for (i = 0; i < nvme_bdev_ctrlr->num_ns; i++) {
uint32_t nsid = i + 1;
@ -1065,8 +1082,10 @@ nvme_ctrlr_populate_namespaces(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr,
TAILQ_INIT(&ns->bdevs);
rc = nvme_ctrlr_populate_namespace(nvme_bdev_ctrlr, ns, ctx);
nvme_ctrlr_populate_namespace_done(ctx, ns, rc);
if (ctx) {
ctx->populates_in_progress++;
}
nvme_ctrlr_populate_namespace(nvme_bdev_ctrlr, ns, ctx);
}
if (ns->populated && !spdk_nvme_ctrlr_is_active_ns(ctrlr, nsid)) {
@ -1074,6 +1093,18 @@ nvme_ctrlr_populate_namespaces(struct nvme_bdev_ctrlr *nvme_bdev_ctrlr,
}
}
if (ctx) {
/* Decrement this count now that the loop is over to account
* for the one we started with. If the count is then 0, we
* know any populate_namespace functions completed immediately,
* so we'll kick the callback here.
*/
ctx->populates_in_progress--;
if (ctx->populates_in_progress == 0) {
nvme_ctrlr_populate_namespaces_done(ctx);
}
}
}
static void
@ -1403,7 +1434,6 @@ bdev_nvme_populate_namespaces(struct nvme_async_probe_ctx *ctx)
assert(nvme_bdev_ctrlr != NULL);
nvme_ctrlr_populate_namespaces(nvme_bdev_ctrlr, ctx);
nvme_ctrlr_populate_namespaces_done(ctx);
}
static void

View File

@ -110,6 +110,7 @@ struct nvme_async_probe_ctx {
struct spdk_nvme_ctrlr_opts opts;
spdk_bdev_create_nvme_fn cb_fn;
void *cb_ctx;
uint32_t populates_in_progress;
};
void nvme_ctrlr_populate_namespace_done(struct nvme_async_probe_ctx *ctx,