Commit c5ff3d7d authored by Dariusz Stojaczyk's avatar Dariusz Stojaczyk Committed by Jim Harris
Browse files

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: default avatarDariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/375573


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
parent 55578433
Loading
Loading
Loading
Loading
+16 −6
Original line number Diff line number Diff line
@@ -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);
@@ -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
+33 −22
Original line number Diff line number Diff line
@@ -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)