diff --git a/lib/ftl/ftl_l2p_cache.c b/lib/ftl/ftl_l2p_cache.c index 5bf509db3..6e65f21f1 100644 --- a/lib/ftl/ftl_l2p_cache.c +++ b/lib/ftl/ftl_l2p_cache.c @@ -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) {