From 8129ede1c8bee45907a811f726523fe57b11836b Mon Sep 17 00:00:00 2001 From: Changpeng Liu Date: Tue, 5 Mar 2019 02:26:58 -0500 Subject: [PATCH] bdev/nvme: use asynchronous API to probe user specified controller NVMe controller can be attached via asynchronous API now, we added the RPC 'construct_nvme_bdev' with asynchronous probe support so that the initialization can be processed later. Change-Id: Ic60fdde6af9c4ba9a07b874852cfba044acb06c Signed-off-by: Changpeng Liu Change-Id: Ic60fdde6af9c4ba9a07b874852cfba044acb06c8 Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/445054 Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: wuzhouhui Reviewed-by: Shuhei Matsumoto Reviewed-by: Darek Stojaczyk --- lib/bdev/nvme/bdev_nvme.c | 91 ++++++++++++++++++++++++++++------- lib/bdev/nvme/bdev_nvme.h | 4 +- lib/bdev/nvme/bdev_nvme_rpc.c | 4 +- 3 files changed, 77 insertions(+), 22 deletions(-) diff --git a/lib/bdev/nvme/bdev_nvme.c b/lib/bdev/nvme/bdev_nvme.c index 388aac946..bece36fe7 100644 --- a/lib/bdev/nvme/bdev_nvme.c +++ b/lib/bdev/nvme/bdev_nvme.c @@ -1183,6 +1183,55 @@ bdev_nvme_create_and_get_bdev_names(struct spdk_nvme_ctrlr *ctrlr, return 0; } +struct nvme_async_probe_ctx { + struct spdk_nvme_probe_ctx *probe_ctx; + const char *base_name; + const char **names; + size_t *count; + uint32_t prchk_flags; + struct spdk_poller *poller; + struct spdk_nvme_transport_id trid; + struct spdk_nvme_ctrlr_opts opts; + spdk_bdev_create_nvme_fn cb_fn; + void *cb_ctx; +}; + +static void +connect_attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, + struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts) +{ + struct spdk_nvme_ctrlr_opts *user_opts = cb_ctx; + struct nvme_async_probe_ctx *ctx; + int rc; + + ctx = SPDK_CONTAINEROF(user_opts, struct nvme_async_probe_ctx, opts); + rc = bdev_nvme_create_and_get_bdev_names(ctrlr, + ctx->base_name, + ctx->names, ctx->count, + &ctx->trid, + ctx->prchk_flags); + + if (ctx->cb_fn) { + ctx->cb_fn(ctx->cb_ctx, rc); + } +} + +static int +bdev_nvme_async_poll(void *arg) +{ + struct nvme_async_probe_ctx *ctx = arg; + int done; + + done = spdk_nvme_probe_poll_async(ctx->probe_ctx); + /* retry again */ + if (done == -EAGAIN) { + return 1; + } + spdk_poller_unregister(&ctx->poller); + free(ctx); + return 1; +} + int spdk_bdev_nvme_create(struct spdk_nvme_transport_id *trid, struct spdk_nvme_host_id *hostid, @@ -1190,13 +1239,11 @@ spdk_bdev_nvme_create(struct spdk_nvme_transport_id *trid, const char **names, size_t *count, const char *hostnqn, uint32_t prchk_flags, - spdk_bdev_nvme_fn cb_fn, + spdk_bdev_create_nvme_fn cb_fn, void *cb_ctx) { - int rc; - struct spdk_nvme_ctrlr_opts opts; - struct spdk_nvme_ctrlr *ctrlr; struct nvme_probe_skip_entry *entry, *tmp; + struct nvme_async_probe_ctx *ctx; if (nvme_bdev_ctrlr_get(trid) != NULL) { SPDK_ERRLOG("A controller with the provided trid (traddr: %s) already exists.\n", trid->traddr); @@ -1218,33 +1265,41 @@ spdk_bdev_nvme_create(struct spdk_nvme_transport_id *trid, } } - spdk_nvme_ctrlr_get_default_ctrlr_opts(&opts, sizeof(opts)); + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) { + return -ENOMEM; + } + ctx->base_name = base_name; + ctx->names = names; + ctx->count = count; + ctx->cb_fn = cb_fn; + ctx->cb_ctx = cb_ctx; + ctx->prchk_flags = prchk_flags; + ctx->trid = *trid; + + spdk_nvme_ctrlr_get_default_ctrlr_opts(&ctx->opts, sizeof(ctx->opts)); if (hostnqn) { - snprintf(opts.hostnqn, sizeof(opts.hostnqn), "%s", hostnqn); + snprintf(ctx->opts.hostnqn, sizeof(ctx->opts.hostnqn), "%s", hostnqn); } if (hostid->hostaddr[0] != '\0') { - snprintf(opts.src_addr, sizeof(opts.src_addr), "%s", hostid->hostaddr); + snprintf(ctx->opts.src_addr, sizeof(ctx->opts.src_addr), "%s", hostid->hostaddr); } if (hostid->hostsvcid[0] != '\0') { - snprintf(opts.src_svcid, sizeof(opts.src_svcid), "%s", hostid->hostsvcid); + snprintf(ctx->opts.src_svcid, sizeof(ctx->opts.src_svcid), "%s", hostid->hostsvcid); } - ctrlr = spdk_nvme_connect(trid, &opts, sizeof(opts)); - if (!ctrlr) { - SPDK_ERRLOG("Failed to create new device\n"); + ctx->probe_ctx = spdk_nvme_connect_async(trid, &ctx->opts, connect_attach_cb); + if (ctx->probe_ctx == NULL) { + SPDK_ERRLOG("No controller was found with provided trid (traddr: %s)\n", trid->traddr); + free(ctx); return -1; } + ctx->poller = spdk_poller_register(bdev_nvme_async_poll, ctx, 1000); - rc = bdev_nvme_create_and_get_bdev_names(ctrlr, base_name, names, - count, trid, prchk_flags); - if (rc == 0 && cb_fn) { - cb_fn(cb_ctx); - } - - return rc; + return 0; } int diff --git a/lib/bdev/nvme/bdev_nvme.h b/lib/bdev/nvme/bdev_nvme.h index e9ecdb7be..150351dfc 100644 --- a/lib/bdev/nvme/bdev_nvme.h +++ b/lib/bdev/nvme/bdev_nvme.h @@ -54,7 +54,7 @@ struct spdk_bdev_nvme_opts { uint64_t nvme_ioq_poll_period_us; }; -typedef void (*spdk_bdev_nvme_fn)(void *ctx); +typedef void (*spdk_bdev_create_nvme_fn)(void *ctx, int rc); struct spdk_nvme_qpair *spdk_bdev_nvme_get_io_qpair(struct spdk_io_channel *ctrlr_io_ch); void spdk_bdev_nvme_get_opts(struct spdk_bdev_nvme_opts *opts); int spdk_bdev_nvme_set_opts(const struct spdk_bdev_nvme_opts *opts); @@ -66,7 +66,7 @@ int spdk_bdev_nvme_create(struct spdk_nvme_transport_id *trid, const char **names, size_t *count, const char *hostnqn, uint32_t prchk_flags, - spdk_bdev_nvme_fn cb_fn, + spdk_bdev_create_nvme_fn cb_fn, void *cb_ctx); struct spdk_nvme_ctrlr *spdk_bdev_nvme_get_ctrlr(struct spdk_bdev *bdev); diff --git a/lib/bdev/nvme/bdev_nvme_rpc.c b/lib/bdev/nvme/bdev_nvme_rpc.c index ef646621c..2334abe4b 100644 --- a/lib/bdev/nvme/bdev_nvme_rpc.c +++ b/lib/bdev/nvme/bdev_nvme_rpc.c @@ -213,7 +213,7 @@ struct rpc_create_nvme_bdev_ctx { }; static void -spdk_rpc_construct_nvme_bdev_done(void *cb_ctx) +spdk_rpc_construct_nvme_bdev_done(void *cb_ctx, int rc) { struct rpc_create_nvme_bdev_ctx *ctx = cb_ctx; struct spdk_jsonrpc_request *request = ctx->request; @@ -225,7 +225,7 @@ spdk_rpc_construct_nvme_bdev_done(void *cb_ctx) goto exit; } - if (ctx->count == 0) { + if (rc < 0) { spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); goto exit; }