bdev: make module init asynchronous again

bdev_virtio requires us to do SCSI inquiry for
each device and wait for a response. It currently
polls inline for this response, taking up entire
reactor exclusively. Making it async would allow
other pollers to run while bdev_virtio still has
to wait.

Change-Id: Iefc88e0a2efb5b791ffe23b2e623b7c50d759084
Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/375573
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
Dariusz Stojaczyk 2017-08-24 17:36:25 +02:00 committed by Jim Harris
parent 5557843311
commit c5ff3d7d26
2 changed files with 49 additions and 28 deletions

View File

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

View File

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