LCOV - code coverage report
Current view: top level - lib/ftl/mngt - ftl_mngt_md.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 31 348 8.9 %
Date: 2024-07-13 08:38:25 Functions: 2 33 6.1 %

          Line data    Source code
       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           0 : ftl_mngt_init_layout(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
      25             : {
      26           0 :         if (ftl_layout_setup(dev)) {
      27           0 :                 ftl_mngt_fail_step(mngt);
      28             :         } else {
      29           0 :                 ftl_mngt_next_step(mngt);
      30             :         }
      31           0 : }
      32             : 
      33             : static bool
      34           0 : is_buffer_needed(enum ftl_layout_region_type type)
      35             : {
      36           0 :         switch (type) {
      37           0 :         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           0 :                 return false;
      48             : 
      49           0 :         default:
      50           0 :                 return true;
      51             :         }
      52             : }
      53             : 
      54             : void
      55           0 : ftl_mngt_init_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
      56             : {
      57           0 :         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           0 :         for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++) {
      64           0 :                 region = ftl_layout_region_get(dev, i);
      65           0 :                 if (!region) {
      66           0 :                         continue;
      67             :                 }
      68           0 :                 assert(i == region->type);
      69           0 :                 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           0 :                         continue;
      77             :                 }
      78           0 :                 md_flags = is_buffer_needed(i) ? ftl_md_create_region_flags(dev,
      79           0 :                                 region->type) : FTL_MD_CREATE_NO_MEM;
      80           0 :                 layout->md[i] = ftl_md_create(dev, region->current.blocks, region->vss_blksz, region->name,
      81             :                                               md_flags, region);
      82           0 :                 if (NULL == layout->md[i]) {
      83           0 :                         ftl_mngt_fail_step(mngt);
      84           0 :                         return;
      85             :                 }
      86             :         }
      87             : 
      88             :         /* Initialize mirror regions */
      89           0 :         for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++) {
      90           0 :                 region = ftl_layout_region_get(dev, i);
      91           0 :                 if (!region) {
      92           0 :                         continue;
      93             :                 }
      94           0 :                 assert(i == region->type);
      95           0 :                 if (region->mirror_type != FTL_LAYOUT_REGION_TYPE_INVALID &&
      96           0 :                     !is_buffer_needed(region->mirror_type)) {
      97           0 :                         md = layout->md[i];
      98           0 :                         md_mirror = layout->md[region->mirror_type];
      99             : 
     100           0 :                         md_mirror->dev = md->dev;
     101           0 :                         md_mirror->data_blocks = md->data_blocks;
     102           0 :                         md_mirror->data = md->data;
     103           0 :                         if (md_mirror->region->vss_blksz == md->region->vss_blksz) {
     104           0 :                                 md_mirror->vss_data = md->vss_data;
     105             :                         }
     106           0 :                         md_mirror->region = ftl_layout_region_get(dev, region->mirror_type);
     107           0 :                         ftl_bug(md_mirror->region == NULL);
     108           0 :                         md_mirror->is_mirror = true;
     109             :                 }
     110             :         }
     111             : 
     112           0 :         ftl_mngt_next_step(mngt);
     113             : }
     114             : 
     115             : void
     116           0 : ftl_mngt_deinit_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     117             : {
     118           0 :         struct ftl_layout *layout = &dev->layout;
     119             :         struct ftl_layout_region *region;
     120             :         enum ftl_layout_region_type i;
     121             : 
     122           0 :         for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++) {
     123           0 :                 region = ftl_layout_region_get(dev, i);
     124           0 :                 if (!region) {
     125           0 :                         continue;
     126             :                 }
     127           0 :                 if (layout->md[i]) {
     128           0 :                         ftl_md_destroy(layout->md[i], ftl_md_destroy_region_flags(dev, region->type));
     129           0 :                         layout->md[i] = NULL;
     130             :                 }
     131             :         }
     132             : 
     133           0 :         ftl_mngt_next_step(mngt);
     134           0 : }
     135             : 
     136             : static void
     137           0 : persist_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status)
     138             : {
     139           0 :         struct ftl_mngt_process *mngt = md->owner.cb_ctx;
     140             : 
     141           0 :         if (status) {
     142           0 :                 ftl_mngt_fail_step(mngt);
     143             :         } else {
     144           0 :                 ftl_mngt_next_step(mngt);
     145             :         }
     146           0 : }
     147             : 
     148             : static void
     149           0 : persist(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt,
     150             :         enum ftl_layout_region_type type)
     151             : {
     152           0 :         struct ftl_layout *layout = &dev->layout;
     153             :         struct ftl_md *md;
     154             : 
     155           0 :         assert(type < FTL_LAYOUT_REGION_TYPE_MAX);
     156             : 
     157           0 :         md = layout->md[type];
     158           0 :         if (!md) {
     159           0 :                 ftl_mngt_fail_step(mngt);
     160           0 :                 return;
     161             :         }
     162             : 
     163           0 :         md->owner.cb_ctx = mngt;
     164           0 :         md->cb = persist_cb;
     165           0 :         ftl_md_persist(md);
     166             : }
     167             : 
     168             : static int
     169           0 : ftl_md_restore_region(struct spdk_ftl_dev *dev, int region_type)
     170             : {
     171           0 :         int status = 0;
     172           0 :         switch (region_type) {
     173           0 :         case FTL_LAYOUT_REGION_TYPE_NVC_MD:
     174           0 :                 status = ftl_nv_cache_load_state(&dev->nv_cache);
     175           0 :                 break;
     176           0 :         case FTL_LAYOUT_REGION_TYPE_VALID_MAP:
     177           0 :                 ftl_valid_map_load_state(dev);
     178           0 :                 break;
     179           0 :         case FTL_LAYOUT_REGION_TYPE_BAND_MD:
     180           0 :                 ftl_bands_load_state(dev);
     181           0 :                 break;
     182           0 :         default:
     183           0 :                 break;
     184             :         }
     185           0 :         return status;
     186             : }
     187             : 
     188             : static void
     189           0 : restore_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status)
     190             : {
     191           0 :         struct ftl_mngt_process *mngt = md->owner.cb_ctx;
     192           0 :         const struct ftl_layout_region *region = ftl_md_get_region(md);
     193             : 
     194           0 :         if (status) {
     195             :                 /* Restore error, end step */
     196           0 :                 ftl_mngt_fail_step(mngt);
     197           0 :                 return;
     198             :         }
     199             : 
     200           0 :         assert(region);
     201           0 :         status = ftl_md_restore_region(dev, region->type);
     202             : 
     203           0 :         if (status) {
     204           0 :                 ftl_mngt_fail_step(mngt);
     205             :         } else {
     206           0 :                 ftl_mngt_next_step(mngt);
     207             :         }
     208             : }
     209             : 
     210             : static void
     211           0 : restore(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt, enum ftl_layout_region_type type)
     212             : {
     213           0 :         struct ftl_layout *layout = &dev->layout;
     214           0 :         assert(type < FTL_LAYOUT_REGION_TYPE_MAX);
     215           0 :         struct ftl_md *md = layout->md[type];
     216             : 
     217           0 :         if (!md) {
     218           0 :                 ftl_mngt_fail_step(mngt);
     219           0 :                 return;
     220             :         }
     221             : 
     222           0 :         md->owner.cb_ctx = mngt;
     223           0 :         md->cb = restore_cb;
     224           0 :         ftl_md_restore(md);
     225             : }
     226             : 
     227             : void
     228           0 : ftl_mngt_persist_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     229             : {
     230           0 :         if (ftl_nv_cache_save_state(&dev->nv_cache)) {
     231           0 :                 ftl_mngt_fail_step(mngt);
     232           0 :                 return;
     233             :         }
     234             : 
     235           0 :         persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_NVC_MD);
     236             : }
     237             : 
     238             : static void
     239           0 : ftl_mngt_fast_persist_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     240             : {
     241           0 :         if (ftl_nv_cache_save_state(&dev->nv_cache)) {
     242           0 :                 ftl_mngt_fail_step(mngt);
     243           0 :                 return;
     244             :         }
     245           0 :         ftl_mngt_next_step(mngt);
     246             : }
     247             : 
     248             : static void
     249           0 : ftl_mngt_persist_vld_map_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     250             : {
     251           0 :         persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_VALID_MAP);
     252           0 : }
     253             : 
     254             : static void
     255           0 : 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           0 :         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           0 :         if (ctx->md_region <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN) {
     265           0 :                 ctx->md_region = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN;
     266             :         }
     267           0 :         ftl_mngt_persist_bands_p2l(mngt);
     268           0 : }
     269             : 
     270             : void
     271           0 : ftl_mngt_persist_band_info_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     272             : {
     273           0 :         persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_BAND_MD);
     274           0 : }
     275             : 
     276             : static void
     277           0 : ftl_mngt_persist_trim_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     278             : {
     279           0 :         persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_TRIM_MD);
     280           0 : }
     281             : 
     282             : static uint32_t
     283          16 : get_sb_crc(struct ftl_superblock *sb)
     284             : {
     285          16 :         uint32_t crc = 0;
     286             : 
     287             :         /* Calculate CRC excluding CRC field in superblock */
     288          16 :         void *buffer = sb;
     289          16 :         size_t offset = offsetof(struct ftl_superblock, header.crc);
     290          16 :         size_t size = offset;
     291          16 :         crc = spdk_crc32c_update(buffer, size, crc);
     292             : 
     293          16 :         buffer += offset + sizeof(sb->header.crc);
     294          16 :         if (sb->header.version > FTL_SB_VERSION_2) {
     295             :                 /* whole buf for v3 and on: */
     296          12 :                 size = FTL_SUPERBLOCK_SIZE - offset - sizeof(sb->header.crc);
     297          12 :                 crc = spdk_crc32c_update(buffer, size, crc);
     298             :         } else {
     299             :                 /* special for sb v2 only: */
     300           4 :                 size = sizeof(struct ftl_superblock_v2) - offset - sizeof(sb->header.crc);
     301           4 :                 sb->header.crc = spdk_crc32c_update(buffer, size, crc);
     302             :         }
     303             : 
     304          16 :         return crc;
     305             : }
     306             : 
     307             : static void
     308           0 : ftl_mngt_persist_super_block(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     309             : {
     310           0 :         dev->sb->overprovisioning = dev->conf.overprovisioning;
     311           0 :         dev->sb->gc_info = dev->sb_shm->gc_info;
     312           0 :         dev->sb->header.crc = get_sb_crc(dev->sb);
     313           0 :         persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB);
     314           0 : }
     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           0 : ftl_mngt_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     353             : {
     354           0 :         ftl_mngt_call_process(mngt, &desc_persist);
     355           0 : }
     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           0 : ftl_mngt_fast_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     374             : {
     375           0 :         ftl_mngt_call_process(mngt, &desc_fast_persist);
     376           0 : }
     377             : 
     378             : void
     379           5 : ftl_mngt_init_default_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     380             : {
     381           5 :         struct ftl_superblock *sb = dev->sb;
     382             : 
     383           5 :         sb->header.magic = FTL_SUPERBLOCK_MAGIC;
     384           5 :         sb->header.version = FTL_SB_VERSION_CURRENT;
     385           5 :         sb->uuid = dev->conf.uuid;
     386           5 :         sb->clean = 0;
     387           5 :         dev->sb_shm->shm_clean = false;
     388           5 :         sb->ckpt_seq_id = 0;
     389             : 
     390             :         /* Max 16 IO depth per band relocate */
     391           5 :         sb->max_reloc_qdepth = 16;
     392             : 
     393           5 :         sb->overprovisioning = dev->conf.overprovisioning;
     394             : 
     395           5 :         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           5 :         spdk_strcpy_pad(sb->base_dev_name, dev->base_type->name,
     400             :                         SPDK_COUNTOF(sb->base_dev_name), '\0');
     401           5 :         sb->md_layout_base.df_id = FTL_DF_OBJ_ID_INVALID;
     402             : 
     403           5 :         spdk_strcpy_pad(sb->nvc_dev_name, dev->nv_cache.nvc_desc->name,
     404             :                         SPDK_COUNTOF(sb->nvc_dev_name), '\0');
     405           5 :         sb->md_layout_nvc.df_id = FTL_DF_OBJ_ID_INVALID;
     406             : 
     407           5 :         sb->header.crc = get_sb_crc(sb);
     408             : 
     409           5 :         ftl_mngt_next_step(mngt);
     410           5 : }
     411             : 
     412             : void
     413           0 : ftl_mngt_set_dirty(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     414             : {
     415           0 :         struct ftl_superblock *sb = dev->sb;
     416             : 
     417           0 :         sb->clean = 0;
     418           0 :         sb->upgrade_ready = false;
     419           0 :         dev->sb_shm->shm_clean = false;
     420           0 :         sb->header.crc = get_sb_crc(sb);
     421           0 :         persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB);
     422           0 : }
     423             : 
     424             : void
     425           0 : ftl_mngt_set_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     426             : {
     427           0 :         struct ftl_superblock *sb = dev->sb;
     428             : 
     429           0 :         sb->clean = 1;
     430           0 :         sb->upgrade_ready = dev->conf.prep_upgrade_on_shutdown;
     431           0 :         dev->sb_shm->shm_clean = false;
     432           0 :         sb->header.crc = get_sb_crc(sb);
     433           0 :         persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB);
     434             : 
     435           0 :         dev->sb_shm->shm_ready = false;
     436           0 : }
     437             : 
     438             : void
     439           0 : ftl_mngt_set_shm_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     440             : {
     441           0 :         struct ftl_superblock *sb = dev->sb;
     442             : 
     443           0 :         sb->clean = 1;
     444           0 :         dev->sb_shm->shm_clean = true;
     445           0 :         sb->header.crc = get_sb_crc(sb);
     446           0 :         ftl_mngt_next_step(mngt);
     447           0 : }
     448             : 
     449             : void
     450           0 : ftl_mngt_load_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     451             : {
     452           0 :         FTL_NOTICELOG(dev, "SHM: clean %"PRIu64", shm_clean %d\n", dev->sb->clean, dev->sb_shm->shm_clean);
     453             : 
     454           0 :         if (!ftl_fast_startup(dev)) {
     455           0 :                 restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB);
     456           0 :                 return;
     457             :         }
     458             : 
     459           0 :         FTL_DEBUGLOG(dev, "SHM: found SB\n");
     460           0 :         if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_SB)) {
     461           0 :                 ftl_mngt_fail_step(mngt);
     462           0 :                 return;
     463             :         }
     464           0 :         ftl_mngt_next_step(mngt);
     465             : }
     466             : 
     467             : void
     468           0 : ftl_mngt_validate_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     469             : {
     470           0 :         struct ftl_superblock *sb = dev->sb;
     471             : 
     472           0 :         if (!ftl_superblock_check_magic(sb)) {
     473           0 :                 FTL_ERRLOG(dev, "Invalid FTL superblock magic\n");
     474           0 :                 ftl_mngt_fail_step(mngt);
     475           0 :                 return;
     476             :         }
     477             : 
     478           0 :         if (sb->header.crc != get_sb_crc(sb)) {
     479           0 :                 FTL_ERRLOG(dev, "Invalid FTL superblock CRC\n");
     480           0 :                 ftl_mngt_fail_step(mngt);
     481           0 :                 return;
     482             :         }
     483             : 
     484           0 :         if (ftl_superblock_upgrade(dev)) {
     485           0 :                 FTL_ERRLOG(dev, "FTL superblock dirty or invalid version\n");
     486           0 :                 ftl_mngt_fail_step(mngt);
     487           0 :                 return;
     488             :         }
     489             : 
     490           0 :         if (spdk_uuid_compare(&sb->uuid, &dev->conf.uuid) != 0) {
     491           0 :                 FTL_ERRLOG(dev, "Invalid FTL superblock UUID\n");
     492           0 :                 ftl_mngt_fail_step(mngt);
     493           0 :                 return;
     494             :         }
     495             : 
     496           0 :         if (sb->lba_cnt == 0) {
     497           0 :                 FTL_ERRLOG(dev, "Invalid FTL superblock lba_cnt\n");
     498           0 :                 ftl_mngt_fail_step(mngt);
     499           0 :                 return;
     500             :         }
     501           0 :         dev->num_lbas = sb->lba_cnt;
     502             : 
     503             :         /* The sb has just been read. Validate and update the conf */
     504           0 :         if (sb->overprovisioning == 0 || sb->overprovisioning >= 100) {
     505           0 :                 FTL_ERRLOG(dev, "Invalid FTL superblock lba_rsvd\n");
     506           0 :                 ftl_mngt_fail_step(mngt);
     507           0 :                 return;
     508             :         }
     509           0 :         dev->conf.overprovisioning = sb->overprovisioning;
     510             : 
     511           0 :         if (!ftl_superblock_validate_blob_area(dev)) {
     512           0 :                 FTL_ERRLOG(dev, "Corrupted FTL superblock blob area\n");
     513           0 :                 ftl_mngt_fail_step(mngt);
     514           0 :                 return;
     515             :         }
     516             : 
     517           0 :         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           0 : 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           0 :         struct ftl_layout *layout = &dev->layout;
     559           0 :         struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB];
     560           0 :         char uuid[SPDK_UUID_STRING_LEN];
     561           0 :         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           0 :         if (dev->conf.mode & SPDK_FTL_MODE_CREATE) {
     565           0 :                 spdk_uuid_generate(&dev->conf.uuid);
     566           0 :                 spdk_uuid_fmt_lower(uuid, sizeof(uuid), &dev->conf.uuid);
     567           0 :                 FTL_NOTICELOG(dev, "Create new FTL, UUID %s\n", uuid);
     568             :         }
     569             : 
     570           0 : shm_retry:
     571             :         /* Allocate md buf */
     572           0 :         dev->sb_shm = NULL;
     573           0 :         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           0 :         if (dev->sb_shm_md == NULL) {
     577             :                 /* The first attempt may fail when trying to open SHM - try to create new */
     578           0 :                 if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) {
     579           0 :                         md_create_flags |= FTL_MD_CREATE_SHM_NEW;
     580           0 :                         goto shm_retry;
     581             :                 }
     582           0 :                 if (dev->sb_shm_md == NULL) {
     583           0 :                         ftl_mngt_fail_step(mngt);
     584           0 :                         return;
     585             :                 }
     586             :         }
     587             : 
     588           0 :         dev->sb_shm = ftl_md_get_buffer(dev->sb_shm_md);
     589             : 
     590             :         /* Setup the layout of a superblock */
     591           0 :         if (ftl_layout_setup_superblock(dev)) {
     592           0 :                 ftl_mngt_fail_step(mngt);
     593           0 :                 return;
     594             :         }
     595             : 
     596             :         /* Allocate md buf */
     597           0 :         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           0 :         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           0 :                 if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) {
     603           0 :                         md_create_flags |= FTL_MD_CREATE_SHM_NEW;
     604           0 :                         ftl_md_destroy(dev->sb_shm_md, 0);
     605           0 :                         dev->sb_shm_md = NULL;
     606           0 :                         if (ftl_layout_clear_superblock(dev)) {
     607           0 :                                 ftl_mngt_fail_step(mngt);
     608           0 :                                 return;
     609             :                         }
     610           0 :                         goto shm_retry;
     611             :                 }
     612           0 :                 ftl_mngt_fail_step(mngt);
     613           0 :                 return;
     614             :         }
     615             : 
     616             :         /* Link the md buf to the device */
     617           0 :         dev->sb = ftl_md_get_buffer(layout->md[FTL_LAYOUT_REGION_TYPE_SB]);
     618             : 
     619             :         /* Setup superblock mirror to QLC */
     620           0 :         region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB_BASE];
     621           0 :         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           0 :         if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) {
     624           0 :                 ftl_mngt_fail_step(mngt);
     625           0 :                 return;
     626             :         }
     627             : 
     628             :         /* Initialize mirror region buffer */
     629           0 :         md = layout->md[FTL_LAYOUT_REGION_TYPE_SB];
     630           0 :         md_mirror = layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE];
     631             : 
     632           0 :         md_mirror->dev = md->dev;
     633           0 :         md_mirror->data_blocks = md->data_blocks;
     634           0 :         md_mirror->data = md->data;
     635           0 :         md_mirror->is_mirror = true;
     636             : 
     637             :         /* Initialize the superblock */
     638           0 :         if (dev->conf.mode & SPDK_FTL_MODE_CREATE) {
     639           0 :                 ftl_mngt_call_process(mngt, &desc_init_sb);
     640             :         } else {
     641           0 :                 ftl_mngt_call_process(mngt, &desc_restore_sb);
     642             :         }
     643             : }
     644             : 
     645             : void
     646           0 : ftl_mngt_superblock_deinit(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     647             : {
     648           0 :         struct ftl_layout *layout = &dev->layout;
     649             : 
     650           0 :         if (layout->md[FTL_LAYOUT_REGION_TYPE_SB]) {
     651           0 :                 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB],
     652             :                                ftl_md_destroy_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB));
     653           0 :                 layout->md[FTL_LAYOUT_REGION_TYPE_SB] = NULL;
     654             :         }
     655             : 
     656           0 :         if (layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) {
     657           0 :                 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE], 0);
     658           0 :                 layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = NULL;
     659             :         }
     660             : 
     661           0 :         ftl_md_destroy(dev->sb_shm_md, ftl_md_destroy_shm_flags(dev));
     662           0 :         dev->sb_shm_md = NULL;
     663           0 :         dev->sb_shm = NULL;
     664             : 
     665           0 :         ftl_mngt_next_step(mngt);
     666           0 : }
     667             : 
     668             : static void
     669           0 : ftl_mngt_restore_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     670             : {
     671           0 :         if (ftl_fast_startup(dev)) {
     672           0 :                 FTL_DEBUGLOG(dev, "SHM: found nv cache md\n");
     673           0 :                 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_NVC_MD)) {
     674           0 :                         ftl_mngt_fail_step(mngt);
     675           0 :                         return;
     676             :                 }
     677           0 :                 ftl_mngt_next_step(mngt);
     678           0 :                 return;
     679             :         }
     680           0 :         restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_NVC_MD);
     681             : }
     682             : 
     683             : static void
     684           0 : ftl_mngt_restore_vld_map_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     685             : {
     686           0 :         if (ftl_fast_startup(dev)) {
     687           0 :                 FTL_DEBUGLOG(dev, "SHM: found vldmap\n");
     688           0 :                 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_VALID_MAP)) {
     689           0 :                         ftl_mngt_fail_step(mngt);
     690           0 :                         return;
     691             :                 }
     692           0 :                 ftl_mngt_next_step(mngt);
     693           0 :                 return;
     694             :         }
     695           0 :         restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_VALID_MAP);
     696             : }
     697             : 
     698             : static void
     699           0 : ftl_mngt_restore_band_info_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     700             : {
     701           0 :         if (ftl_fast_startup(dev)) {
     702           0 :                 FTL_DEBUGLOG(dev, "SHM: found band md\n");
     703           0 :                 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_BAND_MD)) {
     704           0 :                         ftl_mngt_fail_step(mngt);
     705           0 :                         return;
     706             :                 }
     707           0 :                 ftl_mngt_next_step(mngt);
     708           0 :                 return;
     709             :         }
     710           0 :         restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_BAND_MD);
     711             : }
     712             : 
     713             : static void
     714           0 : ftl_mngt_restore_trim_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     715             : {
     716           0 :         if (ftl_fast_startup(dev)) {
     717           0 :                 FTL_DEBUGLOG(dev, "SHM: found trim md\n");
     718           0 :                 if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_TRIM_MD)) {
     719           0 :                         ftl_mngt_fail_step(mngt);
     720           0 :                         return;
     721             :                 }
     722           0 :                 ftl_mngt_next_step(mngt);
     723           0 :                 return;
     724             :         }
     725           0 :         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           0 : ftl_mngt_restore_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     756             : {
     757           0 :         ftl_mngt_call_process(mngt, &desc_restore);
     758           0 : }
     759             : 
     760             : void
     761           0 : ftl_mngt_persist_superblock(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     762             : {
     763           0 :         dev->sb->header.crc = get_sb_crc(dev->sb);
     764           0 :         persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB);
     765           0 : }

Generated by: LCOV version 1.15