1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/thread.h" 7 #include "spdk/crc32.h" 8 9 #include "ftl_core.h" 10 #include "ftl_mngt.h" 11 #include "ftl_mngt_steps.h" 12 #include "ftl_utils.h" 13 #include "ftl_band.h" 14 #include "ftl_internal.h" 15 #include "ftl_sb.h" 16 17 void 18 ftl_mngt_init_layout(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 19 { 20 if (ftl_layout_setup(dev)) { 21 ftl_mngt_fail_step(mngt); 22 } else { 23 ftl_mngt_next_step(mngt); 24 } 25 } 26 27 static bool 28 is_buffer_needed(enum ftl_layout_region_type type) 29 { 30 switch (type) { 31 #ifdef SPDK_FTL_VSS_EMU 32 case FTL_LAYOUT_REGION_TYPE_VSS: 33 #endif 34 case FTL_LAYOUT_REGION_TYPE_SB: 35 case FTL_LAYOUT_REGION_TYPE_SB_BASE: 36 case FTL_LAYOUT_REGION_TYPE_DATA_NVC: 37 case FTL_LAYOUT_REGION_TYPE_DATA_BASE: 38 case FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR: 39 case FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR: 40 #ifndef SPDK_FTL_L2P_FLAT 41 case FTL_LAYOUT_REGION_TYPE_L2P: 42 #endif 43 case FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR: 44 return false; 45 46 default: 47 return true; 48 } 49 } 50 51 void 52 ftl_mngt_init_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 53 { 54 struct ftl_layout *layout = &dev->layout; 55 struct ftl_layout_region *region = layout->region; 56 uint64_t i; 57 int md_flags; 58 59 for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++, region++) { 60 if (layout->md[i]) { 61 /* 62 * Some metadata objects are initialized by other FTL 63 * components. At the moment it's only used by superblock (and its mirror) - 64 * during load time we need to read it earlier in order to get the layout for the 65 * other regions. 66 */ 67 continue; 68 } 69 md_flags = is_buffer_needed(i) ? ftl_md_create_region_flags(dev, 70 region->type) : FTL_MD_CREATE_NO_MEM; 71 layout->md[i] = ftl_md_create(dev, region->current.blocks, region->vss_blksz, region->name, 72 md_flags, region); 73 if (NULL == layout->md[i]) { 74 ftl_mngt_fail_step(mngt); 75 return; 76 } 77 } 78 79 ftl_mngt_next_step(mngt); 80 } 81 82 void 83 ftl_mngt_deinit_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 84 { 85 struct ftl_layout *layout = &dev->layout; 86 struct ftl_layout_region *region = layout->region; 87 uint64_t i; 88 89 for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++, region++) { 90 if (layout->md[i]) { 91 ftl_md_destroy(layout->md[i], ftl_md_destroy_region_flags(dev, layout->region[i].type)); 92 layout->md[i] = NULL; 93 } 94 } 95 96 ftl_mngt_next_step(mngt); 97 } 98 99 static void 100 persist_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status) 101 { 102 struct ftl_mngt_process *mngt = md->owner.cb_ctx; 103 104 if (status) { 105 ftl_mngt_fail_step(mngt); 106 } else { 107 ftl_mngt_next_step(mngt); 108 } 109 } 110 111 static void 112 persist(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt, 113 enum ftl_layout_region_type type) 114 { 115 struct ftl_layout *layout = &dev->layout; 116 struct ftl_md *md; 117 118 assert(type < FTL_LAYOUT_REGION_TYPE_MAX); 119 120 md = layout->md[type]; 121 if (!md) { 122 ftl_mngt_fail_step(mngt); 123 return; 124 } 125 126 md->owner.cb_ctx = mngt; 127 md->cb = persist_cb; 128 ftl_md_persist(md); 129 } 130 131 static int 132 ftl_md_restore_region(struct spdk_ftl_dev *dev, int region_type) 133 { 134 int status = 0; 135 switch (region_type) { 136 case FTL_LAYOUT_REGION_TYPE_NVC_MD: 137 status = ftl_nv_cache_load_state(&dev->nv_cache); 138 break; 139 case FTL_LAYOUT_REGION_TYPE_VALID_MAP: 140 ftl_valid_map_load_state(dev); 141 break; 142 case FTL_LAYOUT_REGION_TYPE_BAND_MD: 143 ftl_bands_load_state(dev); 144 break; 145 default: 146 break; 147 } 148 return status; 149 } 150 151 static void 152 restore_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status) 153 { 154 struct ftl_mngt_process *mngt = md->owner.cb_ctx; 155 const struct ftl_layout_region *region = ftl_md_get_region(md); 156 157 if (status) { 158 /* Restore error, end step */ 159 ftl_mngt_fail_step(mngt); 160 return; 161 } 162 163 assert(region); 164 status = ftl_md_restore_region(dev, region->type); 165 166 if (status) { 167 ftl_mngt_fail_step(mngt); 168 } else { 169 ftl_mngt_next_step(mngt); 170 } 171 } 172 173 static void 174 restore(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt, enum ftl_layout_region_type type) 175 { 176 struct ftl_layout *layout = &dev->layout; 177 assert(type < FTL_LAYOUT_REGION_TYPE_MAX); 178 struct ftl_md *md = layout->md[type]; 179 180 if (!md) { 181 ftl_mngt_fail_step(mngt); 182 return; 183 } 184 185 md->owner.cb_ctx = mngt; 186 md->cb = restore_cb; 187 ftl_md_restore(md); 188 } 189 190 void 191 ftl_mngt_persist_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 192 { 193 if (ftl_nv_cache_save_state(&dev->nv_cache)) { 194 ftl_mngt_fail_step(mngt); 195 return; 196 } 197 198 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_NVC_MD); 199 } 200 201 static void 202 ftl_mngt_fast_persist_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 203 { 204 if (ftl_nv_cache_save_state(&dev->nv_cache)) { 205 ftl_mngt_fail_step(mngt); 206 return; 207 } 208 ftl_mngt_next_step(mngt); 209 } 210 211 static void 212 ftl_mngt_persist_vld_map_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 213 { 214 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_VALID_MAP); 215 } 216 217 static void 218 ftl_mngt_persist_p2l_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 219 { 220 /* Sync runtime P2L to persist any invalidation that may have happened */ 221 222 struct ftl_p2l_sync_ctx *ctx = ftl_mngt_get_step_ctx(mngt); 223 224 /* 225 * ftl_mngt_persist_bands_p2l will increment the md_region before the step_continue for next regions 226 */ 227 if (ctx->md_region <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN) { 228 ctx->md_region = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN; 229 } 230 ftl_mngt_persist_bands_p2l(mngt); 231 } 232 233 void 234 ftl_mngt_persist_band_info_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 235 { 236 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_BAND_MD); 237 } 238 239 static void 240 ftl_mngt_persist_trim_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 241 { 242 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_TRIM_MD); 243 } 244 245 static uint32_t 246 get_sb_crc(struct ftl_superblock *sb) 247 { 248 uint32_t crc = 0; 249 250 /* Calculate CRC excluding CRC field in superblock */ 251 void *buffer = sb; 252 size_t offset = offsetof(struct ftl_superblock, header.crc); 253 size_t size = offset; 254 crc = spdk_crc32c_update(buffer, size, crc); 255 256 buffer += offset + sizeof(sb->header.crc); 257 size = FTL_SUPERBLOCK_SIZE - offset - sizeof(sb->header.crc); 258 crc = spdk_crc32c_update(buffer, size, crc); 259 260 return crc; 261 } 262 263 static void 264 ftl_mngt_persist_super_block(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 265 { 266 dev->sb->overprovisioning = dev->conf.overprovisioning; 267 dev->sb->gc_info = dev->sb_shm->gc_info; 268 dev->sb->header.crc = get_sb_crc(dev->sb); 269 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 270 } 271 272 #ifdef SPDK_FTL_VSS_EMU 273 static void 274 ftl_mngt_persist_vss(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 275 { 276 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_VSS); 277 } 278 #endif 279 280 /* 281 * Persists all necessary metadata (band state, P2L, etc) during FTL's clean shutdown. 282 */ 283 static const struct ftl_mngt_process_desc desc_persist = { 284 .name = "Persist metadata", 285 .steps = { 286 { 287 .name = "Persist NV cache metadata", 288 .action = ftl_mngt_persist_nv_cache_metadata, 289 }, 290 { 291 .name = "Persist valid map metadata", 292 .action = ftl_mngt_persist_vld_map_metadata, 293 }, 294 { 295 .name = "Persist P2L metadata", 296 .action = ftl_mngt_persist_p2l_metadata, 297 .ctx_size = sizeof(struct ftl_p2l_sync_ctx), 298 }, 299 { 300 .name = "persist band info metadata", 301 .action = ftl_mngt_persist_band_info_metadata, 302 }, 303 { 304 .name = "persist trim metadata", 305 .action = ftl_mngt_persist_trim_metadata, 306 }, 307 { 308 .name = "Persist superblock", 309 .action = ftl_mngt_persist_super_block, 310 }, 311 #ifdef SPDK_FTL_VSS_EMU 312 { 313 .name = "Persist VSS metadata", 314 .action = ftl_mngt_persist_vss, 315 }, 316 #endif 317 {} 318 } 319 }; 320 321 void 322 ftl_mngt_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 323 { 324 ftl_mngt_call_process(mngt, &desc_persist); 325 } 326 327 /* 328 * Fast clean shutdown path - skips the persistance of most metadata regions and 329 * relies on their shared memory state instead. 330 */ 331 static const struct ftl_mngt_process_desc desc_fast_persist = { 332 .name = "Fast persist metadata", 333 .steps = { 334 { 335 .name = "Fast persist NV cache metadata", 336 .action = ftl_mngt_fast_persist_nv_cache_metadata, 337 }, 338 #ifdef SPDK_FTL_VSS_EMU 339 { 340 .name = "Persist VSS metadata", 341 .action = ftl_mngt_persist_vss, 342 }, 343 #endif 344 {} 345 } 346 }; 347 348 void 349 ftl_mngt_fast_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 350 { 351 ftl_mngt_call_process(mngt, &desc_fast_persist); 352 } 353 354 void 355 ftl_mngt_init_default_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 356 { 357 struct ftl_superblock *sb = dev->sb; 358 359 sb->header.magic = FTL_SUPERBLOCK_MAGIC; 360 sb->header.version = FTL_METADATA_VERSION_CURRENT; 361 sb->uuid = dev->conf.uuid; 362 sb->clean = 0; 363 dev->sb_shm->shm_clean = false; 364 sb->ckpt_seq_id = 0; 365 366 /* Max 16 IO depth per band relocate */ 367 sb->max_reloc_qdepth = 16; 368 369 sb->overprovisioning = dev->conf.overprovisioning; 370 371 ftl_band_init_gc_iter(dev); 372 373 /* md layout isn't initialized yet. 374 * empty region list => all regions in the default location */ 375 sb->md_layout_head.type = FTL_LAYOUT_REGION_TYPE_INVALID; 376 377 sb->header.crc = get_sb_crc(sb); 378 379 ftl_mngt_next_step(mngt); 380 } 381 382 void 383 ftl_mngt_set_dirty(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 384 { 385 struct ftl_superblock *sb = dev->sb; 386 387 sb->clean = 0; 388 dev->sb_shm->shm_clean = false; 389 sb->header.crc = get_sb_crc(sb); 390 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 391 } 392 393 void 394 ftl_mngt_set_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 395 { 396 struct ftl_superblock *sb = dev->sb; 397 398 sb->clean = 1; 399 dev->sb_shm->shm_clean = false; 400 sb->header.crc = get_sb_crc(sb); 401 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 402 403 dev->sb_shm->shm_ready = false; 404 } 405 406 void 407 ftl_mngt_set_shm_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 408 { 409 struct ftl_superblock *sb = dev->sb; 410 411 sb->clean = 1; 412 dev->sb_shm->shm_clean = true; 413 sb->header.crc = get_sb_crc(sb); 414 ftl_mngt_next_step(mngt); 415 } 416 417 void 418 ftl_mngt_load_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 419 { 420 FTL_NOTICELOG(dev, "SHM: clean %"PRIu64", shm_clean %d\n", dev->sb->clean, dev->sb_shm->shm_clean); 421 422 if (!ftl_fast_startup(dev)) { 423 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 424 return; 425 } 426 427 FTL_DEBUGLOG(dev, "SHM: found SB\n"); 428 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_SB)) { 429 ftl_mngt_fail_step(mngt); 430 return; 431 } 432 ftl_mngt_next_step(mngt); 433 } 434 435 void 436 ftl_mngt_validate_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 437 { 438 struct ftl_superblock *sb = dev->sb; 439 440 if (!ftl_superblock_check_magic(sb)) { 441 FTL_ERRLOG(dev, "Invalid FTL superblock magic\n"); 442 ftl_mngt_fail_step(mngt); 443 return; 444 } 445 446 if (sb->header.crc != get_sb_crc(sb)) { 447 FTL_ERRLOG(dev, "Invalid FTL superblock CRC\n"); 448 ftl_mngt_fail_step(mngt); 449 return; 450 } 451 452 if (spdk_uuid_compare(&sb->uuid, &dev->conf.uuid) != 0) { 453 FTL_ERRLOG(dev, "Invalid FTL superblock UUID\n"); 454 ftl_mngt_fail_step(mngt); 455 return; 456 } 457 458 if (sb->lba_cnt == 0) { 459 FTL_ERRLOG(dev, "Invalid FTL superblock lba_cnt\n"); 460 ftl_mngt_fail_step(mngt); 461 return; 462 } 463 dev->num_lbas = sb->lba_cnt; 464 465 /* The sb has just been read. Validate and update the conf */ 466 if (sb->overprovisioning == 0 || sb->overprovisioning >= 100) { 467 FTL_ERRLOG(dev, "Invalid FTL superblock lba_rsvd\n"); 468 ftl_mngt_fail_step(mngt); 469 return; 470 } 471 dev->conf.overprovisioning = sb->overprovisioning; 472 473 ftl_mngt_next_step(mngt); 474 } 475 476 /* 477 * Loads and verifies superblock contents - utilized during the load of an FTL 478 * instance (both from a clean and dirty shutdown). 479 */ 480 static const struct ftl_mngt_process_desc desc_restore_sb = { 481 .name = "SB restore", 482 .steps = { 483 { 484 .name = "Load super block", 485 .action = ftl_mngt_load_sb 486 }, 487 { 488 .name = "Validate super block", 489 .action = ftl_mngt_validate_sb 490 }, 491 {} 492 } 493 }; 494 495 /* 496 * Initializes the superblock fields during first startup of FTL 497 */ 498 static const struct ftl_mngt_process_desc desc_init_sb = { 499 .name = "SB initialize", 500 .steps = { 501 { 502 .name = "Default-initialize superblock", 503 .action = ftl_mngt_init_default_sb, 504 }, 505 {} 506 } 507 }; 508 509 #ifdef SPDK_FTL_VSS_EMU 510 void 511 ftl_mngt_md_init_vss_emu(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 512 { 513 struct ftl_layout *layout = &dev->layout; 514 struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_VSS]; 515 516 /* Initialize VSS layout */ 517 ftl_layout_setup_vss_emu(dev); 518 519 /* Allocate md buf */ 520 layout->md[FTL_LAYOUT_REGION_TYPE_VSS] = ftl_md_create(dev, region->current.blocks, 521 region->vss_blksz, NULL, 0, region); 522 if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_VSS]) { 523 ftl_mngt_fail_step(mngt); 524 return; 525 } 526 ftl_mngt_next_step(mngt); 527 } 528 529 void 530 ftl_mngt_md_deinit_vss_emu(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 531 { 532 struct ftl_layout *layout = &dev->layout; 533 534 if (layout->md[FTL_LAYOUT_REGION_TYPE_VSS]) { 535 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_VSS], 0); 536 layout->md[FTL_LAYOUT_REGION_TYPE_VSS] = NULL; 537 } 538 539 ftl_mngt_next_step(mngt); 540 } 541 #endif 542 543 void 544 ftl_mngt_superblock_init(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 545 { 546 struct ftl_layout *layout = &dev->layout; 547 struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB]; 548 char uuid[SPDK_UUID_STRING_LEN]; 549 int md_create_flags = ftl_md_create_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB); 550 551 /* Must generate UUID before MD create on SHM for the SB */ 552 if (dev->conf.mode & SPDK_FTL_MODE_CREATE) { 553 spdk_uuid_generate(&dev->conf.uuid); 554 spdk_uuid_fmt_lower(uuid, sizeof(uuid), &dev->conf.uuid); 555 FTL_NOTICELOG(dev, "Create new FTL, UUID %s\n", uuid); 556 } 557 558 shm_retry: 559 /* Allocate md buf */ 560 dev->sb_shm = NULL; 561 dev->sb_shm_md = ftl_md_create(dev, spdk_divide_round_up(sizeof(*dev->sb_shm), FTL_BLOCK_SIZE), 562 0, "sb_shm", 563 md_create_flags, NULL); 564 if (dev->sb_shm_md == NULL) { 565 /* The first attempt may fail when trying to open SHM - try to create new */ 566 if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) { 567 md_create_flags |= FTL_MD_CREATE_SHM_NEW; 568 goto shm_retry; 569 } 570 if (dev->sb_shm_md == NULL) { 571 ftl_mngt_fail_step(mngt); 572 return; 573 } 574 } 575 576 dev->sb_shm = ftl_md_get_buffer(dev->sb_shm_md); 577 578 /* Setup the layout of a superblock */ 579 if (ftl_layout_setup_superblock(dev)) { 580 ftl_mngt_fail_step(mngt); 581 return; 582 } 583 584 /* Allocate md buf */ 585 layout->md[FTL_LAYOUT_REGION_TYPE_SB] = ftl_md_create(dev, region->current.blocks, 586 region->vss_blksz, region->name, 587 md_create_flags, region); 588 if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB]) { 589 /* The first attempt may fail when trying to open SHM - try to create new */ 590 if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) { 591 md_create_flags |= FTL_MD_CREATE_SHM_NEW; 592 ftl_md_destroy(dev->sb_shm_md, 0); 593 goto shm_retry; 594 } 595 ftl_mngt_fail_step(mngt); 596 return; 597 } 598 599 /* Link the md buf to the device */ 600 dev->sb = ftl_md_get_buffer(layout->md[FTL_LAYOUT_REGION_TYPE_SB]); 601 602 /* Setup superblock mirror to QLC */ 603 region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB_BASE]; 604 layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = ftl_md_create(dev, region->current.blocks, 605 region->vss_blksz, NULL, FTL_MD_CREATE_HEAP, region); 606 if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) { 607 ftl_mngt_fail_step(mngt); 608 return; 609 } 610 611 /* Initialize the superblock */ 612 if (dev->conf.mode & SPDK_FTL_MODE_CREATE) { 613 ftl_mngt_call_process(mngt, &desc_init_sb); 614 } else { 615 ftl_mngt_call_process(mngt, &desc_restore_sb); 616 } 617 } 618 619 void 620 ftl_mngt_superblock_deinit(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 621 { 622 struct ftl_layout *layout = &dev->layout; 623 624 if (layout->md[FTL_LAYOUT_REGION_TYPE_SB]) { 625 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB], 626 ftl_md_destroy_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB)); 627 layout->md[FTL_LAYOUT_REGION_TYPE_SB] = NULL; 628 } 629 630 if (layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) { 631 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE], 0); 632 layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = NULL; 633 } 634 635 ftl_md_destroy(dev->sb_shm_md, ftl_md_destroy_shm_flags(dev)); 636 dev->sb_shm_md = NULL; 637 dev->sb_shm = NULL; 638 639 ftl_mngt_next_step(mngt); 640 } 641 642 static void 643 ftl_mngt_restore_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 644 { 645 if (ftl_fast_startup(dev)) { 646 FTL_DEBUGLOG(dev, "SHM: found nv cache md\n"); 647 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_NVC_MD)) { 648 ftl_mngt_fail_step(mngt); 649 return; 650 } 651 ftl_mngt_next_step(mngt); 652 return; 653 } 654 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_NVC_MD); 655 } 656 657 static void 658 ftl_mngt_restore_vld_map_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 659 { 660 if (ftl_fast_startup(dev)) { 661 FTL_DEBUGLOG(dev, "SHM: found vldmap\n"); 662 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_VALID_MAP)) { 663 ftl_mngt_fail_step(mngt); 664 return; 665 } 666 ftl_mngt_next_step(mngt); 667 return; 668 } 669 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_VALID_MAP); 670 } 671 672 static void 673 ftl_mngt_restore_band_info_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 674 { 675 if (ftl_fast_startup(dev)) { 676 FTL_DEBUGLOG(dev, "SHM: found band md\n"); 677 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_BAND_MD)) { 678 ftl_mngt_fail_step(mngt); 679 return; 680 } 681 ftl_mngt_next_step(mngt); 682 return; 683 } 684 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_BAND_MD); 685 } 686 687 static void 688 ftl_mngt_restore_trim_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 689 { 690 if (ftl_fast_startup(dev)) { 691 FTL_DEBUGLOG(dev, "SHM: found trim md\n"); 692 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_TRIM_MD)) { 693 ftl_mngt_fail_step(mngt); 694 return; 695 } 696 ftl_mngt_next_step(mngt); 697 return; 698 } 699 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_TRIM_MD); 700 } 701 702 703 704 #ifdef SPDK_FTL_VSS_EMU 705 static void 706 ftl_mngt_restore_vss_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 707 { 708 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_VSS); 709 } 710 #endif 711 712 /* 713 * Loads metadata after a clean shutdown. 714 */ 715 static const struct ftl_mngt_process_desc desc_restore = { 716 .name = "Restore metadata", 717 .steps = { 718 #ifdef SPDK_FTL_VSS_EMU 719 { 720 .name = "Restore VSS metadata", 721 .action = ftl_mngt_restore_vss_metadata, 722 }, 723 #endif 724 { 725 .name = "Restore NV cache metadata", 726 .action = ftl_mngt_restore_nv_cache_metadata, 727 }, 728 { 729 .name = "Restore valid map metadata", 730 .action = ftl_mngt_restore_vld_map_metadata, 731 }, 732 { 733 .name = "Restore band info metadata", 734 .action = ftl_mngt_restore_band_info_metadata, 735 }, 736 { 737 .name = "Restore trim metadata", 738 .action = ftl_mngt_restore_trim_metadata, 739 }, 740 {} 741 } 742 }; 743 744 void 745 ftl_mngt_restore_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 746 { 747 ftl_mngt_call_process(mngt, &desc_restore); 748 } 749