diff --git a/include/spdk_internal/bdev.h b/include/spdk_internal/bdev.h index d03d3f09d..1db779413 100644 --- a/include/spdk_internal/bdev.h +++ b/include/spdk_internal/bdev.h @@ -115,10 +115,10 @@ struct spdk_bdev_module_if { void (*examine)(struct spdk_bdev *bdev); /** - * Count of bdev examinations in progress. Used by generic bdev layer and must - * not be modified by bdev modules. + * Count of bdev inits/examinations in progress. Used by generic bdev + * layer and must not be modified by bdev modules. */ - uint32_t examine_in_progress; + uint32_t action_in_progress; TAILQ_ENTRY(spdk_bdev_module_if) tailq; }; @@ -384,7 +384,7 @@ void spdk_vbdev_register(struct spdk_bdev *vbdev, struct spdk_bdev **base_bdevs, void spdk_vbdev_unregister(struct spdk_bdev *vbdev); void spdk_bdev_module_examine_done(struct spdk_bdev_module_if *module); - +void spdk_bdev_module_init_done(struct spdk_bdev_module_if *module); int spdk_bdev_module_claim_bdev(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_bdev_module_if *module); void spdk_bdev_module_release_bdev(struct spdk_bdev *bdev); @@ -437,7 +437,7 @@ spdk_bdev_io_from_ctx(void *ctx) ((uintptr_t)ctx - offsetof(struct spdk_bdev_io, driver_ctx)); } -#define SPDK_BDEV_MODULE_REGISTER(_name, init_fn, fini_fn, config_fn, ctx_size_fn, examine_fn)\ +#define SPDK_BDEV_MODULE_REGISTER(_name, init_fn, fini_fn, config_fn, ctx_size_fn, examine_fn) \ static struct spdk_bdev_module_if _name ## _if = { \ .name = #_name, \ .module_init = init_fn, \ @@ -451,7 +451,17 @@ spdk_bdev_io_from_ctx(void *ctx) spdk_bdev_module_list_add(&_name ## _if); \ } -#define SPDK_GET_BDEV_MODULE(name) &name ## _if +#define SPDK_GET_BDEV_MODULE(name) (&name ## _if) + +/* + * Set module initialization to be asynchronous. After using this macro, the module + * initialization has to be explicitly finished by calling spdk_bdev_module_init_done(). + */ +#define SPDK_BDEV_MODULE_ASYNC_INIT(name) \ + __attribute__((constructor)) static void name ## _async_init(void) \ + { \ + SPDK_GET_BDEV_MODULE(name)->action_in_progress = 1; \ + } /* * Modules are not required to use this macro. It allows modules to reference the module with diff --git a/lib/bdev/bdev.c b/lib/bdev/bdev.c index fcb72d579..05f3691f1 100644 --- a/lib/bdev/bdev.c +++ b/lib/bdev/bdev.c @@ -366,24 +366,53 @@ spdk_bdev_module_action_complete(void) struct spdk_bdev_module_if *m; /* - * Check all bdev modules for an examinations in progress. If any + * Don't finish bdev subsystem initialization if + * module pre-initialization is still in progress, or + * the subsystem been already initialized. + */ + if (!g_bdev_mgr.module_init_complete || g_bdev_mgr.init_complete) { + return; + } + + /* + * Check all bdev modules for inits/examinations in progress. If any * exist, return immediately since we cannot finish bdev subsystem * initialization until all are completed. */ TAILQ_FOREACH(m, &g_bdev_mgr.bdev_modules, tailq) { - if (m->examine_in_progress > 0) { + if (m->action_in_progress > 0) { return; } } /* * Modules already finished initialization - now that all - * the bdev moduless have finished their asynchronous I/O + * the bdev modules have finished their asynchronous I/O * processing, the entire bdev layer can be marked as complete. */ spdk_bdev_init_complete(0); } +static void +spdk_bdev_module_action_done(struct spdk_bdev_module_if *module) +{ + assert(module->action_in_progress > 0); + module->action_in_progress--; + spdk_bdev_module_action_complete(); +} + +void +spdk_bdev_module_init_done(struct spdk_bdev_module_if *module) +{ + spdk_bdev_module_action_done(module); +} + +void +spdk_bdev_module_examine_done(struct spdk_bdev_module_if *module) +{ + spdk_bdev_module_action_done(module); +} + static int spdk_bdev_modules_init(void) { @@ -1433,7 +1462,7 @@ _spdk_bdev_register(struct spdk_bdev *bdev) TAILQ_FOREACH(module, &g_bdev_mgr.bdev_modules, tailq) { if (module->examine) { - module->examine_in_progress++; + module->action_in_progress++; module->examine(bdev); } } @@ -1510,24 +1539,6 @@ spdk_vbdev_unregister(struct spdk_bdev *vbdev) spdk_bdev_unregister(vbdev); } -void -spdk_bdev_module_examine_done(struct spdk_bdev_module_if *module) -{ - assert(module->examine_in_progress > 0); - module->examine_in_progress--; - - if (!g_bdev_mgr.module_init_complete || g_bdev_mgr.init_complete) { - /* - * Don't finish bdev subsystem initialization if - * module initialization is still in progress, or - * the subsystem been already initialized. - */ - return; - } - - spdk_bdev_module_action_complete(); -} - int spdk_bdev_open(struct spdk_bdev *bdev, bool write, spdk_bdev_remove_cb_t remove_cb, void *remove_ctx, struct spdk_bdev_desc **_desc)