1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2023 Solidigm All Rights Reserved 3 * Copyright (C) 2022 Intel Corporation. 4 * All rights reserved. 5 */ 6 7 #include "spdk/thread.h" 8 #include "spdk/crc32.h" 9 10 #include "ftl_core.h" 11 #include "ftl_mngt.h" 12 #include "ftl_mngt_steps.h" 13 #include "ftl_utils.h" 14 #include "ftl_band.h" 15 #include "ftl_internal.h" 16 #include "ftl_sb.h" 17 #include "upgrade/ftl_layout_upgrade.h" 18 #include "upgrade/ftl_sb_upgrade.h" 19 20 void 21 ftl_mngt_init_layout(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 22 { 23 if (ftl_layout_setup(dev)) { 24 ftl_mngt_fail_step(mngt); 25 } else { 26 ftl_mngt_next_step(mngt); 27 } 28 } 29 30 static bool 31 is_buffer_needed(enum ftl_layout_region_type type) 32 { 33 switch (type) { 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 if (sb->header.version > FTL_SB_VERSION_2) { 258 /* whole buf for v3 and on: */ 259 size = FTL_SUPERBLOCK_SIZE - offset - sizeof(sb->header.crc); 260 crc = spdk_crc32c_update(buffer, size, crc); 261 } else { 262 /* special for sb v2 only: */ 263 size = sizeof(struct ftl_superblock_v2) - offset - sizeof(sb->header.crc); 264 sb->header.crc = spdk_crc32c_update(buffer, size, crc); 265 } 266 267 return crc; 268 } 269 270 static void 271 ftl_mngt_persist_super_block(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 272 { 273 dev->sb->overprovisioning = dev->conf.overprovisioning; 274 dev->sb->gc_info = dev->sb_shm->gc_info; 275 dev->sb->header.crc = get_sb_crc(dev->sb); 276 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 277 } 278 279 /* 280 * Persists all necessary metadata (band state, P2L, etc) during FTL's clean shutdown. 281 */ 282 static const struct ftl_mngt_process_desc desc_persist = { 283 .name = "Persist metadata", 284 .steps = { 285 { 286 .name = "Persist NV cache metadata", 287 .action = ftl_mngt_persist_nv_cache_metadata, 288 }, 289 { 290 .name = "Persist valid map metadata", 291 .action = ftl_mngt_persist_vld_map_metadata, 292 }, 293 { 294 .name = "Persist P2L metadata", 295 .action = ftl_mngt_persist_p2l_metadata, 296 .ctx_size = sizeof(struct ftl_p2l_sync_ctx), 297 }, 298 { 299 .name = "persist band info metadata", 300 .action = ftl_mngt_persist_band_info_metadata, 301 }, 302 { 303 .name = "persist trim metadata", 304 .action = ftl_mngt_persist_trim_metadata, 305 }, 306 { 307 .name = "Persist superblock", 308 .action = ftl_mngt_persist_super_block, 309 }, 310 {} 311 } 312 }; 313 314 void 315 ftl_mngt_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 316 { 317 ftl_mngt_call_process(mngt, &desc_persist); 318 } 319 320 /* 321 * Fast clean shutdown path - skips the persistence of most metadata regions and 322 * relies on their shared memory state instead. 323 */ 324 static const struct ftl_mngt_process_desc desc_fast_persist = { 325 .name = "Fast persist metadata", 326 .steps = { 327 { 328 .name = "Fast persist NV cache metadata", 329 .action = ftl_mngt_fast_persist_nv_cache_metadata, 330 }, 331 {} 332 } 333 }; 334 335 void 336 ftl_mngt_fast_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 337 { 338 ftl_mngt_call_process(mngt, &desc_fast_persist); 339 } 340 341 void 342 ftl_mngt_init_default_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 343 { 344 struct ftl_superblock *sb = dev->sb; 345 346 sb->header.magic = FTL_SUPERBLOCK_MAGIC; 347 sb->header.version = FTL_SB_VERSION_CURRENT; 348 sb->uuid = dev->conf.uuid; 349 sb->clean = 0; 350 dev->sb_shm->shm_clean = false; 351 sb->ckpt_seq_id = 0; 352 353 /* Max 16 IO depth per band relocate */ 354 sb->max_reloc_qdepth = 16; 355 356 sb->overprovisioning = dev->conf.overprovisioning; 357 358 ftl_band_init_gc_iter(dev); 359 360 /* md layout isn't initialized yet. 361 * empty region list => all regions in the default location */ 362 sb->md_layout_head.type = FTL_LAYOUT_REGION_TYPE_INVALID; 363 sb->md_layout_head.df_next = FTL_DF_OBJ_ID_INVALID; 364 365 sb->header.crc = get_sb_crc(sb); 366 367 ftl_mngt_next_step(mngt); 368 } 369 370 void 371 ftl_mngt_set_dirty(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 372 { 373 struct ftl_superblock *sb = dev->sb; 374 375 sb->clean = 0; 376 sb->upgrade_ready = false; 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 sb->upgrade_ready = dev->conf.prep_upgrade_on_shutdown; 389 dev->sb_shm->shm_clean = false; 390 sb->header.crc = get_sb_crc(sb); 391 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 392 393 dev->sb_shm->shm_ready = false; 394 } 395 396 void 397 ftl_mngt_set_shm_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 398 { 399 struct ftl_superblock *sb = dev->sb; 400 401 sb->clean = 1; 402 dev->sb_shm->shm_clean = true; 403 sb->header.crc = get_sb_crc(sb); 404 ftl_mngt_next_step(mngt); 405 } 406 407 void 408 ftl_mngt_load_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 409 { 410 FTL_NOTICELOG(dev, "SHM: clean %"PRIu64", shm_clean %d\n", dev->sb->clean, dev->sb_shm->shm_clean); 411 412 if (!ftl_fast_startup(dev)) { 413 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 414 return; 415 } 416 417 FTL_DEBUGLOG(dev, "SHM: found SB\n"); 418 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_SB)) { 419 ftl_mngt_fail_step(mngt); 420 return; 421 } 422 ftl_mngt_next_step(mngt); 423 } 424 425 void 426 ftl_mngt_validate_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 427 { 428 struct ftl_superblock *sb = dev->sb; 429 430 if (!ftl_superblock_check_magic(sb)) { 431 FTL_ERRLOG(dev, "Invalid FTL superblock magic\n"); 432 ftl_mngt_fail_step(mngt); 433 return; 434 } 435 436 if (sb->header.crc != get_sb_crc(sb)) { 437 FTL_ERRLOG(dev, "Invalid FTL superblock CRC\n"); 438 ftl_mngt_fail_step(mngt); 439 return; 440 } 441 442 if (ftl_superblock_upgrade(dev)) { 443 FTL_ERRLOG(dev, "FTL superblock dirty or invalid version\n"); 444 ftl_mngt_fail_step(mngt); 445 return; 446 } 447 448 if (spdk_uuid_compare(&sb->uuid, &dev->conf.uuid) != 0) { 449 FTL_ERRLOG(dev, "Invalid FTL superblock UUID\n"); 450 ftl_mngt_fail_step(mngt); 451 return; 452 } 453 454 if (sb->lba_cnt == 0) { 455 FTL_ERRLOG(dev, "Invalid FTL superblock lba_cnt\n"); 456 ftl_mngt_fail_step(mngt); 457 return; 458 } 459 dev->num_lbas = sb->lba_cnt; 460 461 /* The sb has just been read. Validate and update the conf */ 462 if (sb->overprovisioning == 0 || sb->overprovisioning >= 100) { 463 FTL_ERRLOG(dev, "Invalid FTL superblock lba_rsvd\n"); 464 ftl_mngt_fail_step(mngt); 465 return; 466 } 467 dev->conf.overprovisioning = sb->overprovisioning; 468 469 ftl_mngt_next_step(mngt); 470 } 471 472 /* 473 * Loads and verifies superblock contents - utilized during the load of an FTL 474 * instance (both from a clean and dirty shutdown). 475 */ 476 static const struct ftl_mngt_process_desc desc_restore_sb = { 477 .name = "SB restore", 478 .steps = { 479 { 480 .name = "Load super block", 481 .action = ftl_mngt_load_sb 482 }, 483 { 484 .name = "Validate super block", 485 .action = ftl_mngt_validate_sb 486 }, 487 {} 488 } 489 }; 490 491 /* 492 * Initializes the superblock fields during first startup of FTL 493 */ 494 static const struct ftl_mngt_process_desc desc_init_sb = { 495 .name = "SB initialize", 496 .steps = { 497 { 498 .name = "Default-initialize superblock", 499 .action = ftl_mngt_init_default_sb, 500 }, 501 {} 502 } 503 }; 504 505 void 506 ftl_mngt_superblock_init(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 507 { 508 struct ftl_layout *layout = &dev->layout; 509 struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB]; 510 char uuid[SPDK_UUID_STRING_LEN]; 511 int md_create_flags = ftl_md_create_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB); 512 513 /* Must generate UUID before MD create on SHM for the SB */ 514 if (dev->conf.mode & SPDK_FTL_MODE_CREATE) { 515 spdk_uuid_generate(&dev->conf.uuid); 516 spdk_uuid_fmt_lower(uuid, sizeof(uuid), &dev->conf.uuid); 517 FTL_NOTICELOG(dev, "Create new FTL, UUID %s\n", uuid); 518 } 519 520 shm_retry: 521 /* Allocate md buf */ 522 dev->sb_shm = NULL; 523 dev->sb_shm_md = ftl_md_create(dev, spdk_divide_round_up(sizeof(*dev->sb_shm), FTL_BLOCK_SIZE), 524 0, "sb_shm", 525 md_create_flags, NULL); 526 if (dev->sb_shm_md == NULL) { 527 /* The first attempt may fail when trying to open SHM - try to create new */ 528 if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) { 529 md_create_flags |= FTL_MD_CREATE_SHM_NEW; 530 goto shm_retry; 531 } 532 if (dev->sb_shm_md == NULL) { 533 ftl_mngt_fail_step(mngt); 534 return; 535 } 536 } 537 538 dev->sb_shm = ftl_md_get_buffer(dev->sb_shm_md); 539 540 /* Setup the layout of a superblock */ 541 if (ftl_layout_setup_superblock(dev)) { 542 ftl_mngt_fail_step(mngt); 543 return; 544 } 545 546 /* Allocate md buf */ 547 layout->md[FTL_LAYOUT_REGION_TYPE_SB] = ftl_md_create(dev, region->current.blocks, 548 region->vss_blksz, region->name, 549 md_create_flags, region); 550 if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB]) { 551 /* The first attempt may fail when trying to open SHM - try to create new */ 552 if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) { 553 md_create_flags |= FTL_MD_CREATE_SHM_NEW; 554 ftl_md_destroy(dev->sb_shm_md, 0); 555 dev->sb_shm_md = NULL; 556 goto shm_retry; 557 } 558 ftl_mngt_fail_step(mngt); 559 return; 560 } 561 562 /* Link the md buf to the device */ 563 dev->sb = ftl_md_get_buffer(layout->md[FTL_LAYOUT_REGION_TYPE_SB]); 564 565 /* Setup superblock mirror to QLC */ 566 region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB_BASE]; 567 layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = ftl_md_create(dev, region->current.blocks, 568 region->vss_blksz, NULL, FTL_MD_CREATE_HEAP, region); 569 if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) { 570 ftl_mngt_fail_step(mngt); 571 return; 572 } 573 574 /* Initialize the superblock */ 575 if (dev->conf.mode & SPDK_FTL_MODE_CREATE) { 576 ftl_mngt_call_process(mngt, &desc_init_sb); 577 } else { 578 ftl_mngt_call_process(mngt, &desc_restore_sb); 579 } 580 } 581 582 void 583 ftl_mngt_superblock_deinit(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 584 { 585 struct ftl_layout *layout = &dev->layout; 586 587 if (layout->md[FTL_LAYOUT_REGION_TYPE_SB]) { 588 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB], 589 ftl_md_destroy_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB)); 590 layout->md[FTL_LAYOUT_REGION_TYPE_SB] = NULL; 591 } 592 593 if (layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) { 594 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE], 0); 595 layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = NULL; 596 } 597 598 ftl_md_destroy(dev->sb_shm_md, ftl_md_destroy_shm_flags(dev)); 599 dev->sb_shm_md = NULL; 600 dev->sb_shm = NULL; 601 602 ftl_mngt_next_step(mngt); 603 } 604 605 static void 606 ftl_mngt_restore_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 607 { 608 if (ftl_fast_startup(dev)) { 609 FTL_DEBUGLOG(dev, "SHM: found nv cache md\n"); 610 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_NVC_MD)) { 611 ftl_mngt_fail_step(mngt); 612 return; 613 } 614 ftl_mngt_next_step(mngt); 615 return; 616 } 617 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_NVC_MD); 618 } 619 620 static void 621 ftl_mngt_restore_vld_map_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 622 { 623 if (ftl_fast_startup(dev)) { 624 FTL_DEBUGLOG(dev, "SHM: found vldmap\n"); 625 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_VALID_MAP)) { 626 ftl_mngt_fail_step(mngt); 627 return; 628 } 629 ftl_mngt_next_step(mngt); 630 return; 631 } 632 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_VALID_MAP); 633 } 634 635 static void 636 ftl_mngt_restore_band_info_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 637 { 638 if (ftl_fast_startup(dev)) { 639 FTL_DEBUGLOG(dev, "SHM: found band md\n"); 640 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_BAND_MD)) { 641 ftl_mngt_fail_step(mngt); 642 return; 643 } 644 ftl_mngt_next_step(mngt); 645 return; 646 } 647 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_BAND_MD); 648 } 649 650 static void 651 ftl_mngt_restore_trim_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 652 { 653 if (ftl_fast_startup(dev)) { 654 FTL_DEBUGLOG(dev, "SHM: found trim md\n"); 655 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_TRIM_MD)) { 656 ftl_mngt_fail_step(mngt); 657 return; 658 } 659 ftl_mngt_next_step(mngt); 660 return; 661 } 662 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_TRIM_MD); 663 } 664 665 /* 666 * Loads metadata after a clean shutdown. 667 */ 668 static const struct ftl_mngt_process_desc desc_restore = { 669 .name = "Restore metadata", 670 .steps = { 671 { 672 .name = "Restore NV cache metadata", 673 .action = ftl_mngt_restore_nv_cache_metadata, 674 }, 675 { 676 .name = "Restore valid map metadata", 677 .action = ftl_mngt_restore_vld_map_metadata, 678 }, 679 { 680 .name = "Restore band info metadata", 681 .action = ftl_mngt_restore_band_info_metadata, 682 }, 683 { 684 .name = "Restore trim metadata", 685 .action = ftl_mngt_restore_trim_metadata, 686 }, 687 {} 688 } 689 }; 690 691 void 692 ftl_mngt_restore_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 693 { 694 ftl_mngt_call_process(mngt, &desc_restore); 695 } 696 697 void 698 ftl_mngt_persist_superblock(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 699 { 700 dev->sb->header.crc = get_sb_crc(dev->sb); 701 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 702 } 703