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