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 <konrad.sztyber@intel.com>
Change-Id: I084502ae38c9ae5e385e5566550ec3cb8b6f9d2e
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/448630
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Wojciech Malikowski <wojciech.malikowski@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Konrad Sztyber 2019-03-20 09:36:02 +01:00 committed by Jim Harris
parent a0cb5e9d77
commit 1d98208176
2 changed files with 88 additions and 13 deletions

View File

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

View File

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