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