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 <changpeng.liu@intel.com>
Change-Id: Ic60fdde6af9c4ba9a07b874852cfba044acb06c8
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/445054
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: wuzhouhui <wuzhouhui@kingsoft.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
This commit is contained in:
Changpeng Liu 2019-03-05 02:26:58 -05:00 committed by Darek Stojaczyk
parent 4fb2260117
commit 8129ede1c8
3 changed files with 77 additions and 22 deletions

View File

@ -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

View File

@ -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);

View File

@ -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;
}