bdev: add new fini_start notification callback for modules

When an SPDK application shuts down, the bdev layer will
automatically unregister all of the bdevs to ensure they
are properly quiesced and cleaned up.

Some modules may want to perform different operations when
a bdev is destructed during normal runtime vs. shutdown.
For example, for lvol, when the last lvol is cleaned up,
it should unload the lvolstore, release and close the bdev
that contains the lvolstore.  You never want to do this
during normal runtime though - it is perfectly valid to
have an lvolstore that contains no lvols.  RAID and future
bdev modules such as multipath have similar use cases.

So add a new bdev module callback named "fini_start".
If a module specifies a function pointer for this callback,
the bdev layer will call it before it starts the bdev
unregistrations.

This enables some future patches to the bdev layer such
that it will always unregister block devices that are not
claimed (i.e. logical volumes) before block devices that
are claimed (i.e. the bdev containing an lvolstore).

Signed-off-by: Jim Harris <james.r.harris@intel.com>
Change-Id: I6e87f5c2b27f16731ea5def858f26e882a29495a

Reviewed-on: https://review.gerrithub.io/421175
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
Jim Harris 2018-08-02 11:20:56 -07:00
parent 341fff6397
commit c899854d03
3 changed files with 28 additions and 1 deletions

View File

@ -67,9 +67,18 @@ struct spdk_bdev_module {
*/
void (*init_complete)(void);
/**
* Optional callback for modules that require notification of when
* the bdev subsystem is starting the fini process.
*
* Modules are not required to define this function.
*/
void (*fini_start)(void);
/**
* Finish function for the module. Called by the spdk application
* before the spdk application exits to perform any necessary cleanup.
* after all bdevs for all modules have been unregistered. This allows
* the module to do any final cleanup before the SPDK application exits.
*
* Modules are not required to define this function.
*/

View File

@ -932,6 +932,8 @@ _spdk_bdev_finish_unregister_bdevs_iter(void *cb_arg, int bdeverrno)
void
spdk_bdev_finish(spdk_bdev_fini_cb cb_fn, void *cb_arg)
{
struct spdk_bdev_module *m;
assert(cb_fn != NULL);
g_fini_thread = spdk_get_thread();
@ -939,6 +941,12 @@ spdk_bdev_finish(spdk_bdev_fini_cb cb_fn, void *cb_arg)
g_fini_cb_fn = cb_fn;
g_fini_cb_arg = cb_arg;
TAILQ_FOREACH(m, &g_bdev_mgr.bdev_modules, internal.tailq) {
if (m->fini_start) {
m->fini_start();
}
}
_spdk_bdev_finish_unregister_bdevs_iter(NULL, 0);
}

View File

@ -71,6 +71,7 @@ bool g_teardown_done = false;
bool g_get_io_channel = true;
bool g_create_ch = true;
bool g_init_complete_called = false;
bool g_fini_start_called = true;
static int
stub_create_ch(void *io_device, void *ctx_buf)
@ -190,11 +191,18 @@ init_complete(void)
g_init_complete_called = true;
}
static void
fini_start(void)
{
g_fini_start_called = true;
}
struct spdk_bdev_module bdev_ut_if = {
.name = "bdev_ut",
.module_init = module_init,
.module_fini = module_fini,
.init_complete = init_complete,
.fini_start = fini_start,
};
SPDK_BDEV_MODULE_REGISTER(&bdev_ut_if)
@ -302,7 +310,9 @@ basic(void)
CU_ASSERT(g_ut_threads[0].ch != NULL);
spdk_put_io_channel(g_ut_threads[0].ch);
g_fini_start_called = false;
teardown_test();
CU_ASSERT(g_fini_start_called == true);
}
static void