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