diff --git a/include/spdk/bdev_module.h b/include/spdk/bdev_module.h index 317dd64ad..074cb6438 100644 --- a/include/spdk/bdev_module.h +++ b/include/spdk/bdev_module.h @@ -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. */ diff --git a/lib/bdev/bdev.c b/lib/bdev/bdev.c index c8b28a2a9..20ba9a731 100644 --- a/lib/bdev/bdev.c +++ b/lib/bdev/bdev.c @@ -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); } diff --git a/test/unit/lib/bdev/mt/bdev.c/bdev_ut.c b/test/unit/lib/bdev/mt/bdev.c/bdev_ut.c index 7644f45a3..680e1c95e 100644 --- a/test/unit/lib/bdev/mt/bdev.c/bdev_ut.c +++ b/test/unit/lib/bdev/mt/bdev.c/bdev_ut.c @@ -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