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 dev->sb_shm->shm_clean = false; 377 sb->header.crc = get_sb_crc(sb); 378 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 379 } 380 381 void 382 ftl_mngt_set_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 383 { 384 struct ftl_superblock *sb = dev->sb; 385 386 sb->clean = 1; 387 dev->sb_shm->shm_clean = false; 388 sb->header.crc = get_sb_crc(sb); 389 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 390 391 dev->sb_shm->shm_ready = false; 392 } 393 394 void 395 ftl_mngt_set_shm_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 396 { 397 struct ftl_superblock *sb = dev->sb; 398 399 sb->clean = 1; 400 dev->sb_shm->shm_clean = true; 401 sb->header.crc = get_sb_crc(sb); 402 ftl_mngt_next_step(mngt); 403 } 404 405 void 406 ftl_mngt_load_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 407 { 408 FTL_NOTICELOG(dev, "SHM: clean %"PRIu64", shm_clean %d\n", dev->sb->clean, dev->sb_shm->shm_clean); 409 410 if (!ftl_fast_startup(dev)) { 411 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 412 return; 413 } 414 415 FTL_DEBUGLOG(dev, "SHM: found SB\n"); 416 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_SB)) { 417 ftl_mngt_fail_step(mngt); 418 return; 419 } 420 ftl_mngt_next_step(mngt); 421 } 422 423 void 424 ftl_mngt_validate_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 425 { 426 struct ftl_superblock *sb = dev->sb; 427 428 if (!ftl_superblock_check_magic(sb)) { 429 FTL_ERRLOG(dev, "Invalid FTL superblock magic\n"); 430 ftl_mngt_fail_step(mngt); 431 return; 432 } 433 434 if (sb->header.crc != get_sb_crc(sb)) { 435 FTL_ERRLOG(dev, "Invalid FTL superblock CRC\n"); 436 ftl_mngt_fail_step(mngt); 437 return; 438 } 439 440 if (ftl_superblock_upgrade(dev)) { 441 FTL_ERRLOG(dev, "FTL superblock dirty or invalid version\n"); 442 ftl_mngt_fail_step(mngt); 443 return; 444 } 445 446 if (spdk_uuid_compare(&sb->uuid, &dev->conf.uuid) != 0) { 447 FTL_ERRLOG(dev, "Invalid FTL superblock UUID\n"); 448 ftl_mngt_fail_step(mngt); 449 return; 450 } 451 452 if (sb->lba_cnt == 0) { 453 FTL_ERRLOG(dev, "Invalid FTL superblock lba_cnt\n"); 454 ftl_mngt_fail_step(mngt); 455 return; 456 } 457 dev->num_lbas = sb->lba_cnt; 458 459 /* The sb has just been read. Validate and update the conf */ 460 if (sb->overprovisioning == 0 || sb->overprovisioning >= 100) { 461 FTL_ERRLOG(dev, "Invalid FTL superblock lba_rsvd\n"); 462 ftl_mngt_fail_step(mngt); 463 return; 464 } 465 dev->conf.overprovisioning = sb->overprovisioning; 466 467 ftl_mngt_next_step(mngt); 468 } 469 470 /* 471 * Loads and verifies superblock contents - utilized during the load of an FTL 472 * instance (both from a clean and dirty shutdown). 473 */ 474 static const struct ftl_mngt_process_desc desc_restore_sb = { 475 .name = "SB restore", 476 .steps = { 477 { 478 .name = "Load super block", 479 .action = ftl_mngt_load_sb 480 }, 481 { 482 .name = "Validate super block", 483 .action = ftl_mngt_validate_sb 484 }, 485 {} 486 } 487 }; 488 489 /* 490 * Initializes the superblock fields during first startup of FTL 491 */ 492 static const struct ftl_mngt_process_desc desc_init_sb = { 493 .name = "SB initialize", 494 .steps = { 495 { 496 .name = "Default-initialize superblock", 497 .action = ftl_mngt_init_default_sb, 498 }, 499 {} 500 } 501 }; 502 503 void 504 ftl_mngt_superblock_init(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 505 { 506 struct ftl_layout *layout = &dev->layout; 507 struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB]; 508 char uuid[SPDK_UUID_STRING_LEN]; 509 int md_create_flags = ftl_md_create_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB); 510 511 /* Must generate UUID before MD create on SHM for the SB */ 512 if (dev->conf.mode & SPDK_FTL_MODE_CREATE) { 513 spdk_uuid_generate(&dev->conf.uuid); 514 spdk_uuid_fmt_lower(uuid, sizeof(uuid), &dev->conf.uuid); 515 FTL_NOTICELOG(dev, "Create new FTL, UUID %s\n", uuid); 516 } 517 518 shm_retry: 519 /* Allocate md buf */ 520 dev->sb_shm = NULL; 521 dev->sb_shm_md = ftl_md_create(dev, spdk_divide_round_up(sizeof(*dev->sb_shm), FTL_BLOCK_SIZE), 522 0, "sb_shm", 523 md_create_flags, NULL); 524 if (dev->sb_shm_md == NULL) { 525 /* The first attempt may fail when trying to open SHM - try to create new */ 526 if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) { 527 md_create_flags |= FTL_MD_CREATE_SHM_NEW; 528 goto shm_retry; 529 } 530 if (dev->sb_shm_md == NULL) { 531 ftl_mngt_fail_step(mngt); 532 return; 533 } 534 } 535 536 dev->sb_shm = ftl_md_get_buffer(dev->sb_shm_md); 537 538 /* Setup the layout of a superblock */ 539 if (ftl_layout_setup_superblock(dev)) { 540 ftl_mngt_fail_step(mngt); 541 return; 542 } 543 544 /* Allocate md buf */ 545 layout->md[FTL_LAYOUT_REGION_TYPE_SB] = ftl_md_create(dev, region->current.blocks, 546 region->vss_blksz, region->name, 547 md_create_flags, region); 548 if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB]) { 549 /* The first attempt may fail when trying to open SHM - try to create new */ 550 if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) { 551 md_create_flags |= FTL_MD_CREATE_SHM_NEW; 552 ftl_md_destroy(dev->sb_shm_md, 0); 553 dev->sb_shm_md = NULL; 554 goto shm_retry; 555 } 556 ftl_mngt_fail_step(mngt); 557 return; 558 } 559 560 /* Link the md buf to the device */ 561 dev->sb = ftl_md_get_buffer(layout->md[FTL_LAYOUT_REGION_TYPE_SB]); 562 563 /* Setup superblock mirror to QLC */ 564 region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB_BASE]; 565 layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = ftl_md_create(dev, region->current.blocks, 566 region->vss_blksz, NULL, FTL_MD_CREATE_HEAP, region); 567 if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) { 568 ftl_mngt_fail_step(mngt); 569 return; 570 } 571 572 /* Initialize the superblock */ 573 if (dev->conf.mode & SPDK_FTL_MODE_CREATE) { 574 ftl_mngt_call_process(mngt, &desc_init_sb); 575 } else { 576 ftl_mngt_call_process(mngt, &desc_restore_sb); 577 } 578 } 579 580 void 581 ftl_mngt_superblock_deinit(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 582 { 583 struct ftl_layout *layout = &dev->layout; 584 585 if (layout->md[FTL_LAYOUT_REGION_TYPE_SB]) { 586 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB], 587 ftl_md_destroy_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB)); 588 layout->md[FTL_LAYOUT_REGION_TYPE_SB] = NULL; 589 } 590 591 if (layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) { 592 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE], 0); 593 layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = NULL; 594 } 595 596 ftl_md_destroy(dev->sb_shm_md, ftl_md_destroy_shm_flags(dev)); 597 dev->sb_shm_md = NULL; 598 dev->sb_shm = NULL; 599 600 ftl_mngt_next_step(mngt); 601 } 602 603 static void 604 ftl_mngt_restore_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 605 { 606 if (ftl_fast_startup(dev)) { 607 FTL_DEBUGLOG(dev, "SHM: found nv cache md\n"); 608 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_NVC_MD)) { 609 ftl_mngt_fail_step(mngt); 610 return; 611 } 612 ftl_mngt_next_step(mngt); 613 return; 614 } 615 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_NVC_MD); 616 } 617 618 static void 619 ftl_mngt_restore_vld_map_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 620 { 621 if (ftl_fast_startup(dev)) { 622 FTL_DEBUGLOG(dev, "SHM: found vldmap\n"); 623 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_VALID_MAP)) { 624 ftl_mngt_fail_step(mngt); 625 return; 626 } 627 ftl_mngt_next_step(mngt); 628 return; 629 } 630 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_VALID_MAP); 631 } 632 633 static void 634 ftl_mngt_restore_band_info_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 635 { 636 if (ftl_fast_startup(dev)) { 637 FTL_DEBUGLOG(dev, "SHM: found band md\n"); 638 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_BAND_MD)) { 639 ftl_mngt_fail_step(mngt); 640 return; 641 } 642 ftl_mngt_next_step(mngt); 643 return; 644 } 645 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_BAND_MD); 646 } 647 648 static void 649 ftl_mngt_restore_trim_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 650 { 651 if (ftl_fast_startup(dev)) { 652 FTL_DEBUGLOG(dev, "SHM: found trim md\n"); 653 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_TRIM_MD)) { 654 ftl_mngt_fail_step(mngt); 655 return; 656 } 657 ftl_mngt_next_step(mngt); 658 return; 659 } 660 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_TRIM_MD); 661 } 662 663 /* 664 * Loads metadata after a clean shutdown. 665 */ 666 static const struct ftl_mngt_process_desc desc_restore = { 667 .name = "Restore metadata", 668 .steps = { 669 { 670 .name = "Restore NV cache metadata", 671 .action = ftl_mngt_restore_nv_cache_metadata, 672 }, 673 { 674 .name = "Restore valid map metadata", 675 .action = ftl_mngt_restore_vld_map_metadata, 676 }, 677 { 678 .name = "Restore band info metadata", 679 .action = ftl_mngt_restore_band_info_metadata, 680 }, 681 { 682 .name = "Restore trim metadata", 683 .action = ftl_mngt_restore_trim_metadata, 684 }, 685 {} 686 } 687 }; 688 689 void 690 ftl_mngt_restore_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 691 { 692 ftl_mngt_call_process(mngt, &desc_restore); 693 } 694 695 void 696 ftl_mngt_persist_superblock(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 697 { 698 dev->sb->header.crc = get_sb_crc(dev->sb); 699 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 700 } 701