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