Commit 55147295 authored by Kozlowski Mateusz's avatar Kozlowski Mateusz Committed by Ben Walker
Browse files

FTL: Add L2P restore path



Adds initialization code for L2P done after shutdown (both clean and
dirty).

Signed-off-by: default avatarKozlowski Mateusz <mateusz.kozlowski@intel.com>
Signed-off-by: default avatarArtur Paszkiewicz <artur.paszkiewicz@intel.com>
Change-Id: I7a938b298467c96d68f40cb14c3171d1533e1a08
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13361


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent b5e2c59a
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -81,6 +81,12 @@ ftl_l2p_clear(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx)
	FTL_L2P_OP(clear)(dev, cb, cb_ctx);
}

void
ftl_l2p_restore(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx)
{
	FTL_L2P_OP(restore)(dev, cb, cb_ctx);
}

void
ftl_l2p_persist(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx)
{
+101 −0
Original line number Diff line number Diff line
@@ -625,6 +625,107 @@ ftl_l2p_cache_clear(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx)
	ftl_md_clear(md, invalid_addr, NULL);
}

static void
l2p_shm_restore_clean(struct spdk_ftl_dev *dev)
{
	struct ftl_l2p_cache *cache = (struct ftl_l2p_cache *)dev->l2p;
	struct ftl_l2p_l1_map_entry *me = cache->l2_mapping;
	struct ftl_l2p_page *page;
	ftl_df_obj_id obj_id;
	uint64_t page_no;

	for (page_no = 0; page_no < cache->num_pages; ++page_no) {
		obj_id = me[page_no].page_obj_id;
		if (obj_id == FTL_DF_OBJ_ID_INVALID) {
			continue;
		}

		page = ftl_mempool_claim_df(cache->l2_ctx_pool, obj_id);
		assert(page);
		assert(page->obj_id == ftl_mempool_get_df_obj_id(cache->l2_ctx_pool, page));
		assert(page->page_no == page_no);
		assert(page->state != L2P_CACHE_PAGE_INIT);
		assert(page->state != L2P_CACHE_PAGE_CLEARING);
		assert(cache->l2_pgs_avail > 0);
		cache->l2_pgs_avail--;

		page->page_buffer = (char *)ftl_md_get_buffer(cache->l1_md) + ftl_mempool_get_df_obj_index(
					    cache->l2_ctx_pool, page) * FTL_BLOCK_SIZE;

		TAILQ_INIT(&page->ppe_list);

		page->pin_ref_cnt = 0;
		page->on_lru_list = 0;
		memset(&page->ctx, 0, sizeof(page->ctx));

		ftl_l2p_cache_lru_add_page(cache, page);
	}

	ftl_mempool_initialize_ext(cache->l2_ctx_pool);
}

static void
l2p_shm_restore_dirty(struct spdk_ftl_dev *dev)
{
	struct ftl_l2p_cache *cache = (struct ftl_l2p_cache *)dev->l2p;
	struct ftl_l2p_l1_map_entry *me = cache->l2_mapping;
	struct ftl_l2p_page *page;
	ftl_df_obj_id obj_id;
	uint64_t page_no;

	for (page_no = 0; page_no < cache->num_pages; ++page_no) {
		obj_id = me[page_no].page_obj_id;
		if (obj_id == FTL_DF_OBJ_ID_INVALID) {
			continue;
		}

		page = ftl_mempool_claim_df(cache->l2_ctx_pool, obj_id);
		assert(page);
		assert(page->obj_id == ftl_mempool_get_df_obj_id(cache->l2_ctx_pool, page));
		assert(page->page_no == page_no);
		assert(page->state != L2P_CACHE_PAGE_CLEARING);
		assert(cache->l2_pgs_avail > 0);
		cache->l2_pgs_avail--;

		if (page->state == L2P_CACHE_PAGE_INIT) {
			me[page_no].page_obj_id = FTL_DF_OBJ_ID_INVALID;
			cache->l2_pgs_avail++;
			ftl_mempool_release_df(cache->l2_ctx_pool, obj_id);
			continue;
		}

		page->state = L2P_CACHE_PAGE_READY;
		/* Assume page is dirty after crash */
		page->updates = 1;
		page->page_buffer = (char *)ftl_md_get_buffer(cache->l1_md) + ftl_mempool_get_df_obj_index(
					    cache->l2_ctx_pool, page) * FTL_BLOCK_SIZE;

		TAILQ_INIT(&page->ppe_list);

		page->pin_ref_cnt = 0;
		page->on_lru_list = 0;
		memset(&page->ctx, 0, sizeof(page->ctx));

		ftl_l2p_cache_lru_add_page(cache, page);
	}

	ftl_mempool_initialize_ext(cache->l2_ctx_pool);
}

void
ftl_l2p_cache_restore(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx)
{
	if (ftl_fast_startup(dev)) {
		l2p_shm_restore_clean(dev);
	}

	if (ftl_fast_recovery(dev)) {
		l2p_shm_restore_dirty(dev);
	}

	cb(dev, 0, cb_ctx);
}

static void
process_persist(struct ftl_l2p_cache *cache)
{
+1 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ void ftl_l2p_cache_unpin(struct spdk_ftl_dev *dev, uint64_t lba, uint64_t count)
ftl_addr ftl_l2p_cache_get(struct spdk_ftl_dev *dev, uint64_t lba);
void ftl_l2p_cache_set(struct spdk_ftl_dev *dev, uint64_t lba, ftl_addr addr);
void ftl_l2p_cache_clear(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx);
void ftl_l2p_cache_restore(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx);
void ftl_l2p_cache_persist(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx);
void ftl_l2p_cache_process(struct spdk_ftl_dev *dev);
bool ftl_l2p_cache_is_halted(struct spdk_ftl_dev *dev);
+12 −0
Original line number Diff line number Diff line
@@ -80,6 +80,18 @@ ftl_l2p_flat_clear(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx)
	ftl_md_persist(md);
}

void
ftl_l2p_flat_restore(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx)
{
	struct ftl_md *md;

	md = get_l2p_md(dev);
	md->cb = md_cb;
	md->owner.cb_ctx = cb_ctx;
	md->owner.private = cb;
	ftl_md_restore(md);
}

void
ftl_l2p_flat_persist(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx)
{
+1 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ ftl_addr ftl_l2p_flat_get(struct spdk_ftl_dev *dev, uint64_t lba);
void ftl_l2p_flat_set(struct spdk_ftl_dev *dev, uint64_t lba, ftl_addr addr);
void ftl_l2p_flat_unmap(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx);
void ftl_l2p_flat_clear(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx);
void ftl_l2p_flat_restore(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx);
void ftl_l2p_flat_persist(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx);
void ftl_l2p_flat_process(struct spdk_ftl_dev *dev);
bool ftl_l2p_flat_is_halted(struct spdk_ftl_dev *dev);
Loading