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