xref: /spdk/lib/ftl/ftl_l2p_cache.c (revision ea8f5b27612fa03698a9ce3ad4bd37765d9cdfa5)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (c) Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/stdinc.h"
7 #include "spdk/cpuset.h"
8 #include "spdk/queue.h"
9 #include "spdk/thread.h"
10 #include "spdk/event.h"
11 #include "spdk/ftl.h"
12 #include "spdk/conf.h"
13 #include "spdk/env.h"
14 #include "spdk/util.h"
15 
16 #include "ftl_core.h"
17 #include "ftl_l2p_cache.h"
18 #include "ftl_layout.h"
19 #include "ftl_nv_cache_io.h"
20 #include "mngt/ftl_mngt_steps.h"
21 #include "utils/ftl_defs.h"
22 #include "utils/ftl_addr_utils.h"
23 
24 struct ftl_l2p_cache_page_io_ctx {
25 	struct ftl_l2p_cache *cache;
26 	uint64_t updates;
27 	spdk_bdev_io_completion_cb cb;
28 	struct spdk_bdev_io_wait_entry bdev_io_wait;
29 };
30 
31 enum ftl_l2p_page_state {
32 	L2P_CACHE_PAGE_INIT,		/* Page in memory not initialized from disk page */
33 	L2P_CACHE_PAGE_READY,		/* Page initialized from disk */
34 	L2P_CACHE_PAGE_FLUSHING,	/* Page is being flushed to disk and removed from memory */
35 	L2P_CACHE_PAGE_PERSISTING,	/* Page is being flushed to disk and not removed from memory */
36 	L2P_CACHE_PAGE_CLEARING,	/* Page is being initialized with INVALID addresses */
37 	L2P_CACHE_PAGE_CORRUPTED	/* Page corrupted */
38 };
39 
40 struct ftl_l2p_page {
41 	uint64_t updates; /* Number of times an L2P entry was updated in the page since it was last persisted */
42 	TAILQ_HEAD(, ftl_l2p_page_wait_ctx) ppe_list; /* for deferred pins */
43 	TAILQ_ENTRY(ftl_l2p_page) list_entry;
44 	uint64_t page_no;
45 	enum ftl_l2p_page_state state;
46 	uint64_t pin_ref_cnt;
47 	struct ftl_l2p_cache_page_io_ctx ctx;
48 	bool on_lru_list;
49 	void *page_buffer;
50 	uint64_t ckpt_seq_id;
51 	ftl_df_obj_id obj_id;
52 };
53 
54 struct ftl_l2p_page_set;
55 
56 struct ftl_l2p_page_wait_ctx {
57 	uint16_t	pg_pin_issued;
58 	uint16_t	pg_pin_completed;
59 	struct ftl_l2p_page_set *parent;
60 	uint64_t	pg_no;
61 	TAILQ_ENTRY(ftl_l2p_page_wait_ctx) list_entry;
62 };
63 
64 /* A L2P page contains 1024 4B entries (or 512 8B ones for big drives).
65  * Currently internal IO will only pin 1 LBA at a time, so only one entry should be needed.
66  * User IO is split on internal xfer_size boundaries, which is currently set to 1MiB (256 blocks),
67  * so one entry should also be enough.
68  * TODO: We should probably revisit this though, when/if the xfer_size is based on io requirements of the
69  * bottom device (e.g. RAID5F), since then big IOs (especially unaligned ones) could potentially break this.
70  */
71 #define L2P_MAX_PAGES_TO_PIN 4
72 struct ftl_l2p_page_set {
73 	uint16_t to_pin_cnt;
74 	uint16_t pinned_cnt;
75 	uint16_t pin_fault_cnt;
76 	uint8_t locked;
77 	uint8_t deferred;
78 	struct ftl_l2p_pin_ctx *pin_ctx;
79 	TAILQ_ENTRY(ftl_l2p_page_set) list_entry;
80 	struct ftl_l2p_page_wait_ctx entry[L2P_MAX_PAGES_TO_PIN];
81 };
82 
83 struct ftl_l2p_l1_map_entry {
84 	ftl_df_obj_id page_obj_id;
85 };
86 
87 enum ftl_l2p_cache_state {
88 	L2P_CACHE_INIT,
89 	L2P_CACHE_RUNNING,
90 	L2P_CACHE_IN_SHUTDOWN,
91 	L2P_CACHE_SHUTDOWN_DONE,
92 };
93 
94 struct ftl_l2p_cache_process_ctx {
95 	int status;
96 	ftl_l2p_cb cb;
97 	void *cb_ctx;
98 	uint64_t idx;
99 	uint64_t qd;
100 };
101 
102 struct ftl_l2p_cache {
103 	struct spdk_ftl_dev *dev;
104 	struct ftl_l2p_l1_map_entry *l2_mapping;
105 	struct ftl_md *l2_md;
106 	struct ftl_md *l2_ctx_md;
107 	struct ftl_mempool *l2_ctx_pool;
108 	struct ftl_md *l1_md;
109 
110 	TAILQ_HEAD(l2p_lru_list, ftl_l2p_page) lru_list;
111 	/* TODO: A lot of / and % operations are done on this value, consider adding a shift based field and calculactions instead */
112 	uint64_t lbas_in_page;
113 	uint64_t num_pages;		/* num pages to hold the entire L2P */
114 
115 	uint64_t ios_in_flight;		/* Currently in flight IOs, to determine l2p shutdown readiness */
116 	enum ftl_l2p_cache_state state;
117 	uint32_t l2_pgs_avail;
118 	uint32_t l2_pgs_evicting;
119 	uint32_t l2_pgs_resident_max;
120 	uint32_t evict_keep;
121 	struct ftl_mempool *page_sets_pool;
122 	TAILQ_HEAD(, ftl_l2p_page_set) deferred_page_set_list; /* for deferred page sets */
123 
124 	/* This is a context for a management process */
125 	struct ftl_l2p_cache_process_ctx mctx;
126 
127 	/* MD layout cache: Offset on a device in FTL_BLOCK_SIZE unit */
128 	uint64_t cache_layout_offset;
129 
130 	/* MD layout cache: Device of region */
131 	struct spdk_bdev_desc *cache_layout_bdev_desc;
132 
133 	/* MD layout cache: IO channel of region */
134 	struct spdk_io_channel *cache_layout_ioch;
135 };
136 
137 typedef void (*ftl_l2p_cache_clear_cb)(struct ftl_l2p_cache *cache, int status, void *ctx_page);
138 typedef void (*ftl_l2p_cache_persist_cb)(struct ftl_l2p_cache *cache, int status, void *ctx_page);
139 typedef void (*ftl_l2p_cache_sync_cb)(struct spdk_ftl_dev *dev, int status, void *page,
140 				      void *user_ctx);
141 
142 static bool page_set_is_done(struct ftl_l2p_page_set *page_set);
143 static void page_set_end(struct spdk_ftl_dev *dev, struct ftl_l2p_cache *cache,
144 			 struct ftl_l2p_page_set *page_set);
145 static void page_out_io_retry(void *arg);
146 static void page_in_io_retry(void *arg);
147 
148 static inline void
149 ftl_l2p_page_queue_wait_ctx(struct ftl_l2p_page *page,
150 			    struct ftl_l2p_page_wait_ctx *ppe)
151 {
152 	TAILQ_INSERT_TAIL(&page->ppe_list, ppe, list_entry);
153 }
154 
155 static inline uint64_t
156 ftl_l2p_cache_get_l1_page_size(void)
157 {
158 	return 1UL << 12;
159 }
160 
161 static inline size_t
162 ftl_l2p_cache_get_page_all_size(void)
163 {
164 	return sizeof(struct ftl_l2p_page) + ftl_l2p_cache_get_l1_page_size();
165 }
166 
167 static void
168 ftl_l2p_cache_lru_remove_page(struct ftl_l2p_cache *cache, struct ftl_l2p_page *page)
169 {
170 	assert(page);
171 	assert(page->on_lru_list);
172 
173 	TAILQ_REMOVE(&cache->lru_list, page, list_entry);
174 	page->on_lru_list = false;
175 }
176 
177 static void
178 ftl_l2p_cache_lru_add_page(struct ftl_l2p_cache *cache, struct ftl_l2p_page *page)
179 {
180 	assert(page);
181 	assert(!page->on_lru_list);
182 
183 	TAILQ_INSERT_HEAD(&cache->lru_list, page, list_entry);
184 
185 	page->on_lru_list = true;
186 }
187 
188 static void
189 ftl_l2p_cache_lru_promote_page(struct ftl_l2p_cache *cache, struct ftl_l2p_page *page)
190 {
191 	if (!page->on_lru_list) {
192 		return;
193 	}
194 
195 	ftl_l2p_cache_lru_remove_page(cache, page);
196 	ftl_l2p_cache_lru_add_page(cache, page);
197 }
198 
199 static inline void
200 ftl_l2p_cache_page_insert(struct ftl_l2p_cache *cache, struct ftl_l2p_page *page)
201 {
202 	struct ftl_l2p_l1_map_entry *me = cache->l2_mapping;
203 	assert(me);
204 
205 	assert(me[page->page_no].page_obj_id == FTL_DF_OBJ_ID_INVALID);
206 	me[page->page_no].page_obj_id = page->obj_id;
207 }
208 
209 static void
210 ftl_l2p_cache_page_remove(struct ftl_l2p_cache *cache, struct ftl_l2p_page *page)
211 {
212 	struct ftl_l2p_l1_map_entry *me = cache->l2_mapping;
213 	assert(me);
214 	assert(me[page->page_no].page_obj_id != FTL_DF_OBJ_ID_INVALID);
215 	assert(TAILQ_EMPTY(&page->ppe_list));
216 
217 	me[page->page_no].page_obj_id = FTL_DF_OBJ_ID_INVALID;
218 	cache->l2_pgs_avail++;
219 	ftl_mempool_put(cache->l2_ctx_pool, page);
220 }
221 
222 static inline struct ftl_l2p_page *
223 ftl_l2p_cache_get_coldest_page(struct ftl_l2p_cache *cache)
224 {
225 	return TAILQ_LAST(&cache->lru_list, l2p_lru_list);
226 }
227 
228 static inline struct ftl_l2p_page *
229 ftl_l2p_cache_get_hotter_page(struct ftl_l2p_page *page)
230 {
231 	return TAILQ_PREV(page, l2p_lru_list, list_entry);
232 }
233 
234 static inline uint64_t
235 ftl_l2p_cache_page_get_bdev_offset(struct ftl_l2p_cache *cache,
236 				   struct ftl_l2p_page *page)
237 {
238 	return cache->cache_layout_offset + page->page_no;
239 }
240 
241 static inline struct spdk_bdev_desc *
242 ftl_l2p_cache_get_bdev_desc(struct ftl_l2p_cache *cache)
243 {
244 	return cache->cache_layout_bdev_desc;
245 }
246 
247 static inline struct spdk_io_channel *
248 ftl_l2p_cache_get_bdev_iochannel(struct ftl_l2p_cache *cache)
249 {
250 	return cache->cache_layout_ioch;
251 }
252 
253 static struct ftl_l2p_page *
254 ftl_l2p_cache_page_alloc(struct ftl_l2p_cache *cache, size_t page_no)
255 {
256 	struct ftl_l2p_page *page = ftl_mempool_get(cache->l2_ctx_pool);
257 	ftl_bug(!page);
258 
259 	cache->l2_pgs_avail--;
260 
261 	memset(page, 0, sizeof(*page));
262 
263 	page->obj_id = ftl_mempool_get_df_obj_id(cache->l2_ctx_pool, page);
264 
265 	page->page_buffer = (char *)ftl_md_get_buffer(cache->l1_md) + ftl_mempool_get_df_obj_index(
266 				    cache->l2_ctx_pool, page) * FTL_BLOCK_SIZE;
267 
268 	TAILQ_INIT(&page->ppe_list);
269 
270 	page->page_no = page_no;
271 	page->state = L2P_CACHE_PAGE_INIT;
272 
273 	return page;
274 }
275 
276 static inline bool
277 ftl_l2p_cache_page_can_remove(struct ftl_l2p_page *page)
278 {
279 	return (!page->updates &&
280 		page->state != L2P_CACHE_PAGE_INIT &&
281 		!page->pin_ref_cnt);
282 }
283 
284 static inline ftl_addr
285 ftl_l2p_cache_get_addr(struct spdk_ftl_dev *dev,
286 		       struct ftl_l2p_cache *cache, struct ftl_l2p_page *page, uint64_t lba)
287 {
288 	return ftl_addr_load(dev, page->page_buffer, lba % cache->lbas_in_page);
289 }
290 
291 static inline void
292 ftl_l2p_cache_set_addr(struct spdk_ftl_dev *dev, struct ftl_l2p_cache *cache,
293 		       struct ftl_l2p_page *page, uint64_t lba, ftl_addr addr)
294 {
295 	ftl_addr_store(dev, page->page_buffer, lba % cache->lbas_in_page, addr);
296 }
297 
298 static inline void
299 ftl_l2p_cache_page_pin(struct ftl_l2p_cache *cache,
300 		       struct ftl_l2p_page *page)
301 {
302 	page->pin_ref_cnt++;
303 	/* Pinned pages can't be evicted (since L2P sets/gets will be executed on it), so remove them from LRU */
304 	if (page->on_lru_list) {
305 		ftl_l2p_cache_lru_remove_page(cache, page);
306 	}
307 }
308 
309 static inline void
310 ftl_l2p_cache_page_unpin(struct ftl_l2p_cache *cache, struct ftl_l2p_page *page)
311 {
312 	page->pin_ref_cnt--;
313 	if (!page->pin_ref_cnt && !page->on_lru_list && page->state != L2P_CACHE_PAGE_FLUSHING) {
314 		/* L2P_CACHE_PAGE_FLUSHING: the page is currently being evicted.
315 		 * In such a case, the page can't be returned to the rank list, because
316 		 * the ongoing eviction will remove it if no pg updates had happened.
317 		 * Moreover, the page could make it to the top of the rank list and be
318 		 * selected for another eviction, while the ongoing one did not finish yet.
319 		 *
320 		 * Depending on the page updates tracker, the page will be evicted
321 		 * or returned to the rank list in context of the eviction completion
322 		 * cb - see page_out_io_complete().
323 		 */
324 		ftl_l2p_cache_lru_add_page(cache, page);
325 	}
326 }
327 
328 static inline bool
329 ftl_l2p_cache_page_can_evict(struct ftl_l2p_page *page)
330 {
331 	return (page->state == L2P_CACHE_PAGE_FLUSHING ||
332 		page->state == L2P_CACHE_PAGE_PERSISTING ||
333 		page->state == L2P_CACHE_PAGE_INIT ||
334 		page->pin_ref_cnt) ? false : true;
335 }
336 
337 static bool
338 ftl_l2p_cache_evict_continue(struct ftl_l2p_cache *cache)
339 {
340 	return cache->l2_pgs_avail + cache->l2_pgs_evicting < cache->evict_keep;
341 }
342 
343 static void *
344 _ftl_l2p_cache_init(struct spdk_ftl_dev *dev, size_t addr_size, uint64_t l2p_size)
345 {
346 	struct ftl_l2p_cache *cache;
347 	uint64_t l2_pages = spdk_divide_round_up(l2p_size, ftl_l2p_cache_get_l1_page_size());
348 	size_t l2_size = l2_pages * sizeof(struct ftl_l2p_l1_map_entry);
349 
350 	cache = calloc(1, sizeof(struct ftl_l2p_cache));
351 	if (cache == NULL) {
352 		return NULL;
353 	}
354 	cache->dev = dev;
355 
356 	cache->l2_md = ftl_md_create(dev,
357 				     spdk_divide_round_up(l2_size, FTL_BLOCK_SIZE), 0,
358 				     FTL_L2P_CACHE_MD_NAME_L2,
359 				     ftl_md_create_shm_flags(dev), NULL);
360 
361 	if (cache->l2_md == NULL) {
362 		goto fail_l2_md;
363 	}
364 	cache->l2_mapping = ftl_md_get_buffer(cache->l2_md);
365 
366 	cache->lbas_in_page = dev->layout.l2p.lbas_in_page;
367 	cache->num_pages = l2_pages;
368 
369 	return cache;
370 fail_l2_md:
371 	free(cache);
372 	return NULL;
373 }
374 
375 static struct ftl_l2p_page *
376 get_l2p_page_by_df_id(struct ftl_l2p_cache *cache, size_t page_no)
377 {
378 	struct ftl_l2p_l1_map_entry *me = cache->l2_mapping;
379 	ftl_df_obj_id obj_id = me[page_no].page_obj_id;
380 
381 	if (obj_id != FTL_DF_OBJ_ID_INVALID) {
382 		return ftl_mempool_get_df_ptr(cache->l2_ctx_pool, obj_id);
383 	}
384 
385 	return NULL;
386 }
387 
388 int
389 ftl_l2p_cache_init(struct spdk_ftl_dev *dev)
390 {
391 	uint64_t l2p_size = dev->num_lbas * dev->layout.l2p.addr_size;
392 	struct ftl_l2p_cache *cache;
393 	const struct ftl_layout_region *reg;
394 	void *l2p = _ftl_l2p_cache_init(dev, dev->layout.l2p.addr_size, l2p_size);
395 	size_t page_sets_pool_size = 1 << 15;
396 	size_t max_resident_size, max_resident_pgs;
397 
398 	if (!l2p) {
399 		return -1;
400 	}
401 	dev->l2p = l2p;
402 
403 	cache = (struct ftl_l2p_cache *)dev->l2p;
404 	cache->page_sets_pool = ftl_mempool_create(page_sets_pool_size,
405 				sizeof(struct ftl_l2p_page_set),
406 				64, SPDK_ENV_SOCKET_ID_ANY);
407 	if (!cache->page_sets_pool) {
408 		return -1;
409 	}
410 
411 	max_resident_size = dev->conf.l2p_dram_limit << 20;
412 	max_resident_pgs = max_resident_size / ftl_l2p_cache_get_page_all_size();
413 
414 	if (max_resident_pgs > cache->num_pages) {
415 		SPDK_NOTICELOG("l2p memory limit higher than entire L2P size\n");
416 		max_resident_pgs = cache->num_pages;
417 	}
418 
419 	/* Round down max res pgs to the nearest # of l2/l1 pgs */
420 	max_resident_size = max_resident_pgs * ftl_l2p_cache_get_page_all_size();
421 	SPDK_NOTICELOG("l2p maximum resident size is: %"PRIu64" (of %"PRIu64") MiB\n",
422 		       max_resident_size >> 20, dev->conf.l2p_dram_limit);
423 
424 	TAILQ_INIT(&cache->deferred_page_set_list);
425 	TAILQ_INIT(&cache->lru_list);
426 
427 	cache->l2_ctx_md = ftl_md_create(dev,
428 					 spdk_divide_round_up(max_resident_pgs * SPDK_ALIGN_CEIL(sizeof(struct ftl_l2p_page), 64),
429 							 FTL_BLOCK_SIZE), 0, FTL_L2P_CACHE_MD_NAME_L2_CTX, ftl_md_create_shm_flags(dev), NULL);
430 
431 	if (cache->l2_ctx_md == NULL) {
432 		return -1;
433 	}
434 
435 	cache->l2_pgs_resident_max = max_resident_pgs;
436 	cache->l2_pgs_avail = max_resident_pgs;
437 	cache->l2_pgs_evicting = 0;
438 	cache->l2_ctx_pool = ftl_mempool_create_ext(ftl_md_get_buffer(cache->l2_ctx_md),
439 			     max_resident_pgs, sizeof(struct ftl_l2p_page), 64);
440 
441 	if (cache->l2_ctx_pool == NULL) {
442 		return -1;
443 	}
444 
445 #define FTL_L2P_CACHE_PAGE_AVAIL_MAX            16UL << 10
446 #define FTL_L2P_CACHE_PAGE_AVAIL_RATIO          5UL
447 	cache->evict_keep = spdk_divide_round_up(cache->num_pages * FTL_L2P_CACHE_PAGE_AVAIL_RATIO, 100);
448 	cache->evict_keep = spdk_min(FTL_L2P_CACHE_PAGE_AVAIL_MAX, cache->evict_keep);
449 
450 	if (!ftl_fast_startup(dev) && !ftl_fast_recovery(dev)) {
451 		memset(cache->l2_mapping, (int)FTL_DF_OBJ_ID_INVALID, ftl_md_get_buffer_size(cache->l2_md));
452 		ftl_mempool_initialize_ext(cache->l2_ctx_pool);
453 	}
454 
455 	cache->l1_md = ftl_md_create(dev,
456 				     max_resident_pgs, 0,
457 				     FTL_L2P_CACHE_MD_NAME_L1,
458 				     ftl_md_create_shm_flags(dev), NULL);
459 
460 	if (cache->l1_md == NULL) {
461 		return -1;
462 	}
463 
464 	/* Cache MD layout */
465 	reg = &dev->layout.region[FTL_LAYOUT_REGION_TYPE_L2P];
466 	cache->cache_layout_offset = reg->current.offset;
467 	cache->cache_layout_bdev_desc = reg->bdev_desc;
468 	cache->cache_layout_ioch = reg->ioch;
469 
470 	cache->state = L2P_CACHE_RUNNING;
471 	return 0;
472 }
473 
474 static void
475 ftl_l2p_cache_deinit_l2(struct spdk_ftl_dev *dev, struct ftl_l2p_cache *cache)
476 {
477 	ftl_md_destroy(cache->l2_ctx_md, ftl_md_destroy_shm_flags(dev));
478 	cache->l2_ctx_md = NULL;
479 
480 	ftl_mempool_destroy_ext(cache->l2_ctx_pool);
481 	cache->l2_ctx_pool = NULL;
482 
483 	ftl_md_destroy(cache->l1_md, ftl_md_destroy_shm_flags(dev));
484 	cache->l1_md = NULL;
485 
486 	ftl_mempool_destroy(cache->page_sets_pool);
487 	cache->page_sets_pool = NULL;
488 }
489 
490 static void
491 _ftl_l2p_cache_deinit(struct spdk_ftl_dev *dev)
492 {
493 	struct ftl_l2p_cache *cache = (struct ftl_l2p_cache *)dev->l2p;
494 
495 	ftl_l2p_cache_deinit_l2(dev, cache);
496 	ftl_md_destroy(cache->l2_md, ftl_md_destroy_shm_flags(dev));
497 	free(cache);
498 }
499 
500 void
501 ftl_l2p_cache_deinit(struct spdk_ftl_dev *dev)
502 {
503 	struct ftl_l2p_cache *cache = (struct ftl_l2p_cache *)dev->l2p;
504 
505 	if (!cache) {
506 		return;
507 	}
508 	assert(cache->state == L2P_CACHE_SHUTDOWN_DONE || cache->state == L2P_CACHE_INIT);
509 
510 	_ftl_l2p_cache_deinit(dev);
511 	dev->l2p = 0;
512 }
513 
514 static void
515 process_init_ctx(struct spdk_ftl_dev *dev, struct ftl_l2p_cache *cache,
516 		 ftl_l2p_cb cb, void *cb_ctx)
517 {
518 	struct ftl_l2p_cache_process_ctx *ctx = &cache->mctx;
519 
520 	assert(NULL == ctx->cb_ctx);
521 	assert(0 == cache->l2_pgs_evicting);
522 
523 	memset(ctx, 0, sizeof(*ctx));
524 
525 	ctx->cb = cb;
526 	ctx->cb_ctx = cb_ctx;
527 }
528 
529 static void
530 process_finish(struct ftl_l2p_cache *cache)
531 {
532 	struct ftl_l2p_cache_process_ctx ctx = cache->mctx;
533 
534 	assert(cache->l2_pgs_avail == cache->l2_pgs_resident_max);
535 	assert(0 == ctx.qd);
536 
537 	memset(&cache->mctx, 0, sizeof(cache->mctx));
538 	ctx.cb(cache->dev, ctx.status, ctx.cb_ctx);
539 }
540 
541 static void process_page_out_retry(void *_page);
542 static void process_persist(struct ftl_l2p_cache *cache);
543 
544 static void
545 process_persist_page_out_cb(struct spdk_bdev_io *bdev_io, bool success, void *arg)
546 {
547 	struct ftl_l2p_page *page = arg;
548 	struct ftl_l2p_cache *cache = page->ctx.cache;
549 	struct ftl_l2p_cache_process_ctx *ctx = &cache->mctx;
550 
551 	assert(bdev_io);
552 	spdk_bdev_free_io(bdev_io);
553 
554 	if (!success) {
555 		ctx->status = -EIO;
556 	}
557 
558 	ftl_l2p_cache_page_remove(cache, page);
559 
560 	ctx->qd--;
561 	process_persist(cache);
562 }
563 
564 static void
565 process_page_out(struct ftl_l2p_page *page, spdk_bdev_io_completion_cb cb)
566 {
567 	struct spdk_bdev *bdev;
568 	struct spdk_bdev_io_wait_entry *bdev_io_wait;
569 	struct ftl_l2p_cache *cache = page->ctx.cache;
570 	struct spdk_ftl_dev *dev = cache->dev;
571 	int rc;
572 
573 	assert(page->page_buffer);
574 
575 	rc = ftl_nv_cache_bdev_write_blocks_with_md(dev, ftl_l2p_cache_get_bdev_desc(cache),
576 			ftl_l2p_cache_get_bdev_iochannel(cache),
577 			page->page_buffer, NULL, ftl_l2p_cache_page_get_bdev_offset(cache, page),
578 			1, cb, page);
579 
580 	if (spdk_likely(0 == rc)) {
581 		return;
582 	}
583 
584 	if (rc == -ENOMEM) {
585 		bdev = spdk_bdev_desc_get_bdev(ftl_l2p_cache_get_bdev_desc(cache));
586 		bdev_io_wait = &page->ctx.bdev_io_wait;
587 		bdev_io_wait->bdev = bdev;
588 		bdev_io_wait->cb_fn = process_page_out_retry;
589 		bdev_io_wait->cb_arg = page;
590 		page->ctx.cb = cb;
591 
592 		rc = spdk_bdev_queue_io_wait(bdev, ftl_l2p_cache_get_bdev_iochannel(cache), bdev_io_wait);
593 		ftl_bug(rc);
594 	} else {
595 		ftl_abort();
596 	}
597 }
598 
599 static void
600 process_page_out_retry(void *_page)
601 {
602 	struct ftl_l2p_page *page = _page;
603 
604 	process_page_out(page, page->ctx.cb);
605 }
606 
607 static void
608 clear_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status)
609 {
610 	ftl_l2p_cb cb = md->owner.private;
611 	void *cb_cntx = md->owner.cb_ctx;
612 
613 	cb(dev, status, cb_cntx);
614 }
615 
616 void
617 ftl_l2p_cache_clear(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx)
618 {
619 	struct ftl_md *md = dev->layout.md[FTL_LAYOUT_REGION_TYPE_L2P];
620 	ftl_addr invalid_addr = FTL_ADDR_INVALID;
621 
622 	md->cb =  clear_cb;
623 	md->owner.cb_ctx = cb_ctx;
624 	md->owner.private = cb;
625 
626 	ftl_md_clear(md, invalid_addr, NULL);
627 }
628 
629 static void
630 l2p_shm_restore_clean(struct spdk_ftl_dev *dev)
631 {
632 	struct ftl_l2p_cache *cache = (struct ftl_l2p_cache *)dev->l2p;
633 	struct ftl_l2p_l1_map_entry *me = cache->l2_mapping;
634 	struct ftl_l2p_page *page;
635 	ftl_df_obj_id obj_id;
636 	uint64_t page_no;
637 
638 	for (page_no = 0; page_no < cache->num_pages; ++page_no) {
639 		obj_id = me[page_no].page_obj_id;
640 		if (obj_id == FTL_DF_OBJ_ID_INVALID) {
641 			continue;
642 		}
643 
644 		page = ftl_mempool_claim_df(cache->l2_ctx_pool, obj_id);
645 		assert(page);
646 		assert(page->obj_id == ftl_mempool_get_df_obj_id(cache->l2_ctx_pool, page));
647 		assert(page->page_no == page_no);
648 		assert(page->state != L2P_CACHE_PAGE_INIT);
649 		assert(page->state != L2P_CACHE_PAGE_CLEARING);
650 		assert(cache->l2_pgs_avail > 0);
651 		cache->l2_pgs_avail--;
652 
653 		page->page_buffer = (char *)ftl_md_get_buffer(cache->l1_md) + ftl_mempool_get_df_obj_index(
654 					    cache->l2_ctx_pool, page) * FTL_BLOCK_SIZE;
655 
656 		TAILQ_INIT(&page->ppe_list);
657 
658 		page->pin_ref_cnt = 0;
659 		page->on_lru_list = 0;
660 		memset(&page->ctx, 0, sizeof(page->ctx));
661 
662 		ftl_l2p_cache_lru_add_page(cache, page);
663 	}
664 
665 	ftl_mempool_initialize_ext(cache->l2_ctx_pool);
666 }
667 
668 static void
669 l2p_shm_restore_dirty(struct spdk_ftl_dev *dev)
670 {
671 	struct ftl_l2p_cache *cache = (struct ftl_l2p_cache *)dev->l2p;
672 	struct ftl_l2p_l1_map_entry *me = cache->l2_mapping;
673 	struct ftl_l2p_page *page;
674 	ftl_df_obj_id obj_id;
675 	uint64_t page_no;
676 
677 	for (page_no = 0; page_no < cache->num_pages; ++page_no) {
678 		obj_id = me[page_no].page_obj_id;
679 		if (obj_id == FTL_DF_OBJ_ID_INVALID) {
680 			continue;
681 		}
682 
683 		page = ftl_mempool_claim_df(cache->l2_ctx_pool, obj_id);
684 		assert(page);
685 		assert(page->obj_id == ftl_mempool_get_df_obj_id(cache->l2_ctx_pool, page));
686 		assert(page->page_no == page_no);
687 		assert(page->state != L2P_CACHE_PAGE_CLEARING);
688 		assert(cache->l2_pgs_avail > 0);
689 		cache->l2_pgs_avail--;
690 
691 		if (page->state == L2P_CACHE_PAGE_INIT) {
692 			me[page_no].page_obj_id = FTL_DF_OBJ_ID_INVALID;
693 			cache->l2_pgs_avail++;
694 			ftl_mempool_release_df(cache->l2_ctx_pool, obj_id);
695 			continue;
696 		}
697 
698 		page->state = L2P_CACHE_PAGE_READY;
699 		/* Assume page is dirty after crash */
700 		page->updates = 1;
701 		page->page_buffer = (char *)ftl_md_get_buffer(cache->l1_md) + ftl_mempool_get_df_obj_index(
702 					    cache->l2_ctx_pool, page) * FTL_BLOCK_SIZE;
703 
704 		TAILQ_INIT(&page->ppe_list);
705 
706 		page->pin_ref_cnt = 0;
707 		page->on_lru_list = 0;
708 		memset(&page->ctx, 0, sizeof(page->ctx));
709 
710 		ftl_l2p_cache_lru_add_page(cache, page);
711 	}
712 
713 	ftl_mempool_initialize_ext(cache->l2_ctx_pool);
714 }
715 
716 void
717 ftl_l2p_cache_restore(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx)
718 {
719 	if (ftl_fast_startup(dev)) {
720 		l2p_shm_restore_clean(dev);
721 	}
722 
723 	if (ftl_fast_recovery(dev)) {
724 		l2p_shm_restore_dirty(dev);
725 	}
726 
727 	cb(dev, 0, cb_ctx);
728 }
729 
730 static void
731 process_persist(struct ftl_l2p_cache *cache)
732 {
733 	struct ftl_l2p_cache_process_ctx *ctx = &cache->mctx;
734 
735 	while (ctx->idx < cache->num_pages && ctx->qd < 64) {
736 		struct ftl_l2p_page *page = get_l2p_page_by_df_id(cache, ctx->idx);
737 		ctx->idx++;
738 
739 		if (!page) {
740 			continue;
741 		}
742 
743 		if (page->on_lru_list) {
744 			ftl_l2p_cache_lru_remove_page(cache, page);
745 		}
746 
747 		if (page->updates) {
748 			/* Need to persist the page */
749 			page->state = L2P_CACHE_PAGE_PERSISTING;
750 			page->ctx.cache = cache;
751 			ctx->qd++;
752 			process_page_out(page, process_persist_page_out_cb);
753 		} else {
754 			ftl_l2p_cache_page_remove(cache, page);
755 		}
756 	}
757 
758 	if (0 == ctx->qd) {
759 		process_finish(cache);
760 	}
761 }
762 
763 void
764 ftl_l2p_cache_persist(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx)
765 {
766 	struct ftl_l2p_cache *cache = (struct ftl_l2p_cache *)dev->l2p;
767 
768 	process_init_ctx(dev, cache, cb, cb_ctx);
769 	process_persist(cache);
770 }
771 
772 bool
773 ftl_l2p_cache_is_halted(struct spdk_ftl_dev *dev)
774 {
775 	struct ftl_l2p_cache *cache = (struct ftl_l2p_cache *)dev->l2p;
776 
777 	return cache->state == L2P_CACHE_SHUTDOWN_DONE;
778 }
779 
780 void
781 ftl_l2p_cache_halt(struct spdk_ftl_dev *dev)
782 {
783 	struct ftl_l2p_cache *cache = (struct ftl_l2p_cache *)dev->l2p;
784 
785 	if (cache->state != L2P_CACHE_SHUTDOWN_DONE) {
786 		cache->state = L2P_CACHE_IN_SHUTDOWN;
787 		if (!cache->ios_in_flight && !cache->l2_pgs_evicting) {
788 			cache->state = L2P_CACHE_SHUTDOWN_DONE;
789 		}
790 	}
791 }
792 
793 static inline struct ftl_l2p_page *
794 get_page(struct ftl_l2p_cache *cache, uint64_t lba)
795 {
796 	return get_l2p_page_by_df_id(cache, lba / cache->lbas_in_page);
797 }
798 
799 static inline void
800 ftl_l2p_cache_init_page_set(struct ftl_l2p_page_set *page_set, struct ftl_l2p_pin_ctx *pin_ctx)
801 {
802 	page_set->to_pin_cnt = 0;
803 	page_set->pinned_cnt = 0;
804 	page_set->pin_fault_cnt = 0;
805 	page_set->locked = 0;
806 	page_set->deferred = 0;
807 	page_set->pin_ctx = pin_ctx;
808 }
809 
810 static inline bool
811 ftl_l2p_cache_running(struct ftl_l2p_cache *cache)
812 {
813 	return cache->state == L2P_CACHE_RUNNING;
814 }
815 
816 static inline bool
817 ftl_l2p_cache_page_is_pinnable(struct ftl_l2p_page *page)
818 {
819 	return page->state != L2P_CACHE_PAGE_INIT;
820 }
821 
822 void
823 ftl_l2p_cache_pin(struct spdk_ftl_dev *dev, struct ftl_l2p_pin_ctx *pin_ctx)
824 {
825 	assert(dev->num_lbas >= pin_ctx->lba + pin_ctx->count);
826 	struct ftl_l2p_cache *cache = (struct ftl_l2p_cache *)dev->l2p;
827 	struct ftl_l2p_page_set *page_set;
828 	bool defer_pin = false;
829 
830 	/* Calculate first and last page to pin, count of them */
831 	uint64_t start = pin_ctx->lba / cache->lbas_in_page;
832 	uint64_t end = (pin_ctx->lba + pin_ctx->count - 1) / cache->lbas_in_page;
833 	uint64_t count = end - start + 1;
834 	uint64_t i;
835 
836 	if (spdk_unlikely(count > L2P_MAX_PAGES_TO_PIN)) {
837 		ftl_l2p_pin_complete(dev, -E2BIG, pin_ctx);
838 		return;
839 	}
840 
841 	/* Get and initialize page sets */
842 	assert(ftl_l2p_cache_running(cache));
843 	page_set = ftl_mempool_get(cache->page_sets_pool);
844 	if (!page_set) {
845 		ftl_l2p_pin_complete(dev, -EAGAIN, pin_ctx);
846 		return;
847 	}
848 	ftl_l2p_cache_init_page_set(page_set, pin_ctx);
849 
850 	struct ftl_l2p_page_wait_ctx *entry = page_set->entry;
851 	for (i = start; i <= end; i++, entry++) {
852 		struct ftl_l2p_page *page;
853 		entry->parent = page_set;
854 		entry->pg_no = i;
855 		entry->pg_pin_completed = false;
856 		entry->pg_pin_issued = false;
857 
858 		page_set->to_pin_cnt++;
859 
860 		/* Try get page and pin */
861 		page = get_l2p_page_by_df_id(cache, i);
862 		if (page) {
863 			if (ftl_l2p_cache_page_is_pinnable(page)) {
864 				/* Page available and we can pin it */
865 				page_set->pinned_cnt++;
866 				entry->pg_pin_issued = true;
867 				entry->pg_pin_completed = true;
868 				ftl_l2p_cache_page_pin(cache, page);
869 			} else {
870 				/* The page is being loaded */
871 				/* Queue the page pin entry to be executed on page in */
872 				ftl_l2p_page_queue_wait_ctx(page, entry);
873 				entry->pg_pin_issued = true;
874 			}
875 		} else {
876 			/* The page is not in the cache, queue the page_set to page in */
877 			defer_pin = true;
878 		}
879 	}
880 
881 	/* Check if page set is done */
882 	if (page_set_is_done(page_set)) {
883 		page_set_end(dev, cache, page_set);
884 	} else if (defer_pin) {
885 		TAILQ_INSERT_TAIL(&cache->deferred_page_set_list, page_set, list_entry);
886 		page_set->deferred = 1;
887 	}
888 }
889 
890 void
891 ftl_l2p_cache_unpin(struct spdk_ftl_dev *dev, uint64_t lba, uint64_t count)
892 {
893 	assert(dev->num_lbas >= lba + count);
894 	struct ftl_l2p_cache *cache = (struct ftl_l2p_cache *)dev->l2p;
895 	struct ftl_l2p_page *page;
896 	uint64_t start = lba / cache->lbas_in_page;
897 	uint64_t end = (lba + count - 1) / cache->lbas_in_page;
898 	uint64_t i;
899 
900 	assert(count);
901 	assert(start < cache->num_pages);
902 	assert(end < cache->num_pages);
903 
904 	for (i = start; i <= end; i++) {
905 		page = get_l2p_page_by_df_id(cache, i);
906 		ftl_bug(!page);
907 		ftl_l2p_cache_page_unpin(cache, page);
908 	}
909 }
910 
911 ftl_addr
912 ftl_l2p_cache_get(struct spdk_ftl_dev *dev, uint64_t lba)
913 {
914 	assert(dev->num_lbas > lba);
915 	struct ftl_l2p_cache *cache = (struct ftl_l2p_cache *)dev->l2p;
916 	struct ftl_l2p_page *page = get_page(cache, lba);
917 	ftl_addr addr;
918 
919 	ftl_bug(!page);
920 	assert(ftl_l2p_cache_running(cache));
921 	assert(page->pin_ref_cnt);
922 
923 	ftl_l2p_cache_lru_promote_page(cache, page);
924 	addr = ftl_l2p_cache_get_addr(dev, cache, page, lba);
925 
926 	return addr;
927 }
928 
929 void
930 ftl_l2p_cache_set(struct spdk_ftl_dev *dev, uint64_t lba, ftl_addr addr)
931 {
932 	assert(dev->num_lbas > lba);
933 	struct ftl_l2p_cache *cache = (struct ftl_l2p_cache *)dev->l2p;
934 	struct ftl_l2p_page *page = get_page(cache, lba);
935 
936 	ftl_bug(!page);
937 	assert(ftl_l2p_cache_running(cache));
938 	assert(page->pin_ref_cnt);
939 
940 	page->updates++;
941 	ftl_l2p_cache_lru_promote_page(cache, page);
942 	ftl_l2p_cache_set_addr(dev, cache, page, lba, addr);
943 }
944 
945 static struct ftl_l2p_page *
946 page_allocate(struct ftl_l2p_cache *cache, uint64_t page_no)
947 {
948 	struct ftl_l2p_page *page = ftl_l2p_cache_page_alloc(cache, page_no);
949 	ftl_l2p_cache_page_insert(cache, page);
950 
951 	return page;
952 }
953 
954 static bool
955 page_set_is_done(struct ftl_l2p_page_set *page_set)
956 {
957 	if (page_set->locked) {
958 		return false;
959 	}
960 
961 	assert(page_set->pinned_cnt + page_set->pin_fault_cnt <= page_set->to_pin_cnt);
962 	return (page_set->pinned_cnt + page_set->pin_fault_cnt == page_set->to_pin_cnt);
963 }
964 
965 static void
966 page_set_unpin(struct ftl_l2p_cache *cache, struct ftl_l2p_page_set *page_set)
967 {
968 	uint64_t i;
969 	struct ftl_l2p_page_wait_ctx *pentry = page_set->entry;
970 
971 	for (i = 0; i < page_set->to_pin_cnt; i++, pentry++) {
972 		struct ftl_l2p_page *pinned_page;
973 
974 		if (false == pentry->pg_pin_completed) {
975 			continue;
976 		}
977 
978 		pinned_page = get_l2p_page_by_df_id(cache, pentry->pg_no);
979 		ftl_bug(!pinned_page);
980 
981 		ftl_l2p_cache_page_unpin(cache, pinned_page);
982 	}
983 }
984 
985 static void
986 page_set_end(struct spdk_ftl_dev *dev, struct ftl_l2p_cache *cache,
987 	     struct ftl_l2p_page_set *page_set)
988 {
989 	if (spdk_likely(0 == page_set->pin_fault_cnt)) {
990 		ftl_l2p_pin_complete(dev, 0, page_set->pin_ctx);
991 	} else {
992 		page_set_unpin(cache, page_set);
993 		ftl_l2p_pin_complete(dev, -EIO, page_set->pin_ctx);
994 	}
995 
996 	if (page_set->deferred) {
997 		TAILQ_REMOVE(&cache->deferred_page_set_list, page_set, list_entry);
998 	}
999 
1000 	assert(0 == page_set->locked);
1001 	ftl_mempool_put(cache->page_sets_pool, page_set);
1002 }
1003 
1004 static void
1005 page_in_io_complete(struct spdk_ftl_dev *dev, struct ftl_l2p_cache *cache,
1006 		    struct ftl_l2p_page *page, bool success)
1007 {
1008 	struct ftl_l2p_page_set *page_set;
1009 	struct ftl_l2p_page_wait_ctx *pentry;
1010 
1011 	cache->ios_in_flight--;
1012 
1013 	assert(0 == page->pin_ref_cnt);
1014 	assert(L2P_CACHE_PAGE_INIT == page->state);
1015 	assert(false == page->on_lru_list);
1016 
1017 	if (spdk_likely(success)) {
1018 		page->state = L2P_CACHE_PAGE_READY;
1019 	}
1020 
1021 	while ((pentry = TAILQ_FIRST(&page->ppe_list))) {
1022 		TAILQ_REMOVE(&page->ppe_list, pentry, list_entry);
1023 
1024 		page_set = pentry->parent;
1025 
1026 		assert(false == pentry->pg_pin_completed);
1027 
1028 		if (success) {
1029 			ftl_l2p_cache_page_pin(cache, page);
1030 			page_set->pinned_cnt++;
1031 			pentry->pg_pin_completed = true;
1032 		} else {
1033 			page_set->pin_fault_cnt++;
1034 		}
1035 
1036 		/* Check if page_set is done */
1037 		if (page_set_is_done(page_set)) {
1038 			page_set_end(dev, cache, page_set);
1039 		}
1040 	}
1041 
1042 	if (spdk_unlikely(!success)) {
1043 		ftl_bug(page->on_lru_list);
1044 		ftl_l2p_cache_page_remove(cache, page);
1045 	}
1046 }
1047 
1048 static void
1049 page_in_io_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
1050 {
1051 	struct ftl_l2p_page *page = cb_arg;
1052 	struct ftl_l2p_cache *cache = page->ctx.cache;
1053 	struct spdk_ftl_dev *dev = cache->dev;
1054 
1055 	spdk_bdev_free_io(bdev_io);
1056 	page_in_io_complete(dev, cache, page, success);
1057 }
1058 
1059 static void
1060 page_in_io(struct spdk_ftl_dev *dev, struct ftl_l2p_cache *cache, struct ftl_l2p_page *page)
1061 {
1062 	struct spdk_io_channel *ioch;
1063 	struct spdk_bdev *bdev;
1064 	struct spdk_bdev_io_wait_entry *bdev_io_wait;
1065 	int rc;
1066 	page->ctx.cache = cache;
1067 
1068 	rc = ftl_nv_cache_bdev_read_blocks_with_md(cache->dev, ftl_l2p_cache_get_bdev_desc(cache),
1069 			ftl_l2p_cache_get_bdev_iochannel(cache),
1070 			page->page_buffer, NULL, ftl_l2p_cache_page_get_bdev_offset(cache, page),
1071 			1, page_in_io_cb, page);
1072 	cache->ios_in_flight++;
1073 	if (spdk_likely(0 == rc)) {
1074 		return;
1075 	}
1076 
1077 	if (rc == -ENOMEM) {
1078 		ioch = ftl_l2p_cache_get_bdev_iochannel(cache);
1079 		bdev = spdk_bdev_desc_get_bdev(ftl_l2p_cache_get_bdev_desc(cache));
1080 		bdev_io_wait = &page->ctx.bdev_io_wait;
1081 		bdev_io_wait->bdev = bdev;
1082 		bdev_io_wait->cb_fn = page_in_io_retry;
1083 		bdev_io_wait->cb_arg = page;
1084 
1085 		rc = spdk_bdev_queue_io_wait(bdev, ioch, bdev_io_wait);
1086 		ftl_bug(rc);
1087 	} else {
1088 		ftl_abort();
1089 	}
1090 }
1091 
1092 static void
1093 page_in_io_retry(void *arg)
1094 {
1095 	struct ftl_l2p_page *page = arg;
1096 	struct ftl_l2p_cache *cache = page->ctx.cache;
1097 	struct spdk_ftl_dev *dev = cache->dev;
1098 
1099 	cache->ios_in_flight--;
1100 	page_in_io(dev, cache, page);
1101 }
1102 
1103 static void
1104 page_in(struct spdk_ftl_dev *dev, struct ftl_l2p_cache *cache,
1105 	struct ftl_l2p_page_set *page_set, struct ftl_l2p_page_wait_ctx *pentry)
1106 {
1107 	struct ftl_l2p_page *page;
1108 	bool page_in = false;
1109 
1110 	/* Get page */
1111 	page = get_l2p_page_by_df_id(cache, pentry->pg_no);
1112 	if (!page) {
1113 		/* Page not allocated yet, do it */
1114 		page = page_allocate(cache, pentry->pg_no);
1115 		page_in = true;
1116 	}
1117 
1118 	if (ftl_l2p_cache_page_is_pinnable(page)) {
1119 		ftl_l2p_cache_page_pin(cache, page);
1120 		page_set->pinned_cnt++;
1121 		pentry->pg_pin_issued = true;
1122 		pentry->pg_pin_completed = true;
1123 	} else {
1124 		pentry->pg_pin_issued = true;
1125 		ftl_l2p_page_queue_wait_ctx(page, pentry);
1126 	}
1127 
1128 	if (page_in) {
1129 		page_in_io(dev, cache, page);
1130 	}
1131 }
1132 
1133 static int
1134 ftl_l2p_cache_process_page_sets(struct spdk_ftl_dev *dev, struct ftl_l2p_cache *cache)
1135 {
1136 	struct ftl_l2p_page_set *page_set;
1137 	struct ftl_l2p_page_wait_ctx *pentry;
1138 	uint64_t i;
1139 
1140 	page_set = TAILQ_FIRST(&cache->deferred_page_set_list);
1141 	if (!page_set) {
1142 		/* No page_set */
1143 		return -ECHILD;
1144 	}
1145 
1146 	if (page_set->to_pin_cnt > cache->l2_pgs_avail) {
1147 		/* No enough page to pin, wait */
1148 		return -EBUSY;
1149 	}
1150 	if (cache->ios_in_flight > 512) {
1151 		/* Too big QD */
1152 		return -EBUSY;
1153 	}
1154 
1155 	TAILQ_REMOVE(&cache->deferred_page_set_list, page_set, list_entry);
1156 	page_set->deferred = 0;
1157 	page_set->locked = 1;
1158 
1159 	/* Now we can start pinning */
1160 	pentry = page_set->entry;
1161 	for (i = 0; i < page_set->to_pin_cnt; i++, pentry++) {
1162 		if (!pentry->pg_pin_issued) {
1163 			page_in(dev, cache, page_set, pentry);
1164 		}
1165 	}
1166 
1167 	page_set->locked = 0;
1168 
1169 	/* Check if page_set is done */
1170 	if (page_set_is_done(page_set)) {
1171 		page_set_end(dev, cache, page_set);
1172 	}
1173 
1174 	return 0;
1175 }
1176 
1177 static struct ftl_l2p_page *
1178 eviction_get_page(struct spdk_ftl_dev *dev, struct ftl_l2p_cache *cache)
1179 {
1180 	uint64_t i = 0;
1181 	struct ftl_l2p_page *page = ftl_l2p_cache_get_coldest_page(cache);
1182 
1183 	while (page) {
1184 		ftl_bug(L2P_CACHE_PAGE_READY != page->state);
1185 		ftl_bug(page->pin_ref_cnt);
1186 
1187 		if (ftl_l2p_cache_page_can_evict(page)) {
1188 			ftl_l2p_cache_lru_remove_page(cache, page);
1189 			return page;
1190 		}
1191 
1192 		/*
1193 		 * Practically only one iteration is needed to find a page. It is because
1194 		 * the rank of pages contains only ready and unpinned pages
1195 		 */
1196 		ftl_bug(++i > 1024);
1197 
1198 		page = ftl_l2p_cache_get_hotter_page(page);
1199 	}
1200 
1201 	return NULL;
1202 }
1203 
1204 static void
1205 page_out_io_complete(struct spdk_ftl_dev *dev, struct ftl_l2p_cache *cache,
1206 		     struct ftl_l2p_page *page, bool success)
1207 {
1208 	cache->l2_pgs_evicting--;
1209 
1210 	ftl_bug(page->ctx.updates > page->updates);
1211 	ftl_bug(!TAILQ_EMPTY(&page->ppe_list));
1212 	ftl_bug(page->on_lru_list);
1213 
1214 	if (spdk_likely(success)) {
1215 		page->updates -= page->ctx.updates;
1216 	}
1217 
1218 	if (success && ftl_l2p_cache_page_can_remove(page)) {
1219 		ftl_l2p_cache_page_remove(cache, page);
1220 	} else {
1221 		if (!page->pin_ref_cnt) {
1222 			ftl_l2p_cache_lru_add_page(cache, page);
1223 		}
1224 		page->state = L2P_CACHE_PAGE_READY;
1225 	}
1226 }
1227 
1228 static void
1229 page_out_io_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
1230 {
1231 	struct ftl_l2p_page *page = cb_arg;
1232 	struct ftl_l2p_cache *cache = page->ctx.cache;
1233 	struct spdk_ftl_dev *dev = cache->dev;
1234 
1235 	spdk_bdev_free_io(bdev_io);
1236 	page_out_io_complete(dev, cache, page, success);
1237 }
1238 
1239 static void
1240 page_out_io(struct spdk_ftl_dev *dev, struct ftl_l2p_cache *cache,
1241 	    struct ftl_l2p_page *page)
1242 {
1243 	struct spdk_io_channel *ioch;
1244 	struct spdk_bdev *bdev;
1245 	struct spdk_bdev_io_wait_entry *bdev_io_wait;
1246 	int rc;
1247 
1248 	page->ctx.cache = cache;
1249 
1250 	rc = ftl_nv_cache_bdev_write_blocks_with_md(dev, ftl_l2p_cache_get_bdev_desc(cache),
1251 			ftl_l2p_cache_get_bdev_iochannel(cache),
1252 			page->page_buffer, NULL, ftl_l2p_cache_page_get_bdev_offset(cache, page),
1253 			1, page_out_io_cb, page);
1254 
1255 	cache->l2_pgs_evicting++;
1256 	if (spdk_likely(0 == rc)) {
1257 		return;
1258 	}
1259 
1260 	if (rc == -ENOMEM) {
1261 		ioch = ftl_l2p_cache_get_bdev_iochannel(cache);
1262 		bdev = spdk_bdev_desc_get_bdev(ftl_l2p_cache_get_bdev_desc(cache));
1263 		bdev_io_wait = &page->ctx.bdev_io_wait;
1264 		bdev_io_wait->bdev = bdev;
1265 		bdev_io_wait->cb_fn = page_out_io_retry;
1266 		bdev_io_wait->cb_arg = page;
1267 
1268 		rc = spdk_bdev_queue_io_wait(bdev, ioch, bdev_io_wait);
1269 		ftl_bug(rc);
1270 	} else {
1271 		ftl_abort();
1272 	}
1273 }
1274 
1275 static void
1276 page_out_io_retry(void *arg)
1277 {
1278 	struct ftl_l2p_page *page = arg;
1279 	struct ftl_l2p_cache *cache = page->ctx.cache;
1280 	struct spdk_ftl_dev *dev = cache->dev;
1281 
1282 	cache->l2_pgs_evicting--;
1283 	page_out_io(dev, cache, page);
1284 }
1285 
1286 static void
1287 ftl_l2p_cache_process_eviction(struct spdk_ftl_dev *dev, struct ftl_l2p_cache *cache)
1288 {
1289 	struct ftl_l2p_page *page;
1290 
1291 	if (!ftl_l2p_cache_evict_continue(cache)) {
1292 		return;
1293 	}
1294 
1295 	if (cache->l2_pgs_evicting > 512) {
1296 		return;
1297 	}
1298 
1299 	page = eviction_get_page(dev, cache);
1300 	if (spdk_unlikely(!page)) {
1301 		return;
1302 	}
1303 
1304 	if (page->updates) {
1305 		page->state = L2P_CACHE_PAGE_FLUSHING;
1306 		page->ctx.updates = page->updates;
1307 		page_out_io(dev, cache, page);
1308 	} else {
1309 		/* Page clean and we can remove it */
1310 		ftl_l2p_cache_page_remove(cache, page);
1311 	}
1312 }
1313 
1314 void
1315 ftl_l2p_cache_process(struct spdk_ftl_dev *dev)
1316 {
1317 	struct ftl_l2p_cache *cache = dev->l2p;
1318 	int i;
1319 
1320 	if (spdk_unlikely(cache->state != L2P_CACHE_RUNNING)) {
1321 		return;
1322 	}
1323 
1324 	for (i = 0; i < 256; i++) {
1325 		if (ftl_l2p_cache_process_page_sets(dev, cache)) {
1326 			break;
1327 		}
1328 	}
1329 
1330 	ftl_l2p_cache_process_eviction(dev, cache);
1331 }
1332