FTL: Add l2p cache get/set logic

This commit also introduces ranking pages, based on usage for determining the least used
page to be evicted.

Signed-off-by: Kozlowski Mateusz <mateusz.kozlowski@intel.com>
Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
Change-Id: Iaf3812177b61376bb38aa209e4ba8576d784ffb5
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13354
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Kozlowski Mateusz 2022-06-01 15:26:57 +02:00 committed by Ben Walker
parent e7e5bc07b2
commit db65602a39

View File

@ -44,7 +44,7 @@ struct ftl_l2p_page {
enum ftl_l2p_page_state state;
uint64_t pin_ref_cnt;
struct ftl_l2p_cache_page_io_ctx ctx;
bool on_rank_list;
bool on_lru_list;
void *page_buffer;
ftl_df_obj_id obj_id;
};
@ -149,6 +149,52 @@ ftl_l2p_cache_get_page_all_size(void)
return sizeof(struct ftl_l2p_page) + ftl_l2p_cache_get_l1_page_size();
}
static void
ftl_l2p_cache_lru_remove_page(struct ftl_l2p_cache *cache, struct ftl_l2p_page *page)
{
assert(page);
assert(page->on_lru_list);
TAILQ_REMOVE(&cache->lru_list, page, list_entry);
page->on_lru_list = false;
}
static void
ftl_l2p_cache_lru_add_page(struct ftl_l2p_cache *cache, struct ftl_l2p_page *page)
{
assert(page);
assert(!page->on_lru_list);
TAILQ_INSERT_HEAD(&cache->lru_list, page, list_entry);
page->on_lru_list = true;
}
static void
ftl_l2p_cache_lru_promote_page(struct ftl_l2p_cache *cache, struct ftl_l2p_page *page)
{
if (!page->on_lru_list) {
return;
}
ftl_l2p_cache_lru_remove_page(cache, page);
ftl_l2p_cache_lru_add_page(cache, page);
}
static inline ftl_addr
ftl_l2p_cache_get_addr(struct spdk_ftl_dev *dev,
struct ftl_l2p_cache *cache, struct ftl_l2p_page *page, uint64_t lba)
{
return ftl_addr_load(dev, page->page_buffer, lba % cache->lbas_in_page);
}
static inline void
ftl_l2p_cache_set_addr(struct spdk_ftl_dev *dev, struct ftl_l2p_cache *cache,
struct ftl_l2p_page *page, uint64_t lba, ftl_addr addr)
{
ftl_addr_store(dev, page->page_buffer, lba % cache->lbas_in_page, addr);
}
static void *
_ftl_l2p_cache_init(struct spdk_ftl_dev *dev, size_t addr_size, uint64_t l2p_size)
{
@ -181,6 +227,19 @@ fail_l2_md:
return NULL;
}
static struct ftl_l2p_page *
get_l2p_page_by_df_id(struct ftl_l2p_cache *cache, size_t page_no)
{
struct ftl_l2p_l1_map_entry *me = cache->l2_mapping;
ftl_df_obj_id obj_id = me[page_no].page_obj_id;
if (obj_id != FTL_DF_OBJ_ID_INVALID) {
return ftl_mempool_get_df_ptr(cache->l2_ctx_pool, obj_id);
}
return NULL;
}
int
ftl_l2p_cache_init(struct spdk_ftl_dev *dev)
{
@ -350,6 +409,52 @@ ftl_l2p_cache_halt(struct spdk_ftl_dev *dev)
}
}
static inline struct ftl_l2p_page *
get_page(struct ftl_l2p_cache *cache, uint64_t lba)
{
return get_l2p_page_by_df_id(cache, lba / cache->lbas_in_page);
}
static inline bool
ftl_l2p_cache_running(struct ftl_l2p_cache *cache)
{
return cache->state == L2P_CACHE_RUNNING;
}
ftl_addr
ftl_l2p_cache_get(struct spdk_ftl_dev *dev, uint64_t lba)
{
assert(dev->num_lbas > lba);
struct ftl_l2p_cache *cache = (struct ftl_l2p_cache *)dev->l2p;
struct ftl_l2p_page *page = get_page(cache, lba);
ftl_addr addr;
ftl_bug(!page);
assert(ftl_l2p_cache_running(cache));
assert(page->pin_ref_cnt);
ftl_l2p_cache_lru_promote_page(cache, page);
addr = ftl_l2p_cache_get_addr(dev, cache, page, lba);
return addr;
}
void
ftl_l2p_cache_set(struct spdk_ftl_dev *dev, uint64_t lba, ftl_addr addr)
{
assert(dev->num_lbas > lba);
struct ftl_l2p_cache *cache = (struct ftl_l2p_cache *)dev->l2p;
struct ftl_l2p_page *page = get_page(cache, lba);
ftl_bug(!page);
assert(ftl_l2p_cache_running(cache));
assert(page->pin_ref_cnt);
page->updates++;
ftl_l2p_cache_lru_promote_page(cache, page);
ftl_l2p_cache_set_addr(dev, cache, page, lba, addr);
}
void
ftl_l2p_cache_process(struct spdk_ftl_dev *dev)
{