12b5bba56SArtur Paszkiewicz /* SPDX-License-Identifier: BSD-3-Clause 217cf101bSMateusz Kozlowski * Copyright 2023 Solidigm All Rights Reserved 3a6dbe372Spaul luse * Copyright (C) 2022 Intel Corporation. 42b5bba56SArtur Paszkiewicz * All rights reserved. 52b5bba56SArtur Paszkiewicz */ 62b5bba56SArtur Paszkiewicz 72b5bba56SArtur Paszkiewicz #include "spdk/thread.h" 82b5bba56SArtur Paszkiewicz #include "spdk/crc32.h" 99f42898aSLukasz Lasek #include "spdk/string.h" 102b5bba56SArtur Paszkiewicz 112b5bba56SArtur Paszkiewicz #include "ftl_core.h" 122b5bba56SArtur Paszkiewicz #include "ftl_mngt.h" 132b5bba56SArtur Paszkiewicz #include "ftl_mngt_steps.h" 142b5bba56SArtur Paszkiewicz #include "ftl_utils.h" 156448f336SArtur Paszkiewicz #include "ftl_band.h" 162b5bba56SArtur Paszkiewicz #include "ftl_internal.h" 17c6880a39SArtur Paszkiewicz #include "ftl_sb.h" 189f42898aSLukasz Lasek #include "base/ftl_base_dev.h" 199f42898aSLukasz Lasek #include "nvc/ftl_nvc_dev.h" 207ff28519SKozlowski Mateusz #include "upgrade/ftl_layout_upgrade.h" 21c8ab874dSKozlowski Mateusz #include "upgrade/ftl_sb_upgrade.h" 222b5bba56SArtur Paszkiewicz 232b5bba56SArtur Paszkiewicz void 242b5bba56SArtur Paszkiewicz ftl_mngt_init_layout(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 252b5bba56SArtur Paszkiewicz { 262b5bba56SArtur Paszkiewicz if (ftl_layout_setup(dev)) { 272b5bba56SArtur Paszkiewicz ftl_mngt_fail_step(mngt); 282b5bba56SArtur Paszkiewicz } else { 292b5bba56SArtur Paszkiewicz ftl_mngt_next_step(mngt); 302b5bba56SArtur Paszkiewicz } 312b5bba56SArtur Paszkiewicz } 327a7ac2afSArtur Paszkiewicz 337a7ac2afSArtur Paszkiewicz static bool 347a7ac2afSArtur Paszkiewicz is_buffer_needed(enum ftl_layout_region_type type) 357a7ac2afSArtur Paszkiewicz { 367a7ac2afSArtur Paszkiewicz switch (type) { 37c6880a39SArtur Paszkiewicz case FTL_LAYOUT_REGION_TYPE_SB: 38c6880a39SArtur Paszkiewicz case FTL_LAYOUT_REGION_TYPE_SB_BASE: 397a7ac2afSArtur Paszkiewicz case FTL_LAYOUT_REGION_TYPE_DATA_NVC: 407a7ac2afSArtur Paszkiewicz case FTL_LAYOUT_REGION_TYPE_DATA_BASE: 41a68a12a4SKozlowski Mateusz case FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR: 426448f336SArtur Paszkiewicz case FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR: 43b4b70e83SKozlowski Mateusz #ifndef SPDK_FTL_L2P_FLAT 44b4b70e83SKozlowski Mateusz case FTL_LAYOUT_REGION_TYPE_L2P: 45b4b70e83SKozlowski Mateusz #endif 4678c3cbf4SArtur Paszkiewicz case FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR: 472d613454SMateusz Kozlowski case FTL_LAYOUT_REGION_TYPE_TRIM_LOG_MIRROR: 48*6d6179ffSMateusz Kozlowski case FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MIN: 49*6d6179ffSMateusz Kozlowski case FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MAX: 507a7ac2afSArtur Paszkiewicz return false; 517a7ac2afSArtur Paszkiewicz 527a7ac2afSArtur Paszkiewicz default: 537a7ac2afSArtur Paszkiewicz return true; 547a7ac2afSArtur Paszkiewicz } 557a7ac2afSArtur Paszkiewicz } 567a7ac2afSArtur Paszkiewicz 577a7ac2afSArtur Paszkiewicz void 587a7ac2afSArtur Paszkiewicz ftl_mngt_init_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 597a7ac2afSArtur Paszkiewicz { 607a7ac2afSArtur Paszkiewicz struct ftl_layout *layout = &dev->layout; 619f42898aSLukasz Lasek struct ftl_layout_region *region; 62522a0c82SLukasz Lasek struct ftl_md *md, *md_mirror; 639f42898aSLukasz Lasek enum ftl_layout_region_type i; 64818b9c05SArtur Paszkiewicz int md_flags; 657a7ac2afSArtur Paszkiewicz 669f42898aSLukasz Lasek for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++) { 679f42898aSLukasz Lasek region = ftl_layout_region_get(dev, i); 689f42898aSLukasz Lasek if (!region) { 699f42898aSLukasz Lasek continue; 709f42898aSLukasz Lasek } 71522a0c82SLukasz Lasek assert(i == region->type); 727a7ac2afSArtur Paszkiewicz if (layout->md[i]) { 737a7ac2afSArtur Paszkiewicz /* 747a7ac2afSArtur Paszkiewicz * Some metadata objects are initialized by other FTL 757a7ac2afSArtur Paszkiewicz * components. At the moment it's only used by superblock (and its mirror) - 767a7ac2afSArtur Paszkiewicz * during load time we need to read it earlier in order to get the layout for the 777a7ac2afSArtur Paszkiewicz * other regions. 787a7ac2afSArtur Paszkiewicz */ 797a7ac2afSArtur Paszkiewicz continue; 807a7ac2afSArtur Paszkiewicz } 81811a027eSKozlowski Mateusz md_flags = is_buffer_needed(i) ? ftl_md_create_region_flags(dev, 82811a027eSKozlowski Mateusz region->type) : FTL_MD_CREATE_NO_MEM; 837a7ac2afSArtur Paszkiewicz layout->md[i] = ftl_md_create(dev, region->current.blocks, region->vss_blksz, region->name, 84818b9c05SArtur Paszkiewicz md_flags, region); 857a7ac2afSArtur Paszkiewicz if (NULL == layout->md[i]) { 867a7ac2afSArtur Paszkiewicz ftl_mngt_fail_step(mngt); 877a7ac2afSArtur Paszkiewicz return; 887a7ac2afSArtur Paszkiewicz } 897a7ac2afSArtur Paszkiewicz } 907a7ac2afSArtur Paszkiewicz 91522a0c82SLukasz Lasek /* Initialize mirror regions */ 929f42898aSLukasz Lasek for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++) { 939f42898aSLukasz Lasek region = ftl_layout_region_get(dev, i); 949f42898aSLukasz Lasek if (!region) { 959f42898aSLukasz Lasek continue; 969f42898aSLukasz Lasek } 97522a0c82SLukasz Lasek assert(i == region->type); 98522a0c82SLukasz Lasek if (region->mirror_type != FTL_LAYOUT_REGION_TYPE_INVALID && 99522a0c82SLukasz Lasek !is_buffer_needed(region->mirror_type)) { 100522a0c82SLukasz Lasek md = layout->md[i]; 101522a0c82SLukasz Lasek md_mirror = layout->md[region->mirror_type]; 102522a0c82SLukasz Lasek 103522a0c82SLukasz Lasek md_mirror->dev = md->dev; 104522a0c82SLukasz Lasek md_mirror->data_blocks = md->data_blocks; 105522a0c82SLukasz Lasek md_mirror->data = md->data; 106522a0c82SLukasz Lasek if (md_mirror->region->vss_blksz == md->region->vss_blksz) { 107522a0c82SLukasz Lasek md_mirror->vss_data = md->vss_data; 108522a0c82SLukasz Lasek } 1099f42898aSLukasz Lasek md_mirror->region = ftl_layout_region_get(dev, region->mirror_type); 1109f42898aSLukasz Lasek ftl_bug(md_mirror->region == NULL); 111522a0c82SLukasz Lasek md_mirror->is_mirror = true; 112522a0c82SLukasz Lasek } 113522a0c82SLukasz Lasek } 114522a0c82SLukasz Lasek 1157a7ac2afSArtur Paszkiewicz ftl_mngt_next_step(mngt); 1167a7ac2afSArtur Paszkiewicz } 1177a7ac2afSArtur Paszkiewicz 1187a7ac2afSArtur Paszkiewicz void 1197a7ac2afSArtur Paszkiewicz ftl_mngt_deinit_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 1207a7ac2afSArtur Paszkiewicz { 1217a7ac2afSArtur Paszkiewicz struct ftl_layout *layout = &dev->layout; 1229f42898aSLukasz Lasek struct ftl_layout_region *region; 1239f42898aSLukasz Lasek enum ftl_layout_region_type i; 1247a7ac2afSArtur Paszkiewicz 1259f42898aSLukasz Lasek for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++) { 1269f42898aSLukasz Lasek region = ftl_layout_region_get(dev, i); 1279f42898aSLukasz Lasek if (!region) { 1289f42898aSLukasz Lasek continue; 1299f42898aSLukasz Lasek } 1307a7ac2afSArtur Paszkiewicz if (layout->md[i]) { 1319f42898aSLukasz Lasek ftl_md_destroy(layout->md[i], ftl_md_destroy_region_flags(dev, region->type)); 1327a7ac2afSArtur Paszkiewicz layout->md[i] = NULL; 1337a7ac2afSArtur Paszkiewicz } 1347a7ac2afSArtur Paszkiewicz } 1357a7ac2afSArtur Paszkiewicz 1367a7ac2afSArtur Paszkiewicz ftl_mngt_next_step(mngt); 1377a7ac2afSArtur Paszkiewicz } 138f725ca81SArtur Paszkiewicz 139c6880a39SArtur Paszkiewicz static void 140c6880a39SArtur Paszkiewicz persist_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status) 141c6880a39SArtur Paszkiewicz { 142c6880a39SArtur Paszkiewicz struct ftl_mngt_process *mngt = md->owner.cb_ctx; 143c6880a39SArtur Paszkiewicz 144c6880a39SArtur Paszkiewicz if (status) { 145c6880a39SArtur Paszkiewicz ftl_mngt_fail_step(mngt); 146c6880a39SArtur Paszkiewicz } else { 147c6880a39SArtur Paszkiewicz ftl_mngt_next_step(mngt); 148c6880a39SArtur Paszkiewicz } 149c6880a39SArtur Paszkiewicz } 150c6880a39SArtur Paszkiewicz 151c6880a39SArtur Paszkiewicz static void 152c6880a39SArtur Paszkiewicz persist(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt, 153c6880a39SArtur Paszkiewicz enum ftl_layout_region_type type) 154c6880a39SArtur Paszkiewicz { 155c6880a39SArtur Paszkiewicz struct ftl_layout *layout = &dev->layout; 1560c980660SGangCao struct ftl_md *md; 157c6880a39SArtur Paszkiewicz 158c6880a39SArtur Paszkiewicz assert(type < FTL_LAYOUT_REGION_TYPE_MAX); 159c6880a39SArtur Paszkiewicz 1600c980660SGangCao md = layout->md[type]; 161c6880a39SArtur Paszkiewicz if (!md) { 162c6880a39SArtur Paszkiewicz ftl_mngt_fail_step(mngt); 163c6880a39SArtur Paszkiewicz return; 164c6880a39SArtur Paszkiewicz } 165c6880a39SArtur Paszkiewicz 166c6880a39SArtur Paszkiewicz md->owner.cb_ctx = mngt; 167c6880a39SArtur Paszkiewicz md->cb = persist_cb; 168c6880a39SArtur Paszkiewicz ftl_md_persist(md); 169c6880a39SArtur Paszkiewicz } 170c6880a39SArtur Paszkiewicz 171cbd7ae6dSKozlowski Mateusz static int 172cbd7ae6dSKozlowski Mateusz ftl_md_restore_region(struct spdk_ftl_dev *dev, int region_type) 173cbd7ae6dSKozlowski Mateusz { 174cbd7ae6dSKozlowski Mateusz int status = 0; 175cbd7ae6dSKozlowski Mateusz switch (region_type) { 176cbd7ae6dSKozlowski Mateusz case FTL_LAYOUT_REGION_TYPE_NVC_MD: 177cbd7ae6dSKozlowski Mateusz status = ftl_nv_cache_load_state(&dev->nv_cache); 178cbd7ae6dSKozlowski Mateusz break; 179cbd7ae6dSKozlowski Mateusz case FTL_LAYOUT_REGION_TYPE_VALID_MAP: 180cbd7ae6dSKozlowski Mateusz ftl_valid_map_load_state(dev); 181cbd7ae6dSKozlowski Mateusz break; 182cbd7ae6dSKozlowski Mateusz case FTL_LAYOUT_REGION_TYPE_BAND_MD: 183cb00e90aSMateusz Kozlowski status = ftl_bands_load_state(dev); 184cbd7ae6dSKozlowski Mateusz break; 185cbd7ae6dSKozlowski Mateusz default: 186cbd7ae6dSKozlowski Mateusz break; 187cbd7ae6dSKozlowski Mateusz } 188cbd7ae6dSKozlowski Mateusz return status; 189cbd7ae6dSKozlowski Mateusz } 190cbd7ae6dSKozlowski Mateusz 191cbd7ae6dSKozlowski Mateusz static void 192cbd7ae6dSKozlowski Mateusz restore_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status) 193cbd7ae6dSKozlowski Mateusz { 194cbd7ae6dSKozlowski Mateusz struct ftl_mngt_process *mngt = md->owner.cb_ctx; 195cbd7ae6dSKozlowski Mateusz const struct ftl_layout_region *region = ftl_md_get_region(md); 196cbd7ae6dSKozlowski Mateusz 197cbd7ae6dSKozlowski Mateusz if (status) { 198cbd7ae6dSKozlowski Mateusz /* Restore error, end step */ 199cbd7ae6dSKozlowski Mateusz ftl_mngt_fail_step(mngt); 200cbd7ae6dSKozlowski Mateusz return; 201cbd7ae6dSKozlowski Mateusz } 202cbd7ae6dSKozlowski Mateusz 203cbd7ae6dSKozlowski Mateusz assert(region); 204cbd7ae6dSKozlowski Mateusz status = ftl_md_restore_region(dev, region->type); 205cbd7ae6dSKozlowski Mateusz 206cbd7ae6dSKozlowski Mateusz if (status) { 207cbd7ae6dSKozlowski Mateusz ftl_mngt_fail_step(mngt); 208cbd7ae6dSKozlowski Mateusz } else { 209cbd7ae6dSKozlowski Mateusz ftl_mngt_next_step(mngt); 210cbd7ae6dSKozlowski Mateusz } 211cbd7ae6dSKozlowski Mateusz } 212cbd7ae6dSKozlowski Mateusz 213cbd7ae6dSKozlowski Mateusz static void 214cbd7ae6dSKozlowski Mateusz restore(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt, enum ftl_layout_region_type type) 215cbd7ae6dSKozlowski Mateusz { 216cbd7ae6dSKozlowski Mateusz struct ftl_layout *layout = &dev->layout; 217cbd7ae6dSKozlowski Mateusz assert(type < FTL_LAYOUT_REGION_TYPE_MAX); 218cbd7ae6dSKozlowski Mateusz struct ftl_md *md = layout->md[type]; 219cbd7ae6dSKozlowski Mateusz 220cbd7ae6dSKozlowski Mateusz if (!md) { 221cbd7ae6dSKozlowski Mateusz ftl_mngt_fail_step(mngt); 222cbd7ae6dSKozlowski Mateusz return; 223cbd7ae6dSKozlowski Mateusz } 224cbd7ae6dSKozlowski Mateusz 225cbd7ae6dSKozlowski Mateusz md->owner.cb_ctx = mngt; 226cbd7ae6dSKozlowski Mateusz md->cb = restore_cb; 227cbd7ae6dSKozlowski Mateusz ftl_md_restore(md); 228cbd7ae6dSKozlowski Mateusz } 229cbd7ae6dSKozlowski Mateusz 230506315a6SKozlowski Mateusz void 231506315a6SKozlowski Mateusz ftl_mngt_persist_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 232506315a6SKozlowski Mateusz { 233506315a6SKozlowski Mateusz if (ftl_nv_cache_save_state(&dev->nv_cache)) { 234506315a6SKozlowski Mateusz ftl_mngt_fail_step(mngt); 235506315a6SKozlowski Mateusz return; 236506315a6SKozlowski Mateusz } 237506315a6SKozlowski Mateusz 238506315a6SKozlowski Mateusz persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_NVC_MD); 239506315a6SKozlowski Mateusz } 240506315a6SKozlowski Mateusz 241ef93cc38SKozlowski Mateusz static void 242b5e2c59aSKozlowski Mateusz ftl_mngt_fast_persist_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 243b5e2c59aSKozlowski Mateusz { 244b5e2c59aSKozlowski Mateusz if (ftl_nv_cache_save_state(&dev->nv_cache)) { 245b5e2c59aSKozlowski Mateusz ftl_mngt_fail_step(mngt); 246b5e2c59aSKozlowski Mateusz return; 247b5e2c59aSKozlowski Mateusz } 248b5e2c59aSKozlowski Mateusz ftl_mngt_next_step(mngt); 249b5e2c59aSKozlowski Mateusz } 250b5e2c59aSKozlowski Mateusz 251b5e2c59aSKozlowski Mateusz static void 252ef93cc38SKozlowski Mateusz ftl_mngt_persist_vld_map_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 253ef93cc38SKozlowski Mateusz { 254ef93cc38SKozlowski Mateusz persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_VALID_MAP); 255ef93cc38SKozlowski Mateusz } 256ef93cc38SKozlowski Mateusz 2571738488eSArtur Paszkiewicz static void 2581738488eSArtur Paszkiewicz ftl_mngt_persist_p2l_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 2591738488eSArtur Paszkiewicz { 2601738488eSArtur Paszkiewicz /* Sync runtime P2L to persist any invalidation that may have happened */ 2611738488eSArtur Paszkiewicz 2621738488eSArtur Paszkiewicz struct ftl_p2l_sync_ctx *ctx = ftl_mngt_get_step_ctx(mngt); 2631738488eSArtur Paszkiewicz 2641738488eSArtur Paszkiewicz /* 2651738488eSArtur Paszkiewicz * ftl_mngt_persist_bands_p2l will increment the md_region before the step_continue for next regions 2661738488eSArtur Paszkiewicz */ 2671738488eSArtur Paszkiewicz if (ctx->md_region <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN) { 2681738488eSArtur Paszkiewicz ctx->md_region = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN; 2691738488eSArtur Paszkiewicz } 2701738488eSArtur Paszkiewicz ftl_mngt_persist_bands_p2l(mngt); 2711738488eSArtur Paszkiewicz } 2721738488eSArtur Paszkiewicz 2739dbdb029SKozlowski Mateusz void 274ef93cc38SKozlowski Mateusz ftl_mngt_persist_band_info_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 2759dbdb029SKozlowski Mateusz { 2769dbdb029SKozlowski Mateusz persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_BAND_MD); 2779dbdb029SKozlowski Mateusz } 2789dbdb029SKozlowski Mateusz 279b3e5d8a7SKozlowski Mateusz static void 280b3e5d8a7SKozlowski Mateusz ftl_mngt_persist_trim_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 281b3e5d8a7SKozlowski Mateusz { 282b3e5d8a7SKozlowski Mateusz persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_TRIM_MD); 283b3e5d8a7SKozlowski Mateusz } 284b3e5d8a7SKozlowski Mateusz 285c6880a39SArtur Paszkiewicz static uint32_t 286c6880a39SArtur Paszkiewicz get_sb_crc(struct ftl_superblock *sb) 287c6880a39SArtur Paszkiewicz { 288c6880a39SArtur Paszkiewicz uint32_t crc = 0; 289c6880a39SArtur Paszkiewicz 290c6880a39SArtur Paszkiewicz /* Calculate CRC excluding CRC field in superblock */ 291c6880a39SArtur Paszkiewicz void *buffer = sb; 292c6880a39SArtur Paszkiewicz size_t offset = offsetof(struct ftl_superblock, header.crc); 293c6880a39SArtur Paszkiewicz size_t size = offset; 294c6880a39SArtur Paszkiewicz crc = spdk_crc32c_update(buffer, size, crc); 295c6880a39SArtur Paszkiewicz 296c6880a39SArtur Paszkiewicz buffer += offset + sizeof(sb->header.crc); 297c8ab874dSKozlowski Mateusz if (sb->header.version > FTL_SB_VERSION_2) { 298c8ab874dSKozlowski Mateusz /* whole buf for v3 and on: */ 299c6880a39SArtur Paszkiewicz size = FTL_SUPERBLOCK_SIZE - offset - sizeof(sb->header.crc); 300c6880a39SArtur Paszkiewicz crc = spdk_crc32c_update(buffer, size, crc); 301c8ab874dSKozlowski Mateusz } else { 302c8ab874dSKozlowski Mateusz /* special for sb v2 only: */ 303c8ab874dSKozlowski Mateusz size = sizeof(struct ftl_superblock_v2) - offset - sizeof(sb->header.crc); 304c8ab874dSKozlowski Mateusz sb->header.crc = spdk_crc32c_update(buffer, size, crc); 305c8ab874dSKozlowski Mateusz } 306c6880a39SArtur Paszkiewicz 307c6880a39SArtur Paszkiewicz return crc; 308c6880a39SArtur Paszkiewicz } 309c6880a39SArtur Paszkiewicz 310ef93cc38SKozlowski Mateusz static void 311ef93cc38SKozlowski Mateusz ftl_mngt_persist_super_block(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 312ef93cc38SKozlowski Mateusz { 313ef93cc38SKozlowski Mateusz dev->sb->overprovisioning = dev->conf.overprovisioning; 314ef93cc38SKozlowski Mateusz dev->sb->gc_info = dev->sb_shm->gc_info; 315ef93cc38SKozlowski Mateusz dev->sb->header.crc = get_sb_crc(dev->sb); 316ef93cc38SKozlowski Mateusz persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 317ef93cc38SKozlowski Mateusz } 318ef93cc38SKozlowski Mateusz 319ef93cc38SKozlowski Mateusz /* 320ef93cc38SKozlowski Mateusz * Persists all necessary metadata (band state, P2L, etc) during FTL's clean shutdown. 321ef93cc38SKozlowski Mateusz */ 322ef93cc38SKozlowski Mateusz static const struct ftl_mngt_process_desc desc_persist = { 323ef93cc38SKozlowski Mateusz .name = "Persist metadata", 324ef93cc38SKozlowski Mateusz .steps = { 325ef93cc38SKozlowski Mateusz { 326ef93cc38SKozlowski Mateusz .name = "Persist NV cache metadata", 327ef93cc38SKozlowski Mateusz .action = ftl_mngt_persist_nv_cache_metadata, 328ef93cc38SKozlowski Mateusz }, 329ef93cc38SKozlowski Mateusz { 330ef93cc38SKozlowski Mateusz .name = "Persist valid map metadata", 331ef93cc38SKozlowski Mateusz .action = ftl_mngt_persist_vld_map_metadata, 332ef93cc38SKozlowski Mateusz }, 333ef93cc38SKozlowski Mateusz { 3341738488eSArtur Paszkiewicz .name = "Persist P2L metadata", 3351738488eSArtur Paszkiewicz .action = ftl_mngt_persist_p2l_metadata, 3361738488eSArtur Paszkiewicz .ctx_size = sizeof(struct ftl_p2l_sync_ctx), 3371738488eSArtur Paszkiewicz }, 3381738488eSArtur Paszkiewicz { 3391c73a5c3SMateusz Kozlowski .name = "Persist band info metadata", 340ef93cc38SKozlowski Mateusz .action = ftl_mngt_persist_band_info_metadata, 341ef93cc38SKozlowski Mateusz }, 342ef93cc38SKozlowski Mateusz { 3431c73a5c3SMateusz Kozlowski .name = "Persist trim metadata", 344b3e5d8a7SKozlowski Mateusz .action = ftl_mngt_persist_trim_metadata, 345b3e5d8a7SKozlowski Mateusz }, 346b3e5d8a7SKozlowski Mateusz { 347ef93cc38SKozlowski Mateusz .name = "Persist superblock", 348ef93cc38SKozlowski Mateusz .action = ftl_mngt_persist_super_block, 349ef93cc38SKozlowski Mateusz }, 350ef93cc38SKozlowski Mateusz {} 351ef93cc38SKozlowski Mateusz } 352ef93cc38SKozlowski Mateusz }; 353ef93cc38SKozlowski Mateusz 354ef93cc38SKozlowski Mateusz void 355ef93cc38SKozlowski Mateusz ftl_mngt_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 356ef93cc38SKozlowski Mateusz { 3579452abe6SMateusz Kozlowski ftl_mngt_call_process(mngt, &desc_persist, NULL); 358ef93cc38SKozlowski Mateusz } 359ef93cc38SKozlowski Mateusz 360b5e2c59aSKozlowski Mateusz /* 3613f912cf0SMichal Berger * Fast clean shutdown path - skips the persistence of most metadata regions and 362b5e2c59aSKozlowski Mateusz * relies on their shared memory state instead. 363b5e2c59aSKozlowski Mateusz */ 364b5e2c59aSKozlowski Mateusz static const struct ftl_mngt_process_desc desc_fast_persist = { 365b5e2c59aSKozlowski Mateusz .name = "Fast persist metadata", 366b5e2c59aSKozlowski Mateusz .steps = { 367b5e2c59aSKozlowski Mateusz { 368b5e2c59aSKozlowski Mateusz .name = "Fast persist NV cache metadata", 369b5e2c59aSKozlowski Mateusz .action = ftl_mngt_fast_persist_nv_cache_metadata, 370b5e2c59aSKozlowski Mateusz }, 371b5e2c59aSKozlowski Mateusz {} 372b5e2c59aSKozlowski Mateusz } 373b5e2c59aSKozlowski Mateusz }; 374b5e2c59aSKozlowski Mateusz 375b5e2c59aSKozlowski Mateusz void 376b5e2c59aSKozlowski Mateusz ftl_mngt_fast_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 377b5e2c59aSKozlowski Mateusz { 3789452abe6SMateusz Kozlowski ftl_mngt_call_process(mngt, &desc_fast_persist, NULL); 379b5e2c59aSKozlowski Mateusz } 380b5e2c59aSKozlowski Mateusz 381c6880a39SArtur Paszkiewicz void 382c6880a39SArtur Paszkiewicz ftl_mngt_init_default_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 383c6880a39SArtur Paszkiewicz { 384c6880a39SArtur Paszkiewicz struct ftl_superblock *sb = dev->sb; 385c6880a39SArtur Paszkiewicz 386c6880a39SArtur Paszkiewicz sb->header.magic = FTL_SUPERBLOCK_MAGIC; 387c8ab874dSKozlowski Mateusz sb->header.version = FTL_SB_VERSION_CURRENT; 388c6880a39SArtur Paszkiewicz sb->uuid = dev->conf.uuid; 389c6880a39SArtur Paszkiewicz sb->clean = 0; 390f45c0075SArtur Paszkiewicz dev->sb_shm->shm_clean = false; 3911738488eSArtur Paszkiewicz sb->ckpt_seq_id = 0; 392c6880a39SArtur Paszkiewicz 393c6880a39SArtur Paszkiewicz /* Max 16 IO depth per band relocate */ 394c6880a39SArtur Paszkiewicz sb->max_reloc_qdepth = 16; 395c6880a39SArtur Paszkiewicz 396c6880a39SArtur Paszkiewicz sb->overprovisioning = dev->conf.overprovisioning; 397c6880a39SArtur Paszkiewicz 398711759a0SKozlowski Mateusz ftl_band_init_gc_iter(dev); 399711759a0SKozlowski Mateusz 400c6880a39SArtur Paszkiewicz /* md layout isn't initialized yet. 401c6880a39SArtur Paszkiewicz * empty region list => all regions in the default location */ 4029f42898aSLukasz Lasek spdk_strcpy_pad(sb->base_dev_name, dev->base_type->name, 4039f42898aSLukasz Lasek SPDK_COUNTOF(sb->base_dev_name), '\0'); 4049f42898aSLukasz Lasek sb->md_layout_base.df_id = FTL_DF_OBJ_ID_INVALID; 4059f42898aSLukasz Lasek 40626f3b551SMateusz Kozlowski spdk_strcpy_pad(sb->nvc_dev_name, dev->nv_cache.nvc_type->name, 4079f42898aSLukasz Lasek SPDK_COUNTOF(sb->nvc_dev_name), '\0'); 4089f42898aSLukasz Lasek sb->md_layout_nvc.df_id = FTL_DF_OBJ_ID_INVALID; 409c6880a39SArtur Paszkiewicz 410c6880a39SArtur Paszkiewicz sb->header.crc = get_sb_crc(sb); 411c6880a39SArtur Paszkiewicz 412c6880a39SArtur Paszkiewicz ftl_mngt_next_step(mngt); 413c6880a39SArtur Paszkiewicz } 414c6880a39SArtur Paszkiewicz 415c6880a39SArtur Paszkiewicz void 416c6880a39SArtur Paszkiewicz ftl_mngt_set_dirty(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 417c6880a39SArtur Paszkiewicz { 418c6880a39SArtur Paszkiewicz struct ftl_superblock *sb = dev->sb; 419c6880a39SArtur Paszkiewicz 420c6880a39SArtur Paszkiewicz sb->clean = 0; 421d4a2d28dSMateusz Kozlowski sb->upgrade_ready = false; 422f45c0075SArtur Paszkiewicz dev->sb_shm->shm_clean = false; 423c6880a39SArtur Paszkiewicz sb->header.crc = get_sb_crc(sb); 424c6880a39SArtur Paszkiewicz persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 425c6880a39SArtur Paszkiewicz } 426c6880a39SArtur Paszkiewicz 427ef93cc38SKozlowski Mateusz void 428ef93cc38SKozlowski Mateusz ftl_mngt_set_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 429ef93cc38SKozlowski Mateusz { 430ef93cc38SKozlowski Mateusz struct ftl_superblock *sb = dev->sb; 431ef93cc38SKozlowski Mateusz 432ef93cc38SKozlowski Mateusz sb->clean = 1; 433d4a2d28dSMateusz Kozlowski sb->upgrade_ready = dev->conf.prep_upgrade_on_shutdown; 434ef93cc38SKozlowski Mateusz dev->sb_shm->shm_clean = false; 435ef93cc38SKozlowski Mateusz sb->header.crc = get_sb_crc(sb); 436ef93cc38SKozlowski Mateusz persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 437ef93cc38SKozlowski Mateusz 438ef93cc38SKozlowski Mateusz dev->sb_shm->shm_ready = false; 439ef93cc38SKozlowski Mateusz } 440ef93cc38SKozlowski Mateusz 441b5e2c59aSKozlowski Mateusz void 442b5e2c59aSKozlowski Mateusz ftl_mngt_set_shm_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 443b5e2c59aSKozlowski Mateusz { 444b5e2c59aSKozlowski Mateusz struct ftl_superblock *sb = dev->sb; 445b5e2c59aSKozlowski Mateusz 446b5e2c59aSKozlowski Mateusz sb->clean = 1; 447b5e2c59aSKozlowski Mateusz dev->sb_shm->shm_clean = true; 448b5e2c59aSKozlowski Mateusz sb->header.crc = get_sb_crc(sb); 449b5e2c59aSKozlowski Mateusz ftl_mngt_next_step(mngt); 450b5e2c59aSKozlowski Mateusz } 451b5e2c59aSKozlowski Mateusz 452cbd7ae6dSKozlowski Mateusz void 453cbd7ae6dSKozlowski Mateusz ftl_mngt_load_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 454cbd7ae6dSKozlowski Mateusz { 455cbd7ae6dSKozlowski Mateusz FTL_NOTICELOG(dev, "SHM: clean %"PRIu64", shm_clean %d\n", dev->sb->clean, dev->sb_shm->shm_clean); 456cbd7ae6dSKozlowski Mateusz 457cbd7ae6dSKozlowski Mateusz if (!ftl_fast_startup(dev)) { 458cbd7ae6dSKozlowski Mateusz restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 459cbd7ae6dSKozlowski Mateusz return; 460cbd7ae6dSKozlowski Mateusz } 461cbd7ae6dSKozlowski Mateusz 462cbd7ae6dSKozlowski Mateusz FTL_DEBUGLOG(dev, "SHM: found SB\n"); 463cbd7ae6dSKozlowski Mateusz if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_SB)) { 464cbd7ae6dSKozlowski Mateusz ftl_mngt_fail_step(mngt); 465cbd7ae6dSKozlowski Mateusz return; 466cbd7ae6dSKozlowski Mateusz } 467cbd7ae6dSKozlowski Mateusz ftl_mngt_next_step(mngt); 468cbd7ae6dSKozlowski Mateusz } 469cbd7ae6dSKozlowski Mateusz 470cbd7ae6dSKozlowski Mateusz void 471cbd7ae6dSKozlowski Mateusz ftl_mngt_validate_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 472cbd7ae6dSKozlowski Mateusz { 473cbd7ae6dSKozlowski Mateusz struct ftl_superblock *sb = dev->sb; 474cbd7ae6dSKozlowski Mateusz 475cbd7ae6dSKozlowski Mateusz if (!ftl_superblock_check_magic(sb)) { 476cbd7ae6dSKozlowski Mateusz FTL_ERRLOG(dev, "Invalid FTL superblock magic\n"); 477cbd7ae6dSKozlowski Mateusz ftl_mngt_fail_step(mngt); 478cbd7ae6dSKozlowski Mateusz return; 479cbd7ae6dSKozlowski Mateusz } 480cbd7ae6dSKozlowski Mateusz 481cbd7ae6dSKozlowski Mateusz if (sb->header.crc != get_sb_crc(sb)) { 482cbd7ae6dSKozlowski Mateusz FTL_ERRLOG(dev, "Invalid FTL superblock CRC\n"); 483cbd7ae6dSKozlowski Mateusz ftl_mngt_fail_step(mngt); 484cbd7ae6dSKozlowski Mateusz return; 485cbd7ae6dSKozlowski Mateusz } 486cbd7ae6dSKozlowski Mateusz 487d748bc41SKozlowski Mateusz if (ftl_superblock_upgrade(dev)) { 488d748bc41SKozlowski Mateusz FTL_ERRLOG(dev, "FTL superblock dirty or invalid version\n"); 489d748bc41SKozlowski Mateusz ftl_mngt_fail_step(mngt); 490d748bc41SKozlowski Mateusz return; 491d748bc41SKozlowski Mateusz } 492d748bc41SKozlowski Mateusz 493cbd7ae6dSKozlowski Mateusz if (spdk_uuid_compare(&sb->uuid, &dev->conf.uuid) != 0) { 494cbd7ae6dSKozlowski Mateusz FTL_ERRLOG(dev, "Invalid FTL superblock UUID\n"); 495cbd7ae6dSKozlowski Mateusz ftl_mngt_fail_step(mngt); 496cbd7ae6dSKozlowski Mateusz return; 497cbd7ae6dSKozlowski Mateusz } 498cbd7ae6dSKozlowski Mateusz 499cbd7ae6dSKozlowski Mateusz if (sb->lba_cnt == 0) { 500cbd7ae6dSKozlowski Mateusz FTL_ERRLOG(dev, "Invalid FTL superblock lba_cnt\n"); 501cbd7ae6dSKozlowski Mateusz ftl_mngt_fail_step(mngt); 502cbd7ae6dSKozlowski Mateusz return; 503cbd7ae6dSKozlowski Mateusz } 504cbd7ae6dSKozlowski Mateusz dev->num_lbas = sb->lba_cnt; 505cbd7ae6dSKozlowski Mateusz 506cbd7ae6dSKozlowski Mateusz /* The sb has just been read. Validate and update the conf */ 507cbd7ae6dSKozlowski Mateusz if (sb->overprovisioning == 0 || sb->overprovisioning >= 100) { 508cbd7ae6dSKozlowski Mateusz FTL_ERRLOG(dev, "Invalid FTL superblock lba_rsvd\n"); 509cbd7ae6dSKozlowski Mateusz ftl_mngt_fail_step(mngt); 510cbd7ae6dSKozlowski Mateusz return; 511cbd7ae6dSKozlowski Mateusz } 512cbd7ae6dSKozlowski Mateusz dev->conf.overprovisioning = sb->overprovisioning; 513cbd7ae6dSKozlowski Mateusz 5149f42898aSLukasz Lasek if (!ftl_superblock_validate_blob_area(dev)) { 5159f42898aSLukasz Lasek FTL_ERRLOG(dev, "Corrupted FTL superblock blob area\n"); 5169f42898aSLukasz Lasek ftl_mngt_fail_step(mngt); 5179f42898aSLukasz Lasek return; 5189f42898aSLukasz Lasek } 5199f42898aSLukasz Lasek 520cbd7ae6dSKozlowski Mateusz ftl_mngt_next_step(mngt); 521cbd7ae6dSKozlowski Mateusz } 522cbd7ae6dSKozlowski Mateusz 523cbd7ae6dSKozlowski Mateusz /* 524cbd7ae6dSKozlowski Mateusz * Loads and verifies superblock contents - utilized during the load of an FTL 525cbd7ae6dSKozlowski Mateusz * instance (both from a clean and dirty shutdown). 526cbd7ae6dSKozlowski Mateusz */ 527cbd7ae6dSKozlowski Mateusz static const struct ftl_mngt_process_desc desc_restore_sb = { 528cbd7ae6dSKozlowski Mateusz .name = "SB restore", 529cbd7ae6dSKozlowski Mateusz .steps = { 530cbd7ae6dSKozlowski Mateusz { 531cbd7ae6dSKozlowski Mateusz .name = "Load super block", 532cbd7ae6dSKozlowski Mateusz .action = ftl_mngt_load_sb 533cbd7ae6dSKozlowski Mateusz }, 534cbd7ae6dSKozlowski Mateusz { 535cbd7ae6dSKozlowski Mateusz .name = "Validate super block", 536cbd7ae6dSKozlowski Mateusz .action = ftl_mngt_validate_sb 537cbd7ae6dSKozlowski Mateusz }, 538cbd7ae6dSKozlowski Mateusz {} 539cbd7ae6dSKozlowski Mateusz } 540cbd7ae6dSKozlowski Mateusz }; 541cbd7ae6dSKozlowski Mateusz 542c6880a39SArtur Paszkiewicz /* 543c6880a39SArtur Paszkiewicz * Initializes the superblock fields during first startup of FTL 544c6880a39SArtur Paszkiewicz */ 545c6880a39SArtur Paszkiewicz static const struct ftl_mngt_process_desc desc_init_sb = { 546c6880a39SArtur Paszkiewicz .name = "SB initialize", 547c6880a39SArtur Paszkiewicz .steps = { 548c6880a39SArtur Paszkiewicz { 549c6880a39SArtur Paszkiewicz .name = "Default-initialize superblock", 550c6880a39SArtur Paszkiewicz .action = ftl_mngt_init_default_sb, 551c6880a39SArtur Paszkiewicz }, 552c6880a39SArtur Paszkiewicz {} 553c6880a39SArtur Paszkiewicz } 554c6880a39SArtur Paszkiewicz }; 555c6880a39SArtur Paszkiewicz 556c6880a39SArtur Paszkiewicz void 557c6880a39SArtur Paszkiewicz ftl_mngt_superblock_init(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 558c6880a39SArtur Paszkiewicz { 559522a0c82SLukasz Lasek struct ftl_md *md; 560522a0c82SLukasz Lasek struct ftl_md *md_mirror; 561c6880a39SArtur Paszkiewicz struct ftl_layout *layout = &dev->layout; 562c6880a39SArtur Paszkiewicz struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB]; 563c6880a39SArtur Paszkiewicz char uuid[SPDK_UUID_STRING_LEN]; 5641e904e2bSArtur Paszkiewicz int md_create_flags = ftl_md_create_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB); 565c6880a39SArtur Paszkiewicz 566c6880a39SArtur Paszkiewicz /* Must generate UUID before MD create on SHM for the SB */ 567c6880a39SArtur Paszkiewicz if (dev->conf.mode & SPDK_FTL_MODE_CREATE) { 568c6880a39SArtur Paszkiewicz spdk_uuid_generate(&dev->conf.uuid); 569c6880a39SArtur Paszkiewicz spdk_uuid_fmt_lower(uuid, sizeof(uuid), &dev->conf.uuid); 570c6880a39SArtur Paszkiewicz FTL_NOTICELOG(dev, "Create new FTL, UUID %s\n", uuid); 571c6880a39SArtur Paszkiewicz } 572c6880a39SArtur Paszkiewicz 5731e904e2bSArtur Paszkiewicz shm_retry: 574f45c0075SArtur Paszkiewicz /* Allocate md buf */ 575f45c0075SArtur Paszkiewicz dev->sb_shm = NULL; 576f45c0075SArtur Paszkiewicz dev->sb_shm_md = ftl_md_create(dev, spdk_divide_round_up(sizeof(*dev->sb_shm), FTL_BLOCK_SIZE), 577f45c0075SArtur Paszkiewicz 0, "sb_shm", 578f45c0075SArtur Paszkiewicz md_create_flags, NULL); 579f45c0075SArtur Paszkiewicz if (dev->sb_shm_md == NULL) { 5801e904e2bSArtur Paszkiewicz /* The first attempt may fail when trying to open SHM - try to create new */ 5811e904e2bSArtur Paszkiewicz if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) { 5821e904e2bSArtur Paszkiewicz md_create_flags |= FTL_MD_CREATE_SHM_NEW; 5831e904e2bSArtur Paszkiewicz goto shm_retry; 5841e904e2bSArtur Paszkiewicz } 5851e904e2bSArtur Paszkiewicz if (dev->sb_shm_md == NULL) { 586f45c0075SArtur Paszkiewicz ftl_mngt_fail_step(mngt); 587f45c0075SArtur Paszkiewicz return; 588f45c0075SArtur Paszkiewicz } 5891e904e2bSArtur Paszkiewicz } 590f45c0075SArtur Paszkiewicz 591f45c0075SArtur Paszkiewicz dev->sb_shm = ftl_md_get_buffer(dev->sb_shm_md); 592f45c0075SArtur Paszkiewicz 593c6880a39SArtur Paszkiewicz /* Setup the layout of a superblock */ 594c6880a39SArtur Paszkiewicz if (ftl_layout_setup_superblock(dev)) { 595c6880a39SArtur Paszkiewicz ftl_mngt_fail_step(mngt); 596c6880a39SArtur Paszkiewicz return; 597c6880a39SArtur Paszkiewicz } 598c6880a39SArtur Paszkiewicz 599c6880a39SArtur Paszkiewicz /* Allocate md buf */ 600c6880a39SArtur Paszkiewicz layout->md[FTL_LAYOUT_REGION_TYPE_SB] = ftl_md_create(dev, region->current.blocks, 601818b9c05SArtur Paszkiewicz region->vss_blksz, region->name, 602818b9c05SArtur Paszkiewicz md_create_flags, region); 603c6880a39SArtur Paszkiewicz if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB]) { 6041e904e2bSArtur Paszkiewicz /* The first attempt may fail when trying to open SHM - try to create new */ 6051e904e2bSArtur Paszkiewicz if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) { 6061e904e2bSArtur Paszkiewicz md_create_flags |= FTL_MD_CREATE_SHM_NEW; 6071e904e2bSArtur Paszkiewicz ftl_md_destroy(dev->sb_shm_md, 0); 6086a26cb60SKozlowski Mateusz dev->sb_shm_md = NULL; 6099f42898aSLukasz Lasek if (ftl_layout_clear_superblock(dev)) { 6109f42898aSLukasz Lasek ftl_mngt_fail_step(mngt); 6119f42898aSLukasz Lasek return; 6129f42898aSLukasz Lasek } 6131e904e2bSArtur Paszkiewicz goto shm_retry; 6141e904e2bSArtur Paszkiewicz } 615c6880a39SArtur Paszkiewicz ftl_mngt_fail_step(mngt); 616c6880a39SArtur Paszkiewicz return; 617c6880a39SArtur Paszkiewicz } 618c6880a39SArtur Paszkiewicz 619c6880a39SArtur Paszkiewicz /* Link the md buf to the device */ 620c6880a39SArtur Paszkiewicz dev->sb = ftl_md_get_buffer(layout->md[FTL_LAYOUT_REGION_TYPE_SB]); 621c6880a39SArtur Paszkiewicz 622c6880a39SArtur Paszkiewicz /* Setup superblock mirror to QLC */ 623c6880a39SArtur Paszkiewicz region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB_BASE]; 624c6880a39SArtur Paszkiewicz layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = ftl_md_create(dev, region->current.blocks, 625522a0c82SLukasz Lasek region->vss_blksz, NULL, FTL_MD_CREATE_NO_MEM, region); 626c6880a39SArtur Paszkiewicz if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) { 627c6880a39SArtur Paszkiewicz ftl_mngt_fail_step(mngt); 628c6880a39SArtur Paszkiewicz return; 629c6880a39SArtur Paszkiewicz } 630c6880a39SArtur Paszkiewicz 631522a0c82SLukasz Lasek /* Initialize mirror region buffer */ 632522a0c82SLukasz Lasek md = layout->md[FTL_LAYOUT_REGION_TYPE_SB]; 633522a0c82SLukasz Lasek md_mirror = layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]; 634522a0c82SLukasz Lasek 635522a0c82SLukasz Lasek md_mirror->dev = md->dev; 636522a0c82SLukasz Lasek md_mirror->data_blocks = md->data_blocks; 637522a0c82SLukasz Lasek md_mirror->data = md->data; 638522a0c82SLukasz Lasek md_mirror->is_mirror = true; 639522a0c82SLukasz Lasek 640c6880a39SArtur Paszkiewicz /* Initialize the superblock */ 641c6880a39SArtur Paszkiewicz if (dev->conf.mode & SPDK_FTL_MODE_CREATE) { 6429452abe6SMateusz Kozlowski ftl_mngt_call_process(mngt, &desc_init_sb, NULL); 643c6880a39SArtur Paszkiewicz } else { 6449452abe6SMateusz Kozlowski ftl_mngt_call_process(mngt, &desc_restore_sb, NULL); 645c6880a39SArtur Paszkiewicz } 646c6880a39SArtur Paszkiewicz } 647c6880a39SArtur Paszkiewicz 648c6880a39SArtur Paszkiewicz void 649c6880a39SArtur Paszkiewicz ftl_mngt_superblock_deinit(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 650c6880a39SArtur Paszkiewicz { 651c6880a39SArtur Paszkiewicz struct ftl_layout *layout = &dev->layout; 652c6880a39SArtur Paszkiewicz 653c6880a39SArtur Paszkiewicz if (layout->md[FTL_LAYOUT_REGION_TYPE_SB]) { 6540e33da49SKozlowski Mateusz ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB], 6550e33da49SKozlowski Mateusz ftl_md_destroy_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB)); 656c6880a39SArtur Paszkiewicz layout->md[FTL_LAYOUT_REGION_TYPE_SB] = NULL; 657c6880a39SArtur Paszkiewicz } 658c6880a39SArtur Paszkiewicz 659c6880a39SArtur Paszkiewicz if (layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) { 6600e33da49SKozlowski Mateusz ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE], 0); 661c6880a39SArtur Paszkiewicz layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = NULL; 662c6880a39SArtur Paszkiewicz } 663c6880a39SArtur Paszkiewicz 6640e33da49SKozlowski Mateusz ftl_md_destroy(dev->sb_shm_md, ftl_md_destroy_shm_flags(dev)); 665f45c0075SArtur Paszkiewicz dev->sb_shm_md = NULL; 666f45c0075SArtur Paszkiewicz dev->sb_shm = NULL; 667f45c0075SArtur Paszkiewicz 668c6880a39SArtur Paszkiewicz ftl_mngt_next_step(mngt); 669c6880a39SArtur Paszkiewicz } 670cbd7ae6dSKozlowski Mateusz 671cbd7ae6dSKozlowski Mateusz static void 672cbd7ae6dSKozlowski Mateusz ftl_mngt_restore_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 673cbd7ae6dSKozlowski Mateusz { 674cbd7ae6dSKozlowski Mateusz if (ftl_fast_startup(dev)) { 675cbd7ae6dSKozlowski Mateusz FTL_DEBUGLOG(dev, "SHM: found nv cache md\n"); 676cbd7ae6dSKozlowski Mateusz if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_NVC_MD)) { 677cbd7ae6dSKozlowski Mateusz ftl_mngt_fail_step(mngt); 678cbd7ae6dSKozlowski Mateusz return; 679cbd7ae6dSKozlowski Mateusz } 680cbd7ae6dSKozlowski Mateusz ftl_mngt_next_step(mngt); 681cbd7ae6dSKozlowski Mateusz return; 682cbd7ae6dSKozlowski Mateusz } 683cbd7ae6dSKozlowski Mateusz restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_NVC_MD); 684cbd7ae6dSKozlowski Mateusz } 685cbd7ae6dSKozlowski Mateusz 686cbd7ae6dSKozlowski Mateusz static void 687cbd7ae6dSKozlowski Mateusz ftl_mngt_restore_vld_map_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 688cbd7ae6dSKozlowski Mateusz { 689cbd7ae6dSKozlowski Mateusz if (ftl_fast_startup(dev)) { 690cbd7ae6dSKozlowski Mateusz FTL_DEBUGLOG(dev, "SHM: found vldmap\n"); 691cbd7ae6dSKozlowski Mateusz if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_VALID_MAP)) { 692cbd7ae6dSKozlowski Mateusz ftl_mngt_fail_step(mngt); 693cbd7ae6dSKozlowski Mateusz return; 694cbd7ae6dSKozlowski Mateusz } 695cbd7ae6dSKozlowski Mateusz ftl_mngt_next_step(mngt); 696cbd7ae6dSKozlowski Mateusz return; 697cbd7ae6dSKozlowski Mateusz } 698cbd7ae6dSKozlowski Mateusz restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_VALID_MAP); 699cbd7ae6dSKozlowski Mateusz } 700cbd7ae6dSKozlowski Mateusz 701cbd7ae6dSKozlowski Mateusz static void 702cbd7ae6dSKozlowski Mateusz ftl_mngt_restore_band_info_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 703cbd7ae6dSKozlowski Mateusz { 704cbd7ae6dSKozlowski Mateusz if (ftl_fast_startup(dev)) { 705cbd7ae6dSKozlowski Mateusz FTL_DEBUGLOG(dev, "SHM: found band md\n"); 706cbd7ae6dSKozlowski Mateusz if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_BAND_MD)) { 707cbd7ae6dSKozlowski Mateusz ftl_mngt_fail_step(mngt); 708cbd7ae6dSKozlowski Mateusz return; 709cbd7ae6dSKozlowski Mateusz } 710cbd7ae6dSKozlowski Mateusz ftl_mngt_next_step(mngt); 711cbd7ae6dSKozlowski Mateusz return; 712cbd7ae6dSKozlowski Mateusz } 713cbd7ae6dSKozlowski Mateusz restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_BAND_MD); 714cbd7ae6dSKozlowski Mateusz } 715cbd7ae6dSKozlowski Mateusz 716b3e5d8a7SKozlowski Mateusz static void 717b3e5d8a7SKozlowski Mateusz ftl_mngt_restore_trim_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 718b3e5d8a7SKozlowski Mateusz { 719b3e5d8a7SKozlowski Mateusz if (ftl_fast_startup(dev)) { 720b3e5d8a7SKozlowski Mateusz FTL_DEBUGLOG(dev, "SHM: found trim md\n"); 721b3e5d8a7SKozlowski Mateusz if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_TRIM_MD)) { 722b3e5d8a7SKozlowski Mateusz ftl_mngt_fail_step(mngt); 723b3e5d8a7SKozlowski Mateusz return; 724b3e5d8a7SKozlowski Mateusz } 725b3e5d8a7SKozlowski Mateusz ftl_mngt_next_step(mngt); 726b3e5d8a7SKozlowski Mateusz return; 727b3e5d8a7SKozlowski Mateusz } 728b3e5d8a7SKozlowski Mateusz restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_TRIM_MD); 729b3e5d8a7SKozlowski Mateusz } 730b3e5d8a7SKozlowski Mateusz 731cbd7ae6dSKozlowski Mateusz /* 732cbd7ae6dSKozlowski Mateusz * Loads metadata after a clean shutdown. 733cbd7ae6dSKozlowski Mateusz */ 734cbd7ae6dSKozlowski Mateusz static const struct ftl_mngt_process_desc desc_restore = { 735cbd7ae6dSKozlowski Mateusz .name = "Restore metadata", 736cbd7ae6dSKozlowski Mateusz .steps = { 737cbd7ae6dSKozlowski Mateusz { 738cbd7ae6dSKozlowski Mateusz .name = "Restore NV cache metadata", 739cbd7ae6dSKozlowski Mateusz .action = ftl_mngt_restore_nv_cache_metadata, 740cbd7ae6dSKozlowski Mateusz }, 741cbd7ae6dSKozlowski Mateusz { 742cbd7ae6dSKozlowski Mateusz .name = "Restore valid map metadata", 743cbd7ae6dSKozlowski Mateusz .action = ftl_mngt_restore_vld_map_metadata, 744cbd7ae6dSKozlowski Mateusz }, 745cbd7ae6dSKozlowski Mateusz { 746cbd7ae6dSKozlowski Mateusz .name = "Restore band info metadata", 747cbd7ae6dSKozlowski Mateusz .action = ftl_mngt_restore_band_info_metadata, 748cbd7ae6dSKozlowski Mateusz }, 749b3e5d8a7SKozlowski Mateusz { 750b3e5d8a7SKozlowski Mateusz .name = "Restore trim metadata", 751b3e5d8a7SKozlowski Mateusz .action = ftl_mngt_restore_trim_metadata, 752b3e5d8a7SKozlowski Mateusz }, 753cbd7ae6dSKozlowski Mateusz {} 754cbd7ae6dSKozlowski Mateusz } 755cbd7ae6dSKozlowski Mateusz }; 756cbd7ae6dSKozlowski Mateusz 757cbd7ae6dSKozlowski Mateusz void 758cbd7ae6dSKozlowski Mateusz ftl_mngt_restore_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 759cbd7ae6dSKozlowski Mateusz { 7609452abe6SMateusz Kozlowski ftl_mngt_call_process(mngt, &desc_restore, NULL); 761cbd7ae6dSKozlowski Mateusz } 7627ff28519SKozlowski Mateusz 7637ff28519SKozlowski Mateusz void 7647ff28519SKozlowski Mateusz ftl_mngt_persist_superblock(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 7657ff28519SKozlowski Mateusz { 7667ff28519SKozlowski Mateusz dev->sb->header.crc = get_sb_crc(dev->sb); 7677ff28519SKozlowski Mateusz persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 7687ff28519SKozlowski Mateusz } 769