From 1d9820817607296d7a809a662f66d731ad4db88f Mon Sep 17 00:00:00 2001 From: Konrad Sztyber Date: Wed, 20 Mar 2019 09:36:02 +0100 Subject: [PATCH] bdev/ftl: defer bdev initialization Defer the initialization when cache bdev mentioned in the config doesn't exist when the FTL bdev is being created. Signed-off-by: Konrad Sztyber Change-Id: I084502ae38c9ae5e385e5566550ec3cb8b6f9d2e Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/448630 Reviewed-by: Jim Harris Reviewed-by: Paul Luse Reviewed-by: Shuhei Matsumoto Reviewed-by: Wojciech Malikowski Reviewed-by: Darek Stojaczyk Tested-by: SPDK CI Jenkins --- lib/bdev/nvme/bdev_ftl.c | 91 ++++++++++++++++++++++++++++++++++++---- scripts/gen_ftl.sh | 10 +++-- 2 files changed, 88 insertions(+), 13 deletions(-) diff --git a/lib/bdev/nvme/bdev_ftl.c b/lib/bdev/nvme/bdev_ftl.c index ca8f43f01..4acec500c 100644 --- a/lib/bdev/nvme/bdev_ftl.c +++ b/lib/bdev/nvme/bdev_ftl.c @@ -89,6 +89,12 @@ struct ftl_bdev_io { struct spdk_thread *orig_thread; }; +struct ftl_deferred_init { + struct ftl_bdev_init_opts opts; + + LIST_ENTRY(ftl_deferred_init) entry; +}; + typedef void (*bdev_ftl_finish_fn)(void); static LIST_HEAD(, ftl_bdev) g_ftl_bdevs = LIST_HEAD_INITIALIZER(g_ftl_bdevs); @@ -96,9 +102,11 @@ static bdev_ftl_finish_fn g_finish_cb; static size_t g_num_conf_bdevs; static size_t g_num_init_bdevs; static pthread_mutex_t g_ftl_bdev_lock; +static LIST_HEAD(, ftl_deferred_init) g_deferred_init; static int bdev_ftl_initialize(void); static void bdev_ftl_finish(void); +static void bdev_ftl_examine(struct spdk_bdev *); static int bdev_ftl_get_ctx_size(void) @@ -112,6 +120,7 @@ static struct spdk_bdev_module g_ftl_if = { .async_fini = true, .module_init = bdev_ftl_initialize, .module_fini = bdev_ftl_finish, + .examine_disk = bdev_ftl_examine, .get_ctx_size = bdev_ftl_get_ctx_size, }; @@ -492,13 +501,29 @@ out: return rc; } +static int +bdev_ftl_defer_init(struct ftl_bdev_init_opts *opts) +{ + struct ftl_deferred_init *init; + + init = calloc(1, sizeof(*init)); + if (!init) { + return -ENOMEM; + } + + init->opts = *opts; + LIST_INSERT_HEAD(&g_deferred_init, init, entry); + + return 0; +} + static int bdev_ftl_read_bdev_config(struct spdk_conf_section *sp, struct ftl_bdev_init_opts *opts, size_t *num_bdevs) { const char *val, *trid; - int i, rc = 0; + int i, rc = 0, num_deferred = 0; *num_bdevs = 0; @@ -567,17 +592,22 @@ bdev_ftl_read_bdev_config(struct spdk_conf_section *sp, continue; } - if (!spdk_bdev_get_by_name(val)) { - SPDK_ERRLOG("Invalid cache bdev name: %s for TransportID: %s\n", val, trid); - rc = -1; - break; - } - opts->cache_bdev = val; + if (!spdk_bdev_get_by_name(val)) { + SPDK_INFOLOG(SPDK_LOG_BDEV_FTL, "Deferring bdev %s initialization\n", opts->name); + + if (bdev_ftl_defer_init(opts)) { + SPDK_ERRLOG("Unable to initialize bdev %s\n", opts->name); + rc = -1; + break; + } + + num_deferred++; + } } if (!rc) { - *num_bdevs = i; + *num_bdevs = i - num_deferred; } return rc; @@ -818,10 +848,21 @@ bdev_ftl_bdev_init_done(void) static void bdev_ftl_init_cb(const struct ftl_bdev_info *info, void *ctx, int status) { + struct ftl_deferred_init *opts; + if (status) { SPDK_ERRLOG("Failed to initialize FTL bdev\n"); } + LIST_FOREACH(opts, &g_deferred_init, entry) { + if (!strcmp(opts->opts.name, info->name)) { + spdk_bdev_module_examine_done(&g_ftl_if); + LIST_REMOVE(opts, entry); + free(opts); + break; + } + } + bdev_ftl_bdev_init_done(); } @@ -830,6 +871,7 @@ bdev_ftl_initialize_cb(void *ctx, int status) { struct spdk_conf_section *sp; struct ftl_bdev_init_opts *opts = NULL; + struct ftl_deferred_init *defer_opts; size_t i; if (status) { @@ -853,7 +895,16 @@ bdev_ftl_initialize_cb(void *ctx, int status) } for (i = 0; i < g_num_conf_bdevs; ++i) { - if (bdev_ftl_init_bdev(&opts[i], bdev_ftl_init_cb, NULL)) { + bool defer_init = false; + + LIST_FOREACH(defer_opts, &g_deferred_init, entry) { + if (!strcmp(defer_opts->opts.name, opts[i].name)) { + defer_init = true; + break; + } + } + + if (!defer_init && bdev_ftl_init_bdev(&opts[i], bdev_ftl_init_cb, NULL)) { SPDK_ERRLOG("Failed to create bdev '%s'\n", opts[i].name); bdev_ftl_bdev_init_done(); } @@ -937,6 +988,28 @@ bdev_ftl_init_bdev(struct ftl_bdev_init_opts *opts, ftl_bdev_init_fn cb, void *c return bdev_ftl_create(ctrlr, opts, cb, cb_arg); } +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.cache_bdev) == bdev) { + if (bdev_ftl_init_bdev(&opts->opts, bdev_ftl_init_cb, NULL)) { + SPDK_ERRLOG("Unable to initialize bdev '%s'\n", opts->opts.name); + LIST_REMOVE(opts, entry); + free(opts); + break; + } + + /* spdk_bdev_module_examine_done will be called by bdev_ftl_init_cb */ + return; + } + } + + spdk_bdev_module_examine_done(&g_ftl_if); +} + void bdev_ftl_delete_bdev(const char *name, spdk_bdev_unregister_cb cb_fn, void *cb_arg) { diff --git a/scripts/gen_ftl.sh b/scripts/gen_ftl.sh index 222e3e249..d1af330d3 100755 --- a/scripts/gen_ftl.sh +++ b/scripts/gen_ftl.sh @@ -5,28 +5,30 @@ set -e rootdir=$(readlink -f $(dirname $0))/.. function usage { - echo "Usage: $0 -a TRANSPORT_ADDR -n BDEV_NAME -l PUNITS [-u UUID]" + echo "Usage: $0 -a TRANSPORT_ADDR -n BDEV_NAME -l PUNITS [-u UUID] [-c CACHE]" echo "UUID is required when restoring device state" echo echo "TRANSPORT_ADDR - SSD's PCIe address" echo "BDEV_NAME - name of the bdev" echo "PUNITS - bdev's parallel unit range (e.g. 0-3)" echo "UUID - bdev's uuid (used when in restore mode)" + echo "CACHE - name of the bdev to be used as write buffer cache" } function generate_config { echo "[Ftl]" - echo " TransportID \"trtype:PCIe traddr:$1\" $2 $3 $4" + echo " TransportID \"trtype:PCIe traddr:$1\" $2 $3 $4 $5" } uuid=00000000-0000-0000-0000-000000000000 -while getopts ":a:n:l:m:u:" arg; do +while getopts ":a:n:l:m:u:c:" arg; do case "$arg" in a) addr=$OPTARG ;; n) name=$OPTARG ;; l) punits=$OPTARG ;; u) uuid=$OPTARG ;; + c) cache=$OPTARG ;; h) usage exit 0 ;; *) usage @@ -39,4 +41,4 @@ if [[ -z "$addr" || -z "$name" || -z "$punits" ]]; then exit 1 fi -generate_config $addr $name $punits $uuid +generate_config $addr $name $punits $uuid $cache