LCOV - code coverage report
Current view: top level - spdk/lib/ftl/upgrade - ftl_sb_upgrade.c (source / functions) Hit Total Coverage
Test: Combined Lines: 6 71 8.5 %
Date: 2024-07-15 18:50:15 Functions: 1 5 20.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 2 64 3.1 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2022 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "ftl_sb_upgrade.h"
       7                 :            : #include "ftl_layout_upgrade.h"
       8                 :            : #include "ftl_layout.h"
       9                 :            : #include "ftl_core.h"
      10                 :            : #include "ftl_sb_v3.h"
      11                 :            : #include "utils/ftl_df.h"
      12                 :            : #include "utils/ftl_layout_tracker_bdev.h"
      13                 :            : 
      14                 :            : static int
      15                 :          0 : sb_v4_to_v5_verify(struct spdk_ftl_dev *dev, struct ftl_layout_region *region)
      16                 :            : {
      17                 :            :         struct ftl_layout_region *reg;
      18                 :            :         uint32_t reg_no;
      19                 :          0 :         int rc = ftl_region_upgrade_enabled(dev, region);
      20                 :            : 
      21         [ #  # ]:          0 :         if (rc) {
      22                 :          0 :                 return rc;
      23                 :            :         }
      24                 :            : 
      25                 :            :         /* Verify there are no pending major upgrades */
      26         [ #  # ]:          0 :         for (reg_no = 0; reg_no < FTL_LAYOUT_REGION_TYPE_MAX; reg_no++) {
      27                 :          0 :                 reg = ftl_layout_region_get(dev, reg_no);
      28         [ #  # ]:          0 :                 if (!reg) {
      29                 :            :                         /* This region does not exist */
      30                 :          0 :                         continue;
      31                 :            :                 }
      32                 :            : 
      33         [ #  # ]:          0 :                 if (reg->current.version <= ftl_layout_upgrade_region_get_latest_version(reg->type)) {
      34                 :            :                         /* Only latest region version found */
      35                 :          0 :                         continue;
      36                 :            :                 }
      37                 :            : 
      38                 :            :                 /* Previous version found, major upgrade */
      39         [ #  # ]:          0 :                 FTL_WARNLOG(dev, "FTL superblock upgrade v4 to v5 disabled: " \
      40                 :            :                             "cannot upgrade region type 0x%"PRIx32" v%"PRId64" to v%"PRId64", " \
      41                 :            :                             "offs 0x%"PRIx64", blks 0x%"PRIx64"\n",
      42                 :            :                             reg->type, reg->current.version, ftl_layout_upgrade_region_get_latest_version(reg->type),
      43                 :            :                             reg->current.offset, reg->current.blocks);
      44                 :          0 :                 return -1;
      45                 :            :         }
      46                 :            : 
      47                 :          0 :         return 0;
      48                 :            : }
      49                 :            : 
      50                 :            : static bool
      51                 :          0 : sb_v3_md_region_is_fixed(int reg_type)
      52                 :            : {
      53         [ #  # ]:          0 :         switch (reg_type) {
      54                 :          0 :         case FTL_LAYOUT_REGION_TYPE_SB:
      55                 :            :         case FTL_LAYOUT_REGION_TYPE_SB_BASE:
      56                 :            :         case FTL_LAYOUT_REGION_TYPE_DATA_BASE:
      57                 :          0 :                 return true;
      58                 :            : 
      59                 :          0 :         default:
      60                 :          0 :                 return false;
      61                 :            :         }
      62                 :            : }
      63                 :            : 
      64                 :            : static bool
      65                 :        324 : sb_v3_md_region_is_nvc(int reg_type)
      66                 :            : {
      67         [ +  + ]:        324 :         switch (reg_type) {
      68                 :         54 :         case FTL_LAYOUT_REGION_TYPE_SB_BASE:
      69                 :            :         case FTL_LAYOUT_REGION_TYPE_VALID_MAP:
      70                 :            :         case FTL_LAYOUT_REGION_TYPE_DATA_BASE:
      71                 :         54 :                 return false;
      72                 :            : 
      73                 :        270 :         default:
      74                 :        270 :                 return true;
      75                 :            :         }
      76                 :            : }
      77                 :            : 
      78                 :            : static int
      79                 :          0 : sb_v3_md_layout_convert(struct spdk_ftl_dev *dev)
      80                 :            : {
      81                 :          0 :         struct ftl_superblock_v3 *sb = (struct ftl_superblock_v3 *)dev->sb;
      82                 :          0 :         struct ftl_superblock_v3_md_region *sb_reg = &sb->md_layout_head;
      83                 :            :         const struct ftl_layout_tracker_bdev_region_props *reg_props;
      84                 :            : 
      85         [ #  # ]:          0 :         while (sb_reg->type != FTL_LAYOUT_REGION_TYPE_INVALID) {
      86         [ #  # ]:          0 :                 if (sb_reg->type == FTL_LAYOUT_REGION_TYPE_FREE_NVC ||
      87         [ #  # ]:          0 :                     sb_reg->type == FTL_LAYOUT_REGION_TYPE_FREE_BASE) {
      88                 :          0 :                         goto next_sb_reg;
      89                 :            :                 }
      90                 :            : 
      91         [ #  # ]:          0 :                 if (sb_reg->type >= FTL_LAYOUT_REGION_TYPE_MAX) {
      92         [ #  # ]:          0 :                         FTL_ERRLOG(dev, "Invalid MD region type found\n");
      93                 :          0 :                         return -1;
      94                 :            :                 }
      95                 :            : 
      96         [ #  # ]:          0 :                 if (sb_v3_md_region_is_fixed(sb_reg->type)) {
      97         [ #  # ]:          0 :                         FTL_ERRLOG(dev, "Unsupported MD region type found\n");
      98                 :          0 :                         return -1;
      99                 :            :                 }
     100                 :            : 
     101         [ #  # ]:          0 :                 if (sb_v3_md_region_is_nvc(sb_reg->type)) {
     102                 :          0 :                         reg_props = ftl_layout_tracker_bdev_insert_region(dev->nvc_layout_tracker, sb_reg->type,
     103                 :            :                                         sb_reg->version, sb_reg->blk_offs, sb_reg->blk_sz);
     104                 :            :                 } else {
     105                 :          0 :                         reg_props = ftl_layout_tracker_bdev_insert_region(dev->base_layout_tracker, sb_reg->type,
     106                 :            :                                         sb_reg->version, sb_reg->blk_offs, sb_reg->blk_sz);
     107                 :            :                 }
     108         [ #  # ]:          0 :                 if (!reg_props) {
     109         [ #  # ]:          0 :                         FTL_ERRLOG(dev, "Cannot upgrade SB MD layout - region type 0x%"PRIx32" v%"PRId32" " \
     110                 :            :                                    "offs 0x%"PRIx64" blks 0x%"PRIx64"\n",
     111                 :            :                                    sb_reg->type, sb_reg->version, sb_reg->blk_offs, sb_reg->blk_sz);
     112                 :            :                 }
     113                 :            : 
     114                 :          0 : next_sb_reg:
     115         [ #  # ]:          0 :                 if (sb_reg->df_next == FTL_DF_OBJ_ID_INVALID) {
     116                 :          0 :                         break;
     117                 :            :                 }
     118                 :            : 
     119         [ #  # ]:          0 :                 if (UINT64_MAX - (uintptr_t)sb <= sb_reg->df_next) {
     120         [ #  # ]:          0 :                         FTL_ERRLOG(dev, "Buffer overflow\n");
     121                 :          0 :                         return -EOVERFLOW;
     122                 :            :                 }
     123                 :            : 
     124                 :          0 :                 sb_reg = ftl_df_get_obj_ptr(sb, sb_reg->df_next);
     125         [ #  # ]:          0 :                 if (ftl_superblock_v3_md_region_overflow(dev, sb_reg)) {
     126         [ #  # ]:          0 :                         FTL_ERRLOG(dev, "Buffer overflow\n");
     127                 :          0 :                         return -EOVERFLOW;
     128                 :            :                 }
     129                 :            :         }
     130                 :            : 
     131                 :          0 :         return 0;
     132                 :            : }
     133                 :            : 
     134                 :            : static int
     135                 :          0 : sb_v4_to_v5_upgrade(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *ctx)
     136                 :            : {
     137                 :          0 :         union ftl_superblock_ver *sb = (union ftl_superblock_ver *)dev->sb;
     138                 :            : 
     139         [ #  # ]:          0 :         FTL_NOTICELOG(dev, "FTL superblock upgrade v4 to v5\n");
     140                 :            : 
     141                 :            :         /* Convert v3 MD layout */
     142         [ #  # ]:          0 :         if (ftl_superblock_is_blob_area_empty(dev->sb)) {
     143         [ #  # ]:          0 :                 FTL_ERRLOG(dev, "SBv3 MD layout empty\n");
     144                 :          0 :                 return -1;
     145                 :            :         }
     146         [ #  # ]:          0 :         if (sb_v3_md_layout_convert(dev)) {
     147         [ #  # ]:          0 :                 FTL_ERRLOG(dev, "SBv3 MD layout load failed\n");
     148                 :          0 :                 return -1;
     149                 :            :         }
     150                 :            : 
     151                 :            :         /* Bump up the version */
     152                 :          0 :         sb->v5.header.version = FTL_SB_VERSION_5;
     153                 :          0 :         sb->v5.blob_area_end = 0;
     154                 :            : 
     155                 :            :         /* Keep v5 layout empty */
     156         [ #  # ]:          0 :         memset(sb->v5.nvc_dev_name, 0, sizeof(sb->v5.nvc_dev_name));
     157         [ #  # ]:          0 :         memset(&sb->v5.md_layout_nvc, 0, sizeof(sb->v5.md_layout_nvc));
     158         [ #  # ]:          0 :         memset(sb->v5.base_dev_name, 0, sizeof(sb->v5.base_dev_name));
     159         [ #  # ]:          0 :         memset(&sb->v5.md_layout_base, 0, sizeof(sb->v5.md_layout_base));
     160         [ #  # ]:          0 :         memset(&sb->v5.layout_params, 0, sizeof(sb->v5.layout_params));
     161                 :            : 
     162                 :          0 :         return 0;
     163                 :            : }
     164                 :            : 
     165                 :            : struct ftl_region_upgrade_desc sb_upgrade_desc[] = {
     166                 :            :         [FTL_SB_VERSION_0] = {.verify = ftl_region_upgrade_disabled},
     167                 :            :         [FTL_SB_VERSION_1] = {.verify = ftl_region_upgrade_disabled},
     168                 :            :         [FTL_SB_VERSION_2] = {.verify = ftl_region_upgrade_disabled},
     169                 :            :         [FTL_SB_VERSION_3] = {.verify = ftl_region_upgrade_disabled},
     170                 :            :         [FTL_SB_VERSION_4] = {.verify = sb_v4_to_v5_verify, .upgrade = sb_v4_to_v5_upgrade, .new_version = FTL_SB_VERSION_5},
     171                 :            : };
     172                 :            : 
     173                 :            : SPDK_STATIC_ASSERT(SPDK_COUNTOF(sb_upgrade_desc) == FTL_SB_VERSION_CURRENT,
     174                 :            :                    "Missing SB region upgrade descriptors");

Generated by: LCOV version 1.14