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