From 151e37cfaa233273fb1dcbf1136894b27f321d05 Mon Sep 17 00:00:00 2001 From: Wojciech Malikowski Date: Tue, 15 Oct 2019 08:14:49 -0400 Subject: [PATCH] bdev/ftl: Examine config support Bdev FTL is dependent on base bdev and cache bdev. Allow for examine config if dependent bdevs are not ready during bdev FTL creation. Change-Id: I917994d7015f3b74a29ccd066f0c6989ad3c1c4e Signed-off-by: Wojciech Malikowski Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/471375 Tested-by: SPDK CI Jenkins Community-CI: Broadcom SPDK FC-NVMe CI Reviewed-by: Jim Harris Reviewed-by: Tomasz Zawadzki Reviewed-by: Konrad Sztyber --- module/bdev/ftl/bdev_ftl.c | 107 +++++++++++++++++++++++++++++++++ module/bdev/ftl/bdev_ftl_rpc.c | 13 +++- test/ftl/json.sh | 7 ++- 3 files changed, 122 insertions(+), 5 deletions(-) diff --git a/module/bdev/ftl/bdev_ftl.c b/module/bdev/ftl/bdev_ftl.c index 8225bcbdb..9b3d9a252 100644 --- a/module/bdev/ftl/bdev_ftl.c +++ b/module/bdev/ftl/bdev_ftl.c @@ -90,8 +90,11 @@ struct ftl_deferred_init { LIST_ENTRY(ftl_deferred_init) entry; }; +static LIST_HEAD(, ftl_deferred_init) g_deferred_init = LIST_HEAD_INITIALIZER(g_deferred_init); + static int bdev_ftl_initialize(void); static void bdev_ftl_finish(void); +static void bdev_ftl_examine(struct spdk_bdev *bdev); static int bdev_ftl_get_ctx_size(void) @@ -103,6 +106,7 @@ static struct spdk_bdev_module g_ftl_if = { .name = "ftl", .module_init = bdev_ftl_initialize, .module_fini = bdev_ftl_finish, + .examine_disk = bdev_ftl_examine, .get_ctx_size = bdev_ftl_get_ctx_size, }; @@ -527,6 +531,58 @@ error_dev: init_cb(NULL, init_arg, rc); } +static void +bdev_ftl_defer_free(struct ftl_deferred_init *init) +{ + free((char *)init->opts.name); + free((char *)init->opts.base_bdev); + free((char *)init->opts.cache_bdev); + free(init); +} + +static int +bdev_ftl_defer_init(const struct ftl_bdev_init_opts *opts) +{ + struct ftl_deferred_init *init; + + init = calloc(1, sizeof(*init)); + if (!init) { + return -ENOMEM; + } + + init->opts.mode = opts->mode; + init->opts.uuid = opts->uuid; + init->opts.ftl_conf = opts->ftl_conf; + + init->opts.name = strdup(opts->name); + if (!init->opts.name) { + SPDK_ERRLOG("Could not allocate bdev name\n"); + goto error; + } + + init->opts.base_bdev = strdup(opts->base_bdev); + if (!init->opts.base_bdev) { + SPDK_ERRLOG("Could not allocate base bdev name\n"); + goto error; + } + + if (opts->cache_bdev) { + init->opts.cache_bdev = strdup(opts->cache_bdev); + if (!init->opts.cache_bdev) { + SPDK_ERRLOG("Could not allocate cache bdev name\n"); + goto error; + } + } + + LIST_INSERT_HEAD(&g_deferred_init, init, entry); + + return 0; + +error: + bdev_ftl_defer_free(init); + return -ENOMEM; +} + static int bdev_ftl_init_dependent_bdev(struct ftl_bdev *ftl_bdev, const char *bdev_name, struct spdk_bdev_desc **bdev_desc) @@ -574,6 +630,15 @@ bdev_ftl_create_bdev(const struct ftl_bdev_init_opts *bdev_opts, goto error_bdev; } + if (spdk_bdev_get_by_name(bdev_opts->base_bdev) == NULL || + (bdev_opts->cache_bdev && spdk_bdev_get_by_name(bdev_opts->cache_bdev) == NULL)) { + rc = bdev_ftl_defer_init(bdev_opts); + if (rc == 0) { + rc = -ENODEV; + } + goto error_name; + } + rc = bdev_ftl_init_dependent_bdev(ftl_bdev, bdev_opts->base_bdev, &ftl_bdev->base_bdev_desc); if (rc) { @@ -654,4 +719,46 @@ bdev_ftl_finish(void) { } +static void +bdev_ftl_create_defered_cb(const struct ftl_bdev_info *info, void *ctx, int status) +{ + struct ftl_deferred_init *opts = ctx; + + if (status) { + SPDK_ERRLOG("Failed to initialize FTL bdev '%s'\n", opts->opts.name); + } + + bdev_ftl_defer_free(opts); + + spdk_bdev_module_examine_done(&g_ftl_if); +} + +static void +bdev_ftl_examine(struct spdk_bdev *bdev) +{ + struct ftl_deferred_init *opts; + + LIST_FOREACH(opts, &g_deferred_init, entry) { + if (spdk_bdev_get_by_name(opts->opts.base_bdev) == NULL) { + continue; + } + + if (opts->opts.cache_bdev && spdk_bdev_get_by_name(opts->opts.base_bdev) == NULL) { + continue; + } + + LIST_REMOVE(opts, entry); + + /* spdk_bdev_module_examine_done will be called by bdev_ftl_create_defered_cb */ + if (bdev_ftl_create_bdev(&opts->opts, bdev_ftl_create_defered_cb, opts)) { + SPDK_ERRLOG("Failed to initialize FTL bdev '%s'\n", opts->opts.name); + bdev_ftl_defer_free(opts); + break; + } + return; + } + + spdk_bdev_module_examine_done(&g_ftl_if); +} + SPDK_LOG_REGISTER_COMPONENT("bdev_ftl", SPDK_LOG_BDEV_FTL) diff --git a/module/bdev/ftl/bdev_ftl_rpc.c b/module/bdev/ftl/bdev_ftl_rpc.c index 42a173654..6aab475f1 100644 --- a/module/bdev/ftl/bdev_ftl_rpc.c +++ b/module/bdev/ftl/bdev_ftl_rpc.c @@ -148,6 +148,7 @@ spdk_rpc_bdev_ftl_create(struct spdk_jsonrpc_request *request, { struct rpc_bdev_ftl_create req = {}; struct ftl_bdev_init_opts opts = {}; + struct spdk_json_write_ctx *w; int rc; spdk_ftl_conf_init_defaults(&req.ftl_conf); @@ -187,9 +188,15 @@ spdk_rpc_bdev_ftl_create(struct spdk_jsonrpc_request *request, rc = bdev_ftl_create_bdev(&opts, _spdk_rpc_bdev_ftl_create_cb, request); if (rc) { - spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, - "Failed to create FTL bdev: %s", - spdk_strerror(-rc)); + if (rc == -ENODEV) { + w = spdk_jsonrpc_begin_result(request); + spdk_json_write_string_fmt(w, "FTL bdev: %s creation deferred", req.name); + spdk_jsonrpc_end_result(request, w); + } else { + spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, + "Failed to create FTL bdev: %s", + spdk_strerror(-rc)); + } goto invalid; } diff --git a/test/ftl/json.sh b/test/ftl/json.sh index 463b5605e..11f902f5a 100755 --- a/test/ftl/json.sh +++ b/test/ftl/json.sh @@ -20,9 +20,12 @@ $rootdir/app/spdk_tgt/spdk_tgt & svcpid=$! waitforlisten $svcpid # Create new bdev from json configuration -$rootdir/scripts/gen_ftl.sh -j -a $device -n nvme0 | $rpc_py load_subsystem_config +$rootdir/scripts/gen_ftl.sh -n ftl0 -d nvme0n1 | $rpc_py load_subsystem_config +$rpc_py bdev_nvme_attach_controller -b nvme0 -a $device -t pcie +$rpc_py bdev_ocssd_create -c nvme0 -b nvme0n1 -n 1 -uuid=$($rpc_py bdev_get_bdevs | jq -r '.[0].uuid') +waitforbdev ftl0 +uuid=$($rpc_py bdev_get_bdevs | jq -r ".[] | select(.name==\"ftl0\").uuid") $rpc_py bdev_ftl_delete -b nvme0