Commit 5b250c08 authored by Mike Gerdts's avatar Mike Gerdts Committed by Jim Harris
Browse files

vbdev_lvol: load esnaps via examine_config



This introduces an examine_config callback that triggers hotplug of
missing esnap devices.

Signed-off-by: default avatarMike Gerdts <mgerdts@nvidia.com>
Change-Id: I5ced2ff26bfd393d2df4fd4718700be30eb48063
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16626


Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 5e79e84e
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -120,6 +120,7 @@ void spdk_lvol_set_read_only(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn
int spdk_lvs_esnap_missing_add(struct spdk_lvol_store *lvs, struct spdk_lvol *lvol,
			       const void *esnap_id, uint32_t id_len);
void spdk_lvs_esnap_missing_remove(struct spdk_lvol *lvol);
bool spdk_lvs_notify_hotplug(const void *esnap_id, uint32_t id_len);
bool spdk_lvs_notify_hotplug(const void *esnap_id, uint32_t id_len,
			     spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg);

#endif /* SPDK_INTERNAL_LVOLSTORE_H */
+36 −7
Original line number Diff line number Diff line
@@ -1945,26 +1945,37 @@ spdk_lvs_esnap_missing_remove(struct spdk_lvol *lvol)
	free(degraded_set);
}

struct lvs_esnap_hotplug_req {
	struct spdk_lvol			*lvol;
	spdk_lvol_op_with_handle_complete	cb_fn;
	void					*cb_arg;
};

static void
lvs_esnap_hotplug_done(void *cb_arg, int bserrno)
{
	struct spdk_lvol	*lvol = cb_arg;
	struct lvs_esnap_hotplug_req *req = cb_arg;
	struct spdk_lvol	*lvol = req->lvol;
	struct spdk_lvol_store	*lvs = lvol->lvol_store;

	if (bserrno != 0) {
		SPDK_ERRLOG("lvol %s/%s: failed to hotplug blob_bdev due to error %d\n",
			    lvs->name, lvol->name, bserrno);
	}
	req->cb_fn(req->cb_arg, lvol, bserrno);
	free(req);
}

static void
lvs_esnap_degraded_hotplug(struct spdk_lvs_degraded_lvol_set *degraded_set)
lvs_esnap_degraded_hotplug(struct spdk_lvs_degraded_lvol_set *degraded_set,
			   spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
{
	struct spdk_lvol_store	*lvs = degraded_set->lvol_store;
	struct spdk_lvol	*lvol, *tmp, *last_missing;
	struct spdk_bs_dev	*bs_dev;
	const void		*esnap_id = degraded_set->esnap_id;
	uint32_t		id_len = degraded_set->id_len;
	struct lvs_esnap_hotplug_req *req;
	int			rc;

	assert(lvs->thread == spdk_get_thread());
@@ -1984,6 +1995,17 @@ lvs_esnap_degraded_hotplug(struct spdk_lvs_degraded_lvol_set *degraded_set)
	last_missing = TAILQ_LAST(&degraded_set->lvols, degraded_lvols);

	TAILQ_FOREACH_SAFE(lvol, &degraded_set->lvols, degraded_link, tmp) {
		req = calloc(1, sizeof(*req));
		if (req == NULL) {
			SPDK_ERRLOG("lvol %s: failed to create esnap bs_dev: out of memory\n",
				    lvol->unique_id);
			cb_fn(cb_arg, lvol, -ENOMEM);
			/* The next one likely won't succeed either, but keep going so that all the
			 * failed hotplugs are logged.
			 */
			goto next;
		}

		/*
		 * Remove the lvol from the tailq so that tailq corruption is avoided if
		 * lvs->esnap_bs_dev_create() calls spdk_lvs_esnap_missing_add(lvol).
@@ -1998,11 +2020,17 @@ lvs_esnap_degraded_hotplug(struct spdk_lvs_degraded_lvol_set *degraded_set)
				    lvol->unique_id, rc);
			lvol->degraded_set = degraded_set;
			TAILQ_INSERT_TAIL(&degraded_set->lvols, lvol, degraded_link);
		} else {
			spdk_blob_set_esnap_bs_dev(lvol->blob, bs_dev,
						   lvs_esnap_hotplug_done, lvol);
			cb_fn(cb_arg, lvol, rc);
			free(req);
			goto next;
		}

		req->lvol = lvol;
		req->cb_fn = cb_fn;
		req->cb_arg = cb_arg;
		spdk_blob_set_esnap_bs_dev(lvol->blob, bs_dev, lvs_esnap_hotplug_done, req);

next:
		if (lvol == last_missing) {
			/*
			 * Anything after last_missing was added due to some problem encountered
@@ -2024,7 +2052,8 @@ lvs_esnap_degraded_hotplug(struct spdk_lvs_degraded_lvol_set *degraded_set)
 * that the bdev now exists.
 */
bool
spdk_lvs_notify_hotplug(const void *esnap_id, uint32_t id_len)
spdk_lvs_notify_hotplug(const void *esnap_id, uint32_t id_len,
			spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
{
	struct spdk_lvs_degraded_lvol_set *found;
	struct spdk_lvs_degraded_lvol_set find = { 0 };
@@ -2057,7 +2086,7 @@ spdk_lvs_notify_hotplug(const void *esnap_id, uint32_t id_len)
		}

		ret = true;
		lvs_esnap_degraded_hotplug(found);
		lvs_esnap_degraded_hotplug(found, cb_fn, cb_arg);
	}
	pthread_mutex_unlock(&g_lvol_stores_mutex);

+51 −3
Original line number Diff line number Diff line
@@ -24,7 +24,8 @@ static TAILQ_HEAD(, lvol_store_bdev) g_spdk_lvol_pairs = TAILQ_HEAD_INITIALIZER(
static int vbdev_lvs_init(void);
static void vbdev_lvs_fini_start(void);
static int vbdev_lvs_get_ctx_size(void);
static void vbdev_lvs_examine(struct spdk_bdev *bdev);
static void vbdev_lvs_examine_config(struct spdk_bdev *bdev);
static void vbdev_lvs_examine_disk(struct spdk_bdev *bdev);
static bool g_shutdown_started = false;

struct spdk_bdev_module g_lvol_if = {
@@ -32,7 +33,8 @@ struct spdk_bdev_module g_lvol_if = {
	.module_init = vbdev_lvs_init,
	.fini_start = vbdev_lvs_fini_start,
	.async_fini_start = true,
	.examine_disk = vbdev_lvs_examine,
	.examine_config = vbdev_lvs_examine_config,
	.examine_disk = vbdev_lvs_examine_disk,
	.get_ctx_size = vbdev_lvs_get_ctx_size,

};
@@ -1458,6 +1460,52 @@ end:
	}
}

/* Walks a tree of clones that are no longer degraded to create bdevs. */
static int
create_esnap_clone_lvol_disks(void *ctx, struct spdk_lvol *lvol)
{
	struct spdk_bdev *bdev = ctx;
	int rc;

	rc = _create_lvol_disk(lvol, false);
	if (rc != 0) {
		SPDK_ERRLOG("lvol %s: failed to create bdev after esnap hotplug of %s: %d\n",
			    lvol->unique_id, spdk_bdev_get_name(bdev), rc);
		/* Do not prevent creation of other clones in case of one failure. */
		return 0;
	}

	return spdk_lvol_iter_immediate_clones(lvol, create_esnap_clone_lvol_disks, ctx);
}

static void
vbdev_lvs_hotplug(void *ctx, struct spdk_lvol *lvol, int lvolerrno)
{
	struct spdk_bdev *esnap_clone_bdev = ctx;

	if (lvolerrno != 0) {
		SPDK_ERRLOG("lvol %s: during examine of bdev %s: not creating clone bdev due to "
			    "error %d\n", lvol->unique_id, spdk_bdev_get_name(esnap_clone_bdev),
			    lvolerrno);
		return;
	}
	create_esnap_clone_lvol_disks(esnap_clone_bdev, lvol);
}

static void
vbdev_lvs_examine_config(struct spdk_bdev *bdev)
{
	char uuid_str[SPDK_UUID_STRING_LEN];

	spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &bdev->uuid);

	if (spdk_lvs_notify_hotplug(uuid_str, sizeof(uuid_str), vbdev_lvs_hotplug, bdev)) {
		SPDK_INFOLOG(vbdev_lvol, "bdev %s: claimed by one ore more esnap clones\n",
			     uuid_str);
	}
	spdk_bdev_module_examine_done(&g_lvol_if);
}

static void
_vbdev_lvs_examine_cb(void *arg, struct spdk_lvol_store *lvol_store, int lvserrno)
{
@@ -1572,7 +1620,7 @@ vbdev_lvs_load(struct spdk_bs_dev *bs_dev, spdk_lvs_op_with_handle_complete cb_f
}

static void
vbdev_lvs_examine(struct spdk_bdev *bdev)
vbdev_lvs_examine_disk(struct spdk_bdev *bdev)
{
	struct spdk_lvs_req *req;

+6 −1
Original line number Diff line number Diff line
@@ -5,7 +5,12 @@
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk

DIRS-y = esnap
DIRS-y =

ifeq ($(OS),Linux)
# Tests in this directory mostly depend upon aio bdevs, which are not widely supported.
DIRS-y += esnap
endif

.PHONY: all clean $(DIRS-y)

+7 −1
Original line number Diff line number Diff line
@@ -2,9 +2,15 @@
#  Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.

SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk

TEST_FILE = esnap.c

SPDK_LIB_LIST = accel bdev blob blob_bdev dma init lvol notify
SPDK_LIB_LIST = accel bdev blob blob_bdev dma init notify

ifeq ($(OS),Linux)
SPDK_LIB_LIST += bdev_aio
endif

include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk
include $(SPDK_ROOT_DIR)/mk/spdk.modules.mk
Loading