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

lib/ftl: Add FTL layout region tracker



The FTL layout region tracker enables the dynamic creation, removal,
search and tracking of FTL layout regions.
The tracking is done separately for each bdev, i.e. nvc and base.

This change is a prerequisite for the FTL MD major updates.

Change-Id: I0cc7eddd864a8acd6d5871c0417b92cd5a224e32
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/+/19595


Community-CI: Mellanox Build Bot
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Reviewed-by: default avatarArtur Paszkiewicz <artur.paszkiewicz@intel.com>
Reviewed-by: default avatarBen Walker <ben@nvidia.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent fa1fc76c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ C_SRCS += mngt/ftl_mngt_md.c mngt/ftl_mngt_misc.c mngt/ftl_mngt_ioch.c mngt/ftl_
C_SRCS += mngt/ftl_mngt_band.c mngt/ftl_mngt_self_test.c mngt/ftl_mngt_p2l.c
C_SRCS += mngt/ftl_mngt_recovery.c mngt/ftl_mngt_upgrade.c
C_SRCS += utils/ftl_conf.c utils/ftl_md.c utils/ftl_mempool.c utils/ftl_bitmap.c utils/ftl_property.c
C_SRCS += utils/ftl_layout_tracker_bdev.c
C_SRCS += upgrade/ftl_layout_upgrade.c upgrade/ftl_sb_upgrade.c upgrade/ftl_p2l_upgrade.c
C_SRCS += upgrade/ftl_band_upgrade.c upgrade/ftl_chunk_upgrade.c
C_SRCS += upgrade/ftl_sb_v3.c
+16 −20
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#include "ftl_base_dev.h"
#include "ftl_core.h"
#include "ftl_layout.h"
#include "utils/ftl_layout_tracker_bdev.h"

static bool
is_bdev_compatible(struct spdk_ftl_dev *dev, struct spdk_bdev *bdev)
@@ -18,36 +19,36 @@ md_region_create(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type,
{
	struct ftl_layout *layout = &dev->layout;
	struct ftl_layout_region *region;
	uint64_t reg_free_offs = 0, reg_current_end, reg_offs, data_base_alignment;
	const char *md_region_name;
	uint64_t data_base_alignment, reg_blks;
	const struct ftl_layout_tracker_bdev_region_props *reg_props;

	assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX);
	md_region_name = ftl_md_region_name(reg_type);

	/* As new MD regions are added one after another, find where all existing regions end on the device */
	region = layout->region;
	for (int reg_idx = 0; reg_idx < FTL_LAYOUT_REGION_TYPE_MAX; reg_idx++, region++) {
		if (region->bdev_desc == dev->base_bdev_desc) {
			reg_current_end = region->current.offset + region->current.blocks;
			reg_free_offs = spdk_max(reg_free_offs, reg_current_end);
		}
	}


	data_base_alignment = 8 * ftl_bitmap_buffer_alignment;
	/* Allocating a ftl_bitmap requires a 8B input buffer alignment, since we're reusing the global valid map md buffer
	 * this means that each band starting address needs to be aligned too - each device sector takes 1b in the valid map,
	 * so 64 sectors (8*8) is the needed alignment
	 */
	reg_offs = SPDK_ALIGN_CEIL(reg_free_offs, data_base_alignment);
	data_base_alignment = 8 * ftl_bitmap_buffer_alignment;
	reg_blks = ftl_md_region_blocks(dev, entry_count * entry_size);
	reg_props = ftl_layout_tracker_bdev_add_region(dev->base_layout_tracker, reg_type, reg_version,
			reg_blks, data_base_alignment);
	if (!reg_props) {
		return NULL;
	}
	assert(reg_props->type == reg_type);
	assert(reg_props->ver == reg_version);
	assert(reg_props->blk_sz == reg_blks);
	assert(reg_props->blk_offs + reg_blks <= dev->layout.base.total_blocks);

	region = &layout->region[reg_type];
	region->type = reg_type;
	region->mirror_type = FTL_LAYOUT_REGION_TYPE_INVALID;
	region->name = md_region_name;
	region->current.version = region->prev.version = reg_version;
	region->current.offset = reg_offs;
	region->current.blocks = ftl_md_region_blocks(dev, entry_count * entry_size);
	region->current.offset = reg_props->blk_offs;
	region->current.blocks = reg_blks;
	region->entry_size = entry_size / FTL_BLOCK_SIZE;
	region->num_entries = entry_count;

@@ -55,11 +56,6 @@ md_region_create(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type,
	region->ioch = dev->base_ioch;
	region->vss_blksz = 0;

	reg_offs += region->current.blocks;
	if (reg_offs > layout->base.total_blocks) {
		return NULL;
	}

	return region;
}

+8 −0
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@
extern void *g_ftl_write_buf;
extern void *g_ftl_read_buf;

struct ftl_layout_tracker_bdev;

struct spdk_ftl_dev {
	/* Configuration */
	struct spdk_ftl_conf		conf;
@@ -191,6 +193,12 @@ struct spdk_ftl_dev {
		TAILQ_HEAD(, ftl_p2l_ckpt)	inuse;
	} p2l_ckpt;

	/* MD layout region tracker for nvc device */
	struct ftl_layout_tracker_bdev *nvc_layout_tracker;

	/* MD layout region tracker for a base devics */
	struct ftl_layout_tracker_bdev *base_layout_tracker;

	/* FTL properties which can be configured by user */
	struct ftl_properties			*properties;
};
+23 −6
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include "ftl_nv_cache.h"
#include "ftl_sb.h"
#include "nvc/ftl_nvc_dev.h"
#include "utils/ftl_layout_tracker_bdev.h"

#define FTL_NV_CACHE_CHUNK_DATA_SIZE(blocks) ((uint64_t)blocks * FTL_BLOCK_SIZE)
#define FTL_NV_CACHE_CHUNK_SIZE(blocks) \
@@ -152,17 +153,34 @@ get_num_user_lbas(struct spdk_ftl_dev *dev)
	return blocks;
}

static uint64_t
layout_blocks_left(struct spdk_ftl_dev *dev, struct ftl_layout_tracker_bdev *layout_tracker)
{
	uint64_t max_reg_size = 0;
	const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;

	while (true) {
		ftl_layout_tracker_bdev_find_next_region(layout_tracker, FTL_LAYOUT_REGION_TYPE_FREE,
				&reg_search_ctx);
		if (!reg_search_ctx) {
			break;
		}
		max_reg_size = spdk_max(max_reg_size, reg_search_ctx->blk_sz);
	}
	return max_reg_size;
}

static int
setup_layout_nvc(struct spdk_ftl_dev *dev)
{
	int region_type;
	uint64_t left, offset = 0, l2p_blocks;
	uint64_t left, l2p_blocks;
	struct ftl_layout *layout = &dev->layout;
	const struct ftl_md_layout_ops *md_ops = &dev->nv_cache.nvc_desc->ops.md_layout_ops;

	/* Initialize L2P region */
	if (!md_ops->region_create(dev, FTL_LAYOUT_REGION_TYPE_L2P, 0, layout->l2p.addr_size,
				   dev->num_lbas)) {
	l2p_blocks = ftl_md_region_blocks(dev, layout->l2p.addr_size * dev->num_lbas);
	if (!md_ops->region_create(dev, FTL_LAYOUT_REGION_TYPE_L2P, 0, FTL_BLOCK_SIZE, l2p_blocks)) {
		goto error;
	}

@@ -209,9 +227,8 @@ setup_layout_nvc(struct spdk_ftl_dev *dev)
	/*
	 * Initialize NV Cache metadata
	 */
	offset = layout->region[FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR].current.offset +
		 layout->region[FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR].current.blocks;
	left = layout->nvc.total_blocks - offset;
	left = layout_blocks_left(dev, dev->nvc_layout_tracker);

	layout->nvc.chunk_data_blocks =
		FTL_NV_CACHE_CHUNK_DATA_SIZE(ftl_get_num_blocks_in_band(dev)) / FTL_BLOCK_SIZE;
	layout->nvc.chunk_meta_size = FTL_NV_CACHE_CHUNK_MD_SIZE;
+1 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ enum ftl_layout_region_type {
#define FTL_LAYOUT_REGION_LAST_BASE FTL_LAYOUT_REGION_TYPE_VALID_MAP
#define FTL_LAYOUT_REGION_TYPE_FREE_BASE (UINT32_MAX - 2)
#define FTL_LAYOUT_REGION_TYPE_FREE_NVC (UINT32_MAX - 1)
#define FTL_LAYOUT_REGION_TYPE_FREE (UINT32_MAX - 1)
#define FTL_LAYOUT_REGION_TYPE_INVALID (UINT32_MAX)

struct ftl_layout_region_descriptor {
Loading