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