Commit dbdf54f1 authored by Tomasz Zawadzki's avatar Tomasz Zawadzki
Browse files

bdev/lvol: unload empty lvs during fini_start



This patch makes use of async_fini_start flag to
make fini_start asynchronous.

During this time all lvol stores which have no open
lvols are unloaded. This is required, since lvs
holds claim on the underlying bdev.

Fixes #1630

Signed-off-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: If443cb087324d08a4a70df71c7afd930ab654f90
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9095


Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 511fe155
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ static struct spdk_bdev_module g_lvol_if = {
	.name = "lvol",
	.module_init = vbdev_lvs_init,
	.fini_start = vbdev_lvs_fini_start,
	.async_fini_start = true,
	.examine_disk = vbdev_lvs_examine,
	.get_ctx_size = vbdev_lvs_get_ctx_size,

@@ -1230,10 +1231,47 @@ vbdev_lvs_init(void)
	return 0;
}

static void vbdev_lvs_fini_start_iter(struct lvol_store_bdev *lvs_bdev);

static void
vbdev_lvs_fini_start_unload_cb(void *cb_arg, int lvserrno)
{
	struct lvol_store_bdev *lvs_bdev = cb_arg;
	struct lvol_store_bdev *next_lvs_bdev = vbdev_lvol_store_next(lvs_bdev);

	if (lvserrno != 0) {
		SPDK_INFOLOG(vbdev_lvol, "Lvol store removed with error: %d.\n", lvserrno);
	}

	TAILQ_REMOVE(&g_spdk_lvol_pairs, lvs_bdev, lvol_stores);
	free(lvs_bdev);

	vbdev_lvs_fini_start_iter(next_lvs_bdev);
}

static void
vbdev_lvs_fini_start_iter(struct lvol_store_bdev *lvs_bdev)
{
	struct spdk_lvol_store *lvs;

	while (lvs_bdev != NULL) {
		lvs = lvs_bdev->lvs;

		if (_vbdev_lvs_are_lvols_closed(lvs)) {
			spdk_lvs_unload(lvs, vbdev_lvs_fini_start_unload_cb, lvs_bdev);
			return;
		}
		lvs_bdev = vbdev_lvol_store_next(lvs_bdev);
	}

	spdk_bdev_module_fini_start_done();
}

static void
vbdev_lvs_fini_start(void)
{
	g_shutdown_started = true;
	vbdev_lvs_fini_start_iter(vbdev_lvol_store_first());
}

static int
+25 −1
Original line number Diff line number Diff line
@@ -61,6 +61,8 @@ bool g_examine_done = false;
bool g_bdev_alias_already_exists = false;
bool g_lvs_with_name_already_exists = false;

DEFINE_STUB_V(spdk_bdev_module_fini_start_done, (void));

const struct spdk_bdev_aliases_list *
spdk_bdev_get_aliases(const struct spdk_bdev *bdev)
{
@@ -1042,7 +1044,29 @@ ut_bdev_finish(void)
	int sz = 10;
	int rc;

	/* Test creating lvs with two lvols. Delete first lvol explicitly,
	/* Scenario 1
	 * Test unload of lvs with no lvols during bdev finish. */

	rc = vbdev_lvs_create("bdev", "lvs", 0, LVS_CLEAR_WITH_UNMAP,
			      lvol_store_op_with_handle_complete, NULL);
	CU_ASSERT(rc == 0);
	CU_ASSERT(g_lvserrno == 0);
	SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
	lvs = g_lvol_store;

	/* Start bdev finish */
	vbdev_lvs_fini_start();
	CU_ASSERT(g_shutdown_started == true);

	/* During shutdown, lvs with no lvols should be unloaded */
	CU_ASSERT(g_lvol_store == NULL);
	CU_ASSERT(TAILQ_EMPTY(&g_spdk_lvol_pairs));

	/* Revert module state back to normal */
	g_shutdown_started = false;

	/* Scenario 2
	 * Test creating lvs with two lvols. Delete first lvol explicitly,
	 * then start bdev finish. This should unload the remaining lvol and
	 * lvol store. */