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 void 217 ftl_mngt_persist_band_info_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 218 { 219 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_BAND_MD); 220 } 221 222 static uint32_t 223 get_sb_crc(struct ftl_superblock *sb) 224 { 225 uint32_t crc = 0; 226 227 /* Calculate CRC excluding CRC field in superblock */ 228 void *buffer = sb; 229 size_t offset = offsetof(struct ftl_superblock, header.crc); 230 size_t size = offset; 231 crc = spdk_crc32c_update(buffer, size, crc); 232 233 buffer += offset + sizeof(sb->header.crc); 234 size = FTL_SUPERBLOCK_SIZE - offset - sizeof(sb->header.crc); 235 crc = spdk_crc32c_update(buffer, size, crc); 236 237 return crc; 238 } 239 240 static void 241 ftl_mngt_persist_super_block(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 242 { 243 dev->sb->overprovisioning = dev->conf.overprovisioning; 244 dev->sb->gc_info = dev->sb_shm->gc_info; 245 dev->sb->header.crc = get_sb_crc(dev->sb); 246 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 247 } 248 249 #ifdef SPDK_FTL_VSS_EMU 250 static void 251 ftl_mngt_persist_vss(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 252 { 253 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_VSS); 254 } 255 #endif 256 257 /* 258 * Persists all necessary metadata (band state, P2L, etc) during FTL's clean shutdown. 259 */ 260 static const struct ftl_mngt_process_desc desc_persist = { 261 .name = "Persist metadata", 262 .steps = { 263 { 264 .name = "Persist NV cache metadata", 265 .action = ftl_mngt_persist_nv_cache_metadata, 266 }, 267 { 268 .name = "Persist valid map metadata", 269 .action = ftl_mngt_persist_vld_map_metadata, 270 }, 271 { 272 .name = "persist band info metadata", 273 .action = ftl_mngt_persist_band_info_metadata, 274 }, 275 { 276 .name = "Persist superblock", 277 .action = ftl_mngt_persist_super_block, 278 }, 279 #ifdef SPDK_FTL_VSS_EMU 280 { 281 .name = "Persist VSS metadata", 282 .action = ftl_mngt_persist_vss, 283 }, 284 #endif 285 {} 286 } 287 }; 288 289 void 290 ftl_mngt_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 291 { 292 ftl_mngt_call_process(mngt, &desc_persist); 293 } 294 295 /* 296 * Fast clean shutdown path - skips the persistance of most metadata regions and 297 * relies on their shared memory state instead. 298 */ 299 static const struct ftl_mngt_process_desc desc_fast_persist = { 300 .name = "Fast persist metadata", 301 .steps = { 302 { 303 .name = "Fast persist NV cache metadata", 304 .action = ftl_mngt_fast_persist_nv_cache_metadata, 305 }, 306 #ifdef SPDK_FTL_VSS_EMU 307 { 308 .name = "Persist VSS metadata", 309 .action = ftl_mngt_persist_vss, 310 }, 311 #endif 312 {} 313 } 314 }; 315 316 void 317 ftl_mngt_fast_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 318 { 319 ftl_mngt_call_process(mngt, &desc_fast_persist); 320 } 321 322 void 323 ftl_mngt_init_default_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 324 { 325 struct ftl_superblock *sb = dev->sb; 326 327 sb->header.magic = FTL_SUPERBLOCK_MAGIC; 328 sb->header.version = FTL_METADATA_VERSION_CURRENT; 329 sb->uuid = dev->conf.uuid; 330 sb->clean = 0; 331 dev->sb_shm->shm_clean = false; 332 333 /* Max 16 IO depth per band relocate */ 334 sb->max_reloc_qdepth = 16; 335 336 sb->overprovisioning = dev->conf.overprovisioning; 337 338 ftl_band_init_gc_iter(dev); 339 340 /* md layout isn't initialized yet. 341 * empty region list => all regions in the default location */ 342 sb->md_layout_head.type = FTL_LAYOUT_REGION_TYPE_INVALID; 343 344 sb->header.crc = get_sb_crc(sb); 345 346 ftl_mngt_next_step(mngt); 347 } 348 349 void 350 ftl_mngt_set_dirty(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 351 { 352 struct ftl_superblock *sb = dev->sb; 353 354 sb->clean = 0; 355 dev->sb_shm->shm_clean = false; 356 sb->header.crc = get_sb_crc(sb); 357 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 358 } 359 360 void 361 ftl_mngt_set_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 362 { 363 struct ftl_superblock *sb = dev->sb; 364 365 sb->clean = 1; 366 dev->sb_shm->shm_clean = false; 367 sb->header.crc = get_sb_crc(sb); 368 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 369 370 dev->sb_shm->shm_ready = false; 371 } 372 373 void 374 ftl_mngt_set_shm_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 375 { 376 struct ftl_superblock *sb = dev->sb; 377 378 sb->clean = 1; 379 dev->sb_shm->shm_clean = true; 380 sb->header.crc = get_sb_crc(sb); 381 ftl_mngt_next_step(mngt); 382 } 383 384 void 385 ftl_mngt_load_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 386 { 387 FTL_NOTICELOG(dev, "SHM: clean %"PRIu64", shm_clean %d\n", dev->sb->clean, dev->sb_shm->shm_clean); 388 389 if (!ftl_fast_startup(dev)) { 390 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 391 return; 392 } 393 394 FTL_DEBUGLOG(dev, "SHM: found SB\n"); 395 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_SB)) { 396 ftl_mngt_fail_step(mngt); 397 return; 398 } 399 ftl_mngt_next_step(mngt); 400 } 401 402 void 403 ftl_mngt_validate_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 404 { 405 struct ftl_superblock *sb = dev->sb; 406 407 if (!ftl_superblock_check_magic(sb)) { 408 FTL_ERRLOG(dev, "Invalid FTL superblock magic\n"); 409 ftl_mngt_fail_step(mngt); 410 return; 411 } 412 413 if (sb->header.crc != get_sb_crc(sb)) { 414 FTL_ERRLOG(dev, "Invalid FTL superblock CRC\n"); 415 ftl_mngt_fail_step(mngt); 416 return; 417 } 418 419 if (spdk_uuid_compare(&sb->uuid, &dev->conf.uuid) != 0) { 420 FTL_ERRLOG(dev, "Invalid FTL superblock UUID\n"); 421 ftl_mngt_fail_step(mngt); 422 return; 423 } 424 425 if (sb->lba_cnt == 0) { 426 FTL_ERRLOG(dev, "Invalid FTL superblock lba_cnt\n"); 427 ftl_mngt_fail_step(mngt); 428 return; 429 } 430 dev->num_lbas = sb->lba_cnt; 431 432 /* The sb has just been read. Validate and update the conf */ 433 if (sb->overprovisioning == 0 || sb->overprovisioning >= 100) { 434 FTL_ERRLOG(dev, "Invalid FTL superblock lba_rsvd\n"); 435 ftl_mngt_fail_step(mngt); 436 return; 437 } 438 dev->conf.overprovisioning = sb->overprovisioning; 439 440 ftl_mngt_next_step(mngt); 441 } 442 443 /* 444 * Loads and verifies superblock contents - utilized during the load of an FTL 445 * instance (both from a clean and dirty shutdown). 446 */ 447 static const struct ftl_mngt_process_desc desc_restore_sb = { 448 .name = "SB restore", 449 .steps = { 450 { 451 .name = "Load super block", 452 .action = ftl_mngt_load_sb 453 }, 454 { 455 .name = "Validate super block", 456 .action = ftl_mngt_validate_sb 457 }, 458 {} 459 } 460 }; 461 462 /* 463 * Initializes the superblock fields during first startup of FTL 464 */ 465 static const struct ftl_mngt_process_desc desc_init_sb = { 466 .name = "SB initialize", 467 .steps = { 468 { 469 .name = "Default-initialize superblock", 470 .action = ftl_mngt_init_default_sb, 471 }, 472 {} 473 } 474 }; 475 476 #ifdef SPDK_FTL_VSS_EMU 477 void 478 ftl_mngt_md_init_vss_emu(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 479 { 480 struct ftl_layout *layout = &dev->layout; 481 struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_VSS]; 482 483 /* Initialize VSS layout */ 484 ftl_layout_setup_vss_emu(dev); 485 486 /* Allocate md buf */ 487 layout->md[FTL_LAYOUT_REGION_TYPE_VSS] = ftl_md_create(dev, region->current.blocks, 488 region->vss_blksz, NULL, 0, region); 489 if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_VSS]) { 490 ftl_mngt_fail_step(mngt); 491 return; 492 } 493 ftl_mngt_next_step(mngt); 494 } 495 496 void 497 ftl_mngt_md_deinit_vss_emu(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 498 { 499 struct ftl_layout *layout = &dev->layout; 500 501 if (layout->md[FTL_LAYOUT_REGION_TYPE_VSS]) { 502 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_VSS], 0); 503 layout->md[FTL_LAYOUT_REGION_TYPE_VSS] = NULL; 504 } 505 506 ftl_mngt_next_step(mngt); 507 } 508 #endif 509 510 void 511 ftl_mngt_superblock_init(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_SB]; 515 char uuid[SPDK_UUID_STRING_LEN]; 516 int md_create_flags = ftl_md_create_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB); 517 518 /* Must generate UUID before MD create on SHM for the SB */ 519 if (dev->conf.mode & SPDK_FTL_MODE_CREATE) { 520 spdk_uuid_generate(&dev->conf.uuid); 521 spdk_uuid_fmt_lower(uuid, sizeof(uuid), &dev->conf.uuid); 522 FTL_NOTICELOG(dev, "Create new FTL, UUID %s\n", uuid); 523 } 524 525 shm_retry: 526 /* Allocate md buf */ 527 dev->sb_shm = NULL; 528 dev->sb_shm_md = ftl_md_create(dev, spdk_divide_round_up(sizeof(*dev->sb_shm), FTL_BLOCK_SIZE), 529 0, "sb_shm", 530 md_create_flags, NULL); 531 if (dev->sb_shm_md == NULL) { 532 /* The first attempt may fail when trying to open SHM - try to create new */ 533 if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) { 534 md_create_flags |= FTL_MD_CREATE_SHM_NEW; 535 goto shm_retry; 536 } 537 if (dev->sb_shm_md == NULL) { 538 ftl_mngt_fail_step(mngt); 539 return; 540 } 541 } 542 543 dev->sb_shm = ftl_md_get_buffer(dev->sb_shm_md); 544 545 /* Setup the layout of a superblock */ 546 if (ftl_layout_setup_superblock(dev)) { 547 ftl_mngt_fail_step(mngt); 548 return; 549 } 550 551 /* Allocate md buf */ 552 layout->md[FTL_LAYOUT_REGION_TYPE_SB] = ftl_md_create(dev, region->current.blocks, 553 region->vss_blksz, region->name, 554 md_create_flags, region); 555 if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB]) { 556 /* The first attempt may fail when trying to open SHM - try to create new */ 557 if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) { 558 md_create_flags |= FTL_MD_CREATE_SHM_NEW; 559 ftl_md_destroy(dev->sb_shm_md, 0); 560 goto shm_retry; 561 } 562 ftl_mngt_fail_step(mngt); 563 return; 564 } 565 566 /* Link the md buf to the device */ 567 dev->sb = ftl_md_get_buffer(layout->md[FTL_LAYOUT_REGION_TYPE_SB]); 568 569 /* Setup superblock mirror to QLC */ 570 region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB_BASE]; 571 layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = ftl_md_create(dev, region->current.blocks, 572 region->vss_blksz, NULL, FTL_MD_CREATE_HEAP, region); 573 if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) { 574 ftl_mngt_fail_step(mngt); 575 return; 576 } 577 578 /* Initialize the superblock */ 579 if (dev->conf.mode & SPDK_FTL_MODE_CREATE) { 580 ftl_mngt_call_process(mngt, &desc_init_sb); 581 } else { 582 ftl_mngt_call_process(mngt, &desc_restore_sb); 583 } 584 } 585 586 void 587 ftl_mngt_superblock_deinit(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 588 { 589 struct ftl_layout *layout = &dev->layout; 590 591 if (layout->md[FTL_LAYOUT_REGION_TYPE_SB]) { 592 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB], 593 ftl_md_destroy_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB)); 594 layout->md[FTL_LAYOUT_REGION_TYPE_SB] = NULL; 595 } 596 597 if (layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) { 598 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE], 0); 599 layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = NULL; 600 } 601 602 ftl_md_destroy(dev->sb_shm_md, ftl_md_destroy_shm_flags(dev)); 603 dev->sb_shm_md = NULL; 604 dev->sb_shm = NULL; 605 606 ftl_mngt_next_step(mngt); 607 } 608 609 static void 610 ftl_mngt_restore_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 611 { 612 if (ftl_fast_startup(dev)) { 613 FTL_DEBUGLOG(dev, "SHM: found nv cache md\n"); 614 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_NVC_MD)) { 615 ftl_mngt_fail_step(mngt); 616 return; 617 } 618 ftl_mngt_next_step(mngt); 619 return; 620 } 621 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_NVC_MD); 622 } 623 624 static void 625 ftl_mngt_restore_vld_map_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 626 { 627 if (ftl_fast_startup(dev)) { 628 FTL_DEBUGLOG(dev, "SHM: found vldmap\n"); 629 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_VALID_MAP)) { 630 ftl_mngt_fail_step(mngt); 631 return; 632 } 633 ftl_mngt_next_step(mngt); 634 return; 635 } 636 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_VALID_MAP); 637 } 638 639 static void 640 ftl_mngt_restore_band_info_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 641 { 642 if (ftl_fast_startup(dev)) { 643 FTL_DEBUGLOG(dev, "SHM: found band md\n"); 644 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_BAND_MD)) { 645 ftl_mngt_fail_step(mngt); 646 return; 647 } 648 ftl_mngt_next_step(mngt); 649 return; 650 } 651 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_BAND_MD); 652 } 653 654 655 656 #ifdef SPDK_FTL_VSS_EMU 657 static void 658 ftl_mngt_restore_vss_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 659 { 660 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_VSS); 661 } 662 #endif 663 664 /* 665 * Loads metadata after a clean shutdown. 666 */ 667 static const struct ftl_mngt_process_desc desc_restore = { 668 .name = "Restore metadata", 669 .steps = { 670 #ifdef SPDK_FTL_VSS_EMU 671 { 672 .name = "Restore VSS metadata", 673 .action = ftl_mngt_restore_vss_metadata, 674 }, 675 #endif 676 { 677 .name = "Restore NV cache metadata", 678 .action = ftl_mngt_restore_nv_cache_metadata, 679 }, 680 { 681 .name = "Restore valid map metadata", 682 .action = ftl_mngt_restore_vld_map_metadata, 683 }, 684 { 685 .name = "Restore band info metadata", 686 .action = ftl_mngt_restore_band_info_metadata, 687 }, 688 {} 689 } 690 }; 691 692 void 693 ftl_mngt_restore_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 694 { 695 ftl_mngt_call_process(mngt, &desc_restore); 696 } 697