diff --git a/lib/bdev/bdev.c b/lib/bdev/bdev.c index 469be5a53..ca6c23bd0 100644 --- a/lib/bdev/bdev.c +++ b/lib/bdev/bdev.c @@ -100,7 +100,6 @@ static void *g_init_cb_arg = NULL; static spdk_bdev_fini_cb g_fini_cb_fn = NULL; static void *g_fini_cb_arg = NULL; -struct spdk_bdev_module_if *g_bdev_module = NULL; struct spdk_thread *g_fini_thread = NULL; @@ -606,37 +605,52 @@ spdk_bdev_module_finish_complete(void) } static void -_call_next_module_fini(void *arg) +spdk_bdev_module_finish_iter(void *arg) { - struct spdk_bdev_module_if *module = arg; + /* Notice that this variable is static. It is saved between calls to + * this function. */ + static struct spdk_bdev_module_if *resume_bdev_module = NULL; + struct spdk_bdev_module_if *bdev_module; - module->module_fini(); + /* Start iterating from the last touched module */ + if (!resume_bdev_module) { + bdev_module = TAILQ_FIRST(&g_bdev_mgr.bdev_modules); + } else { + bdev_module = TAILQ_NEXT(resume_bdev_module, tailq); + } + + while (bdev_module) { + if (bdev_module->async_fini) { + /* Save our place so we can resume later. We must + * save the variable here, before calling module_fini() + * below, because in some cases the module may immediately + * call spdk_bdev_module_finish_done() and re-enter + * this function to continue iterating. */ + resume_bdev_module = bdev_module; + } + + if (bdev_module->module_fini) { + bdev_module->module_fini(); + } + + if (bdev_module->async_fini) { + return; + } + + bdev_module = TAILQ_NEXT(bdev_module, tailq); + } + + resume_bdev_module = NULL; + spdk_bdev_module_finish_complete(); } void spdk_bdev_module_finish_done(void) { if (spdk_get_thread() != g_fini_thread) { - SPDK_ERRLOG("%s changed threads\n", g_bdev_module->name); - } - - if (!g_bdev_module) { - g_bdev_module = TAILQ_FIRST(&g_bdev_mgr.bdev_modules); + spdk_thread_send_msg(g_fini_thread, spdk_bdev_module_finish_iter, NULL); } else { - g_bdev_module = TAILQ_NEXT(g_bdev_module, tailq); - } - - if (!g_bdev_module) { - spdk_bdev_module_finish_complete(); - return; - } - - if (g_bdev_module->module_fini) { - spdk_thread_send_msg(g_fini_thread, _call_next_module_fini, g_bdev_module); - } - - if (!g_bdev_module->async_fini) { - spdk_bdev_module_finish_done(); + spdk_bdev_module_finish_iter(NULL); } } @@ -650,7 +664,7 @@ spdk_bdev_finish(spdk_bdev_fini_cb cb_fn, void *cb_arg) g_fini_cb_fn = cb_fn; g_fini_cb_arg = cb_arg; - spdk_bdev_module_finish_done(); + spdk_bdev_module_finish_iter(NULL); } struct spdk_bdev_io *