LCOV - code coverage report
Current view: top level - spdk/lib/ftl/upgrade - ftl_layout_upgrade.c (source / functions) Hit Total Coverage
Test: Combined Lines: 92 127 72.4 %
Date: 2024-07-12 10:05:37 Functions: 11 14 78.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 44 96 45.8 %

           Branch data     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/assert.h"
       8                 :            : 
       9                 :            : #include "ftl_layout_upgrade.h"
      10                 :            : #include "ftl_layout.h"
      11                 :            : #include "ftl_sb_current.h"
      12                 :            : #include "ftl_sb_prev.h"
      13                 :            : #include "ftl_core.h"
      14                 :            : #include "ftl_band.h"
      15                 :            : #include "utils/ftl_layout_tracker_bdev.h"
      16                 :            : 
      17                 :            : int
      18                 :          0 : ftl_region_major_upgrade_enabled(struct spdk_ftl_dev *dev, struct ftl_layout_region *region)
      19                 :            : {
      20         [ #  # ]:          0 :         if (ftl_region_upgrade_enabled(dev, region)) {
      21                 :          0 :                 return -1;
      22                 :            :         }
      23                 :            : 
      24         [ #  # ]:          0 :         if (dev->sb->upgrade_ready) {
      25                 :          0 :                 return 0;
      26                 :            :         } else {
      27         [ #  # ]:          0 :                 FTL_ERRLOG(dev, "FTL major upgrade ERROR, required upgrade shutdown in the previous version\n");
      28                 :          0 :                 return -1;
      29                 :            :         }
      30                 :            : }
      31                 :            : 
      32                 :            : int
      33                 :          0 : ftl_region_upgrade_disabled(struct spdk_ftl_dev *dev, struct ftl_layout_region *region)
      34                 :            : {
      35                 :          0 :         return -1;
      36                 :            : }
      37                 :            : 
      38                 :            : int
      39                 :         18 : ftl_region_upgrade_enabled(struct spdk_ftl_dev *dev, struct ftl_layout_region *region)
      40                 :            : {
      41   [ +  -  -  +  :         18 :         if (!(dev->sb->clean == 1 && dev->sb_shm->shm_clean == 0)) {
                   -  + ]
      42         [ #  # ]:          0 :                 FTL_ERRLOG(dev, "FTL region upgrade: SB dirty\n");
      43                 :          0 :                 return -1;
      44                 :            :         }
      45                 :         18 :         return 0;
      46                 :            : }
      47                 :            : 
      48                 :            : #ifndef UTEST
      49                 :            : extern struct ftl_region_upgrade_desc sb_upgrade_desc[];
      50                 :            : extern struct ftl_region_upgrade_desc p2l_upgrade_desc[];
      51                 :            : extern struct ftl_region_upgrade_desc nvc_upgrade_desc[];
      52                 :            : extern struct ftl_region_upgrade_desc band_upgrade_desc[];
      53                 :            : extern struct ftl_region_upgrade_desc trim_log_upgrade_desc[];
      54                 :            : 
      55                 :            : static struct ftl_layout_upgrade_desc_list layout_upgrade_desc[] = {
      56                 :            :         [FTL_LAYOUT_REGION_TYPE_SB] = {
      57                 :            :                 .latest_ver = FTL_SB_VERSION_CURRENT,
      58                 :            :                 .count = FTL_SB_VERSION_CURRENT,
      59                 :            :                 .desc = sb_upgrade_desc,
      60                 :            :         },
      61                 :            :         [FTL_LAYOUT_REGION_TYPE_SB_BASE] = {
      62                 :            :                 .latest_ver = FTL_SB_VERSION_CURRENT,
      63                 :            :                 .count = FTL_SB_VERSION_CURRENT,
      64                 :            :                 .desc = sb_upgrade_desc,
      65                 :            :         },
      66                 :            :         [FTL_LAYOUT_REGION_TYPE_L2P] = {},
      67                 :            :         [FTL_LAYOUT_REGION_TYPE_BAND_MD] = {
      68                 :            :                 .latest_ver = FTL_BAND_VERSION_CURRENT,
      69                 :            :                 .count = FTL_BAND_VERSION_CURRENT,
      70                 :            :                 .desc = band_upgrade_desc,
      71                 :            :         },
      72                 :            :         [FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR] = {
      73                 :            :                 .latest_ver = FTL_BAND_VERSION_CURRENT,
      74                 :            :                 .count = FTL_BAND_VERSION_CURRENT,
      75                 :            :                 .desc = band_upgrade_desc,
      76                 :            :         },
      77                 :            :         [FTL_LAYOUT_REGION_TYPE_VALID_MAP] = {},
      78                 :            :         [FTL_LAYOUT_REGION_TYPE_NVC_MD] = {
      79                 :            :                 .latest_ver = FTL_NVC_VERSION_CURRENT,
      80                 :            :                 .count = FTL_NVC_VERSION_CURRENT,
      81                 :            :                 .desc = nvc_upgrade_desc,
      82                 :            :         },
      83                 :            :         [FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR] = {
      84                 :            :                 .latest_ver = FTL_NVC_VERSION_CURRENT,
      85                 :            :                 .count = FTL_NVC_VERSION_CURRENT,
      86                 :            :                 .desc = nvc_upgrade_desc,
      87                 :            :         },
      88                 :            :         [FTL_LAYOUT_REGION_TYPE_DATA_NVC] = {},
      89                 :            :         [FTL_LAYOUT_REGION_TYPE_DATA_BASE] = {},
      90                 :            :         [FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC] = {
      91                 :            :                 .latest_ver = FTL_P2L_VERSION_CURRENT,
      92                 :            :                 .count = FTL_P2L_VERSION_CURRENT,
      93                 :            :                 .desc = p2l_upgrade_desc,
      94                 :            :         },
      95                 :            :         [FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC_NEXT] = {
      96                 :            :                 .latest_ver = FTL_P2L_VERSION_CURRENT,
      97                 :            :                 .count = FTL_P2L_VERSION_CURRENT,
      98                 :            :                 .desc = p2l_upgrade_desc,
      99                 :            :         },
     100                 :            :         [FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP] = {
     101                 :            :                 .latest_ver = FTL_P2L_VERSION_CURRENT,
     102                 :            :                 .count = FTL_P2L_VERSION_CURRENT,
     103                 :            :                 .desc = p2l_upgrade_desc,
     104                 :            :         },
     105                 :            :         [FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP_NEXT] = {
     106                 :            :                 .latest_ver = FTL_P2L_VERSION_CURRENT,
     107                 :            :                 .count = FTL_P2L_VERSION_CURRENT,
     108                 :            :                 .desc = p2l_upgrade_desc,
     109                 :            :         },
     110                 :            :         [FTL_LAYOUT_REGION_TYPE_TRIM_MD] = {},
     111                 :            :         [FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR] = {},
     112                 :            : 
     113                 :            :         [FTL_LAYOUT_REGION_TYPE_TRIM_LOG] = {
     114                 :            :                 .latest_ver = FTL_TRIM_LOG_VERSION_CURRENT,
     115                 :            :                 .count = FTL_TRIM_LOG_VERSION_CURRENT,
     116                 :            :                 .desc = trim_log_upgrade_desc,
     117                 :            :         },
     118                 :            :         [FTL_LAYOUT_REGION_TYPE_TRIM_LOG_MIRROR] = {
     119                 :            :                 .latest_ver = FTL_TRIM_LOG_VERSION_CURRENT,
     120                 :            :                 .count = FTL_TRIM_LOG_VERSION_CURRENT,
     121                 :            :                 .desc = trim_log_upgrade_desc,
     122                 :            :         },
     123                 :            : };
     124                 :            : 
     125                 :            : SPDK_STATIC_ASSERT(sizeof(layout_upgrade_desc) / sizeof(*layout_upgrade_desc) ==
     126                 :            :                    FTL_LAYOUT_REGION_TYPE_MAX,
     127                 :            :                    "Missing layout upgrade descriptors");
     128                 :            : #endif
     129                 :            : 
     130                 :            : uint64_t
     131                 :        357 : ftl_layout_upgrade_get_latest_version(enum ftl_layout_region_type reg_type)
     132                 :            : {
     133         [ -  + ]:        357 :         assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX);
     134                 :        357 :         return layout_upgrade_desc[reg_type].latest_ver;
     135                 :            : }
     136                 :            : 
     137                 :            : static int
     138                 :        588 : region_verify(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *ctx)
     139                 :            : {
     140                 :            :         uint64_t ver;
     141                 :            : 
     142         [ -  + ]:        588 :         assert(ctx->reg);
     143                 :        588 :         ver = ctx->reg->current.version;
     144         [ -  + ]:        588 :         if (ver > ctx->upgrade->latest_ver) {
     145         [ #  # ]:          0 :                 FTL_ERRLOG(dev, "Unknown region version\n");
     146                 :          0 :                 return -1;
     147                 :            :         }
     148                 :            : 
     149         [ +  + ]:        606 :         while (ver < ctx->upgrade->latest_ver) {
     150                 :         18 :                 int rc = ctx->upgrade->desc[ver].verify(dev, ctx->reg);
     151         [ -  + ]:         18 :                 if (rc) {
     152                 :          0 :                         return rc;
     153                 :            :                 }
     154         [ -  + ]:         18 :                 ftl_bug(ver > ctx->upgrade->desc[ver].new_version);
     155         [ -  + ]:         18 :                 ftl_bug(ctx->upgrade->desc[ver].new_version > ctx->upgrade->latest_ver);
     156                 :         18 :                 ver = ctx->upgrade->desc[ver].new_version;
     157                 :            :         }
     158                 :        588 :         return 0;
     159                 :            : }
     160                 :            : 
     161                 :            : int
     162                 :         18 : ftl_region_upgrade(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *ctx)
     163                 :            : {
     164                 :         18 :         int rc = 0;
     165                 :            :         uint64_t ver;
     166                 :            : 
     167         [ -  + ]:         18 :         assert(ctx->reg);
     168         [ -  + ]:         18 :         assert(ctx->reg->current.version <= ctx->upgrade->latest_ver);
     169                 :         18 :         ver = ctx->reg->current.version;
     170         [ +  - ]:         18 :         if (ver < ctx->upgrade->latest_ver) {
     171                 :         18 :                 ctx->next_reg_ver = ctx->upgrade->desc[ver].new_version;
     172                 :         18 :                 rc = ctx->upgrade->desc[ver].upgrade(dev, ctx);
     173                 :            :         }
     174                 :         18 :         return rc;
     175                 :            : }
     176                 :            : 
     177                 :            : void
     178                 :         18 : ftl_region_upgrade_completed(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *ctx,
     179                 :            :                              uint64_t entry_size, uint64_t num_entries, int status)
     180                 :            : {
     181                 :            :         int rc;
     182                 :            : 
     183         [ -  + ]:         18 :         assert(ctx->reg);
     184         [ -  + ]:         18 :         assert(ctx->reg->current.version < ctx->next_reg_ver);
     185         [ -  + ]:         18 :         assert(ctx->next_reg_ver <= ctx->upgrade->latest_ver);
     186                 :            : 
     187         [ +  - ]:         18 :         if (!status) {
     188         [ +  - ]:         18 :                 if (ctx->reg->type != FTL_LAYOUT_REGION_TYPE_SB) {
     189                 :            :                         /* Superblock region is always default-created in the latest version - see ftl_layout_setup_superblock() */
     190                 :         18 :                         rc = ftl_superblock_md_layout_upgrade_region(dev, ctx->reg, ctx->next_reg_ver);
     191   [ +  +  +  - ]:         18 :                         if (entry_size && num_entries) {
     192                 :          6 :                                 dev->layout.region[ctx->reg->type].entry_size = entry_size;
     193                 :          6 :                                 dev->layout.region[ctx->reg->type].num_entries = num_entries;
     194                 :            :                         }
     195                 :            : 
     196         [ -  + ]:         18 :                         ftl_bug(rc != 0);
     197                 :            :                 }
     198                 :            : 
     199                 :         18 :                 ctx->reg->current.version = ctx->next_reg_ver;
     200                 :            :         }
     201                 :            : 
     202         [ -  + ]:         18 :         if (ctx->cb) {
     203                 :          0 :                 ctx->cb(dev, ctx->cb_ctx, status);
     204                 :            :         }
     205                 :         18 : }
     206                 :            : 
     207                 :            : int
     208                 :         27 : ftl_layout_verify(struct spdk_ftl_dev *dev)
     209                 :            : {
     210                 :         27 :         struct ftl_layout *layout = &dev->layout;
     211                 :         27 :         struct ftl_layout_upgrade_ctx ctx = {0};
     212                 :            :         enum ftl_layout_region_type reg_type;
     213                 :            : 
     214                 :            :         /**
     215                 :            :          * Upon SB upgrade some MD regions may be missing in the MD layout blob - e.g. v3 to v5, FTL_LAYOUT_REGION_TYPE_DATA_BASE.
     216                 :            :          * The regions couldn't have be added in the SB upgrade path, as the FTL layout wasn't initialized at that point.
     217                 :            :          * Now that the FTL layout is initialized, add the missing regions and store the MD layout blob again.
     218                 :            :          */
     219                 :            : 
     220         [ -  + ]:         27 :         if (ftl_validate_regions(dev, layout)) {
     221                 :          0 :                 return -1;
     222                 :            :         }
     223                 :            : 
     224         [ +  + ]:        513 :         for (reg_type = 0; reg_type < FTL_LAYOUT_REGION_TYPE_MAX; reg_type++) {
     225                 :        486 :                 ctx.reg = ftl_layout_region_get(dev, reg_type);
     226                 :        486 :                 ctx.upgrade = &layout_upgrade_desc[reg_type];
     227         [ +  + ]:        486 :                 if (!ctx.reg) {
     228                 :         27 :                         continue;
     229                 :            :                 }
     230                 :            : 
     231         [ -  + ]:        459 :                 if (region_verify(dev, &ctx)) {
     232                 :          0 :                         return -1;
     233                 :            :                 }
     234                 :            :         }
     235                 :            : 
     236                 :         27 :         return 0;
     237                 :            : }
     238                 :            : 
     239                 :            : int
     240                 :         27 : ftl_upgrade_layout_dump(struct spdk_ftl_dev *dev)
     241                 :            : {
     242         [ -  + ]:         27 :         if (ftl_validate_regions(dev, &dev->layout)) {
     243                 :          0 :                 return -1;
     244                 :            :         }
     245                 :            : 
     246                 :         27 :         ftl_layout_dump(dev);
     247                 :         27 :         ftl_superblock_md_layout_dump(dev);
     248                 :         27 :         return 0;
     249                 :            : }
     250                 :            : 
     251                 :            : int
     252                 :         21 : ftl_superblock_upgrade(struct spdk_ftl_dev *dev)
     253                 :            : {
     254                 :         21 :         struct ftl_layout_upgrade_ctx ctx = {0};
     255                 :         21 :         struct ftl_layout_region *reg = ftl_layout_region_get(dev, FTL_LAYOUT_REGION_TYPE_SB);
     256                 :            :         int rc;
     257                 :            : 
     258                 :         21 :         ctx.reg = reg;
     259                 :         21 :         ctx.upgrade = &layout_upgrade_desc[FTL_LAYOUT_REGION_TYPE_SB];
     260                 :         21 :         reg->current.version = dev->sb->header.version;
     261                 :            : 
     262                 :         21 :         rc = region_verify(dev, &ctx);
     263         [ -  + ]:         21 :         if (rc) {
     264                 :          0 :                 return rc;
     265                 :            :         }
     266                 :            : 
     267         [ -  + ]:         21 :         while (reg->current.version < ctx.upgrade->latest_ver) {
     268                 :          0 :                 rc = ftl_region_upgrade(dev, &ctx);
     269         [ #  # ]:          0 :                 if (rc) {
     270                 :          0 :                         return rc;
     271                 :            :                 }
     272                 :            :                 /* SB upgrades are all synchronous */
     273                 :          0 :                 ftl_region_upgrade_completed(dev, &ctx, 0, 0, rc);
     274                 :            :         }
     275                 :            : 
     276                 :            :         /* The mirror shares the same DMA buf, so it is automatically updated upon SB store */
     277                 :         21 :         dev->layout.region[FTL_LAYOUT_REGION_TYPE_SB_BASE].current.version = reg->current.version;
     278                 :         21 :         return 0;
     279                 :            : }
     280                 :            : 
     281                 :            : static int
     282                 :         57 : layout_upgrade_select_next_region(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *ctx)
     283                 :            : {
     284                 :            :         struct ftl_layout_region *reg;
     285                 :            :         uint64_t reg_ver, reg_latest_ver;
     286                 :         57 :         uint32_t reg_type = ctx->reg->type;
     287                 :            : 
     288         [ +  - ]:        720 :         while (reg_type != FTL_LAYOUT_REGION_TYPE_MAX) {
     289         [ -  + ]:        720 :                 assert(ctx->reg);
     290         [ -  + ]:        720 :                 assert(ctx->upgrade);
     291                 :        720 :                 reg = ctx->reg;
     292                 :        720 :                 reg_latest_ver = ctx->upgrade->latest_ver;
     293                 :        720 :                 reg_ver = reg->current.version;
     294                 :            : 
     295   [ +  +  -  + ]:        720 :                 if (reg_ver == reg_latest_ver || reg->type == FTL_LAYOUT_REGION_TYPE_INVALID) {
     296                 :            :                         /* select the next region to upgrade */
     297                 :        702 :                         reg_type++;
     298         [ +  + ]:        702 :                         if (reg_type == FTL_LAYOUT_REGION_TYPE_MAX) {
     299                 :         39 :                                 break;
     300                 :            :                         }
     301                 :        663 :                         ctx->reg++;
     302                 :        663 :                         ctx->upgrade++;
     303         [ +  - ]:         18 :                 } else if (reg_ver < reg_latest_ver) {
     304                 :            :                         /* qualify region version to upgrade */
     305                 :         18 :                         return FTL_LAYOUT_UPGRADE_CONTINUE;
     306                 :            :                 } else {
     307                 :            :                         /* unknown version */
     308         [ #  # ]:          0 :                         assert(reg_ver <= reg_latest_ver);
     309         [ #  # ]:          0 :                         FTL_ERRLOG(dev, "Region %d upgrade fault: version %"PRIu64"/%"PRIu64"\n", reg_type, reg_ver,
     310                 :            :                                    reg_latest_ver);
     311                 :          0 :                         return FTL_LAYOUT_UPGRADE_FAULT;
     312                 :            :                 }
     313                 :            :         }
     314                 :            : 
     315                 :         39 :         return FTL_LAYOUT_UPGRADE_DONE;
     316                 :            : }
     317                 :            : 
     318                 :            : int
     319                 :         27 : ftl_layout_upgrade_init_ctx(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *ctx)
     320                 :            : {
     321         [ +  - ]:         27 :         if (!ctx->reg) {
     322                 :         27 :                 ctx->reg = ftl_layout_region_get(dev, 0);
     323                 :         27 :                 ctx->upgrade = &layout_upgrade_desc[0];
     324                 :            :                 SPDK_STATIC_ASSERT(FTL_LAYOUT_REGION_TYPE_SB == 0, "Invalid SB region type");
     325                 :            :         }
     326                 :            : 
     327                 :         27 :         return layout_upgrade_select_next_region(dev, ctx);
     328                 :            : }
     329                 :            : 
     330                 :            : uint64_t
     331                 :        246 : ftl_layout_upgrade_region_get_latest_version(enum ftl_layout_region_type reg_type)
     332                 :            : {
     333         [ -  + ]:        246 :         assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX);
     334                 :        246 :         return layout_upgrade_desc[reg_type].latest_ver;
     335                 :            : }
     336                 :            : 
     337                 :            : int
     338                 :          0 : ftl_layout_upgrade_drop_region(struct spdk_ftl_dev *dev,
     339                 :            :                                struct ftl_layout_tracker_bdev *layout_tracker,
     340                 :            :                                enum ftl_layout_region_type reg_type, uint32_t reg_ver)
     341                 :            : {
     342                 :          0 :         const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
     343                 :          0 :         int rc = ftl_layout_tracker_bdev_rm_region(layout_tracker, reg_type, reg_ver);
     344                 :            : 
     345                 :          0 :         ftl_layout_tracker_bdev_find_next_region(layout_tracker, reg_type, &reg_search_ctx);
     346         [ #  # ]:          0 :         if (reg_search_ctx) {
     347         [ #  # ]:          0 :                 FTL_ERRLOG(dev,
     348                 :            :                            "Error when dropping region type %"PRId32", ver %"PRIu32": rc:%"PRId32" but found reg ver %"PRIu32"\n",
     349                 :            :                            reg_type, reg_ver, rc, reg_search_ctx->ver);
     350                 :          0 :                 return -1;
     351                 :            :         }
     352                 :          0 :         dev->layout.region[reg_type].type = FTL_LAYOUT_REGION_TYPE_INVALID;
     353                 :          0 :         return 0;
     354                 :            : }

Generated by: LCOV version 1.14