LCOV - code coverage report
Current view: top level - spdk/lib/ftl/upgrade - ftl_layout_upgrade.c (source / functions) Hit Total Coverage
Test: Combined Lines: 88 108 81.5 %
Date: 2024-07-15 14:57:06 Functions: 10 11 90.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 42 84 50.0 %

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

Generated by: LCOV version 1.14