Commit 5555d51c authored by Lukasz Lasek's avatar Lukasz Lasek Committed by Tomasz Zawadzki
Browse files

lib/ftl: Add means to create new layout regions



During major upgrade new FTL layout regions are being created with
ftl_layout_upgrade_add_region_placeholder().
Similarly, regions that are no longer in use, are deleted with
ftl_layout_upgrade_drop_region().

Change-Id: Ia03de78f308c05430ca52d26d5f6249bf9a5e72b
Signed-off-by: default avatarLukasz Lasek <lukasz.lasek@solidigm.com>
Signed-off-by: default avatarMariusz Barczak <Mariusz.Barczak@solidigmtechnology.com>
Signed-off-by: default avatarMateusz Kozlowski <mateusz.kozlowski@solidigm.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/19608


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarArtur Paszkiewicz <artur.paszkiewicz@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Reviewed-by: default avatarBen Walker <ben@nvidia.com>
parent 5d89ebb7
Loading
Loading
Loading
Loading
+19 −5
Original line number Diff line number Diff line
@@ -368,6 +368,8 @@ layout_setup_legacy_default_nvc(struct spdk_ftl_dev *dev)
		goto error;
	}

	/* Here is the place to add necessary region placeholders for the creation of new regions */

	return 0;

error:
@@ -639,11 +641,6 @@ ftl_layout_setup(struct spdk_ftl_dev *dev)
		return -EINVAL;
	}

	/* Now drop the unused regions in preparation for the layout upgrade */
	if (ftl_layout_upgrade_drop_regions(dev)) {
		return -EINVAL;
	}

	rc = ftl_superblock_store_blob_area(dev);

	FTL_NOTICELOG(dev, "Base device capacity:         %.2f MiB\n",
@@ -823,3 +820,20 @@ ftl_layout_blob_load(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_sz)

	return 0;
}

void
ftl_layout_upgrade_add_region_placeholder(struct spdk_ftl_dev *dev,
		struct ftl_layout_tracker_bdev *layout_tracker, enum ftl_layout_region_type reg_type)
{
	const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;

	ftl_layout_tracker_bdev_find_next_region(layout_tracker, reg_type, &reg_search_ctx);
	if (reg_search_ctx) {
		return;
	}

	dev->layout.region[reg_type].type = reg_type;
	dev->layout.region[reg_type].current.version = 0;
	dev->layout.region[reg_type].current.offset = UINT64_MAX;
	dev->layout.region[reg_type].current.blocks = 0;
}
+32 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@

struct spdk_ftl_dev;
struct ftl_md;
struct ftl_layout_tracker_bdev;

#define FTL_LAYOUT_REGION_TYPE_P2L_COUNT \
	(FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX - FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN + 1)
@@ -179,6 +180,8 @@ struct ftl_md_layout_ops {
			   uint32_t reg_version, size_t entry_size, size_t entry_count, struct ftl_layout_region *region);
};

uint64_t ftl_layout_upgrade_get_latest_version(enum ftl_layout_region_type reg_type);

/**
 * @brief Get number of blocks required to store an MD region
 *
@@ -266,4 +269,33 @@ int ftl_layout_blob_load(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_s

uint64_t ftl_layout_base_offset(struct spdk_ftl_dev *dev);

/**
 * @brief Adds a new region entry to the layout
 *
 * Any offset and length are not explicitly assigned yet, used to define any new metadata in the layout,
 * before the exact sizes are calculated.
 *
 * @param dev FTL device
 * @param layout_tracker Tracker of the base/nvc bdev
 * @param reg_type type of the layout region
 * @return int 0: add region successful, -1 otherwise
 */
void ftl_layout_upgrade_add_region_placeholder(struct spdk_ftl_dev *dev,
		struct ftl_layout_tracker_bdev *layout_tracker, enum ftl_layout_region_type reg_type);

/**
 * @brief Removes the given metadata region from the layout
 *
 * Used to remove regions that are no longer utilized in FTL
 *
 * @param dev FTL device
 * @param layout_tracker Tracker of the base/nvc bdev
 * @param reg_type type of the layout region
 * @param reg_ver region version to be dropped
 * @return int 0: drop region successful, -1 otherwise
 */
int ftl_layout_upgrade_drop_region(struct spdk_ftl_dev *dev,
				   struct ftl_layout_tracker_bdev *layout_tracker, enum ftl_layout_region_type reg_type,
				   uint32_t reg_ver);

#endif /* FTL_LAYOUT_H */
+11 −13
Original line number Diff line number Diff line
@@ -115,6 +115,13 @@ SPDK_STATIC_ASSERT(sizeof(layout_upgrade_desc) / sizeof(*layout_upgrade_desc) ==
		   "Missing layout upgrade descriptors");
#endif

uint64_t
ftl_layout_upgrade_get_latest_version(enum ftl_layout_region_type reg_type)
{
	assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX);
	return layout_upgrade_desc[reg_type].latest_ver;
}

static int
region_verify(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *ctx)
{
@@ -315,8 +322,9 @@ ftl_layout_upgrade_region_get_latest_version(enum ftl_layout_region_type reg_typ
	return layout_upgrade_desc[reg_type].latest_ver;
}

static int
layout_upgrade_drop_region(struct spdk_ftl_dev *dev, struct ftl_layout_tracker_bdev *layout_tracker,
int
ftl_layout_upgrade_drop_region(struct spdk_ftl_dev *dev,
			       struct ftl_layout_tracker_bdev *layout_tracker,
			       enum ftl_layout_region_type reg_type, uint32_t reg_ver)
{
	const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
@@ -332,13 +340,3 @@ layout_upgrade_drop_region(struct spdk_ftl_dev *dev, struct ftl_layout_tracker_b
	dev->layout.region[reg_type].type = FTL_LAYOUT_REGION_TYPE_INVALID;
	return 0;
}

int
ftl_layout_upgrade_drop_regions(struct spdk_ftl_dev *dev)
{
	if (layout_upgrade_drop_region(dev, dev->nvc_layout_tracker, FTL_LAYOUT_REGION_TYPE_DATA_NVC, 0)) {
		return -1;
	}

	return 0;
}
+0 −8
Original line number Diff line number Diff line
@@ -201,12 +201,4 @@ int ftl_layout_upgrade_init_ctx(struct spdk_ftl_dev *dev, struct ftl_layout_upgr
 */
uint64_t ftl_layout_upgrade_region_get_latest_version(enum ftl_layout_region_type reg_type);

/**
 * @brief Removes all metadata regions from the layout that are no longer utilized in FTL
 *
 * @param dev FTL device
 * @return int 0: drop regions successful, -1 otherwise
 */
int ftl_layout_upgrade_drop_regions(struct spdk_ftl_dev *dev);

#endif /* FTL_LAYOUT_UPGRADE_H */
+42 −25
Original line number Diff line number Diff line
@@ -312,7 +312,8 @@ sb_md_layout_delete_prev_region(struct spdk_ftl_dev *dev, struct ftl_layout_regi
	struct ftl_layout_tracker_bdev *layout_tracker = sb_get_md_layout_tracker(dev, reg);

	rc = ftl_layout_tracker_bdev_rm_region(layout_tracker, reg->type, reg->current.version);
	ftl_bug(rc != 0);
	/* Version 0 indicates a placeholder for creation of a new region */
	ftl_bug(reg->current.version != 0 && rc != 0);
}

static void
@@ -489,21 +490,18 @@ layout_apply_from_sb_blob(struct spdk_ftl_dev *dev, struct ftl_layout_tracker_bd
}

static int
layout_region_verify(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type,
		     uint32_t reg_ver)
layout_region_verify(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type)
{
	struct ftl_layout_region *reg = ftl_layout_region_get(dev, reg_type);

	if (!reg) {
		FTL_ERRLOG(dev, "Region not found in nvc layout blob: reg type 0x%"PRIx32"\n", reg_type);
		return -1;
		return -ENOENT;
	}

	/* Unknown version found in the blob */
	if (reg->current.version > reg_ver) {
	if (reg->current.version > ftl_layout_upgrade_get_latest_version(reg_type)) {
		FTL_ERRLOG(dev, "Unknown region version found in layout blob: reg type 0x%"PRIx32"\n",
			   reg_type);
		return -1;
		return -EINVAL;
	}

	return 0;
@@ -555,7 +553,7 @@ layout_fixup_base(struct spdk_ftl_dev *dev)
	for (reg_descr = nvc_regs; reg_descr->type != FTL_LAYOUT_REGION_TYPE_INVALID; reg_descr++) {
		struct ftl_layout_region *region;

		if (layout_region_verify(dev, reg_descr->type, reg_descr->ver) &&
		if (layout_region_verify(dev, reg_descr->type) &&
		    reg_descr->on_reg_miss && reg_descr->on_reg_miss(dev)) {
			return -1;
		}
@@ -576,38 +574,57 @@ layout_fixup_base(struct spdk_ftl_dev *dev)
static int
layout_fixup_nvc(struct spdk_ftl_dev *dev)
{
	int rc;
	struct ftl_layout_region_descr {
		enum ftl_layout_region_type type;
		uint32_t ver;
		bool deprecated;
		enum ftl_layout_region_type mirror_type;
	};
	struct ftl_layout_region_descr *reg_descr;
	static struct ftl_layout_region_descr nvc_regs[] = {
		{ .type = FTL_LAYOUT_REGION_TYPE_SB, .ver = FTL_SB_VERSION_CURRENT, .mirror_type = FTL_LAYOUT_REGION_TYPE_SB_BASE },
		{ .type = FTL_LAYOUT_REGION_TYPE_L2P, .ver = 0 },
		{ .type = FTL_LAYOUT_REGION_TYPE_BAND_MD, .ver = FTL_BAND_VERSION_CURRENT, .mirror_type = FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR },
		{ .type = FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR, .ver = FTL_BAND_VERSION_CURRENT },
		{ .type = FTL_LAYOUT_REGION_TYPE_TRIM_MD, .ver = 0, .mirror_type = FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR },
		{ .type = FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR, .ver = 0 },
		{ .type = FTL_LAYOUT_REGION_TYPE_NVC_MD, .ver = FTL_NVC_VERSION_CURRENT, .mirror_type = FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR },
		{ .type = FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR, .ver = FTL_NVC_VERSION_CURRENT },
		{ .type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC, .ver = FTL_P2L_VERSION_CURRENT },
		{ .type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC_NEXT, .ver = FTL_P2L_VERSION_CURRENT },
		{ .type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP, .ver = FTL_P2L_VERSION_CURRENT },
		{ .type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP_NEXT, .ver = FTL_P2L_VERSION_CURRENT },
		{ .type = FTL_LAYOUT_REGION_TYPE_INVALID, .ver = 0 },
		{ .type = FTL_LAYOUT_REGION_TYPE_SB, .mirror_type = FTL_LAYOUT_REGION_TYPE_SB_BASE },
		{ .type = FTL_LAYOUT_REGION_TYPE_L2P },
		{ .type = FTL_LAYOUT_REGION_TYPE_BAND_MD, .mirror_type = FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR },
		{ .type = FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR },
		{ .type = FTL_LAYOUT_REGION_TYPE_TRIM_MD, .mirror_type = FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR },
		{ .type = FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR },
		{ .type = FTL_LAYOUT_REGION_TYPE_NVC_MD, .mirror_type = FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR },
		{ .type = FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR },
		{ .type = FTL_LAYOUT_REGION_TYPE_DATA_NVC, .deprecated = true },
		{ .type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC },
		{ .type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC_NEXT },
		{ .type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP },
		{ .type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP_NEXT },
		{ .type = FTL_LAYOUT_REGION_TYPE_INVALID },
	};

	for (reg_descr = nvc_regs; reg_descr->type != FTL_LAYOUT_REGION_TYPE_INVALID; reg_descr++) {
		struct ftl_layout_region *region;

		if (layout_region_verify(dev, reg_descr->type, reg_descr->ver)) {
		rc = layout_region_verify(dev, reg_descr->type);
		if (rc == -ENOENT) {
			if (reg_descr->deprecated) {
				continue;
			}

			ftl_layout_upgrade_add_region_placeholder(dev, dev->nvc_layout_tracker, reg_descr->type);
		} else if (rc) {
			return -1;
		}

		if (reg_descr->deprecated) {
			rc = ftl_layout_upgrade_drop_region(dev, dev->nvc_layout_tracker, reg_descr->type,
							    dev->layout.region[reg_descr->type].current.version);
			if (rc) {
				return rc;
			}
			continue;
		}

		region = &dev->layout.region[reg_descr->type];
		region->type = reg_descr->type;
		region->mirror_type = FTL_LAYOUT_REGION_TYPE_INVALID;
		region->mirror_type = (reg_descr->mirror_type) ? reg_descr->mirror_type :
				      FTL_LAYOUT_REGION_TYPE_INVALID;
		region->name = ftl_md_region_name(reg_descr->type);

		region->bdev_desc = dev->nv_cache.bdev_desc;