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:
parent
169e19c320
commit
0cdcf62a65
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user