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

Generated by: LCOV version 1.15