LCOV - code coverage report
Current view: top level - spdk/lib/ftl/upgrade - ftl_layout_upgrade.c (source / functions) Hit Total Coverage
Test: Combined Lines: 102 130 78.5 %
Date: 2024-12-15 00:31:35 Functions: 10 11 90.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 238 574 41.5 %

           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                 :         18 : ftl_region_upgrade_enabled(struct spdk_ftl_dev *dev, struct ftl_layout_region *region)
      22                 :            : {
      23   [ +  -  +  +  :         18 :         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                 :         18 :         return 0;
      28                 :          3 : }
      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                 :        465 : region_verify(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *ctx)
     102                 :            : {
     103                 :         16 :         uint64_t ver;
     104                 :            : 
     105   [ +  +  +  -  :        465 :         assert(ctx->reg);
             +  -  #  # ]
     106   [ +  -  +  -  :        465 :         ver = ctx->reg->current.version;
          +  -  +  -  +  
                      - ]
     107   [ +  +  +  -  :        465 :         if (ver > ctx->upgrade->latest_ver) {
          +  -  +  -  -  
                      + ]
     108   [ #  #  #  #  :          0 :                 FTL_ERRLOG(dev, "Unknown region version\n");
             #  #  #  # ]
     109                 :          0 :                 return -1;
     110                 :            :         }
     111                 :            : 
     112   [ +  +  +  -  :        483 :         while (ver < ctx->upgrade->latest_ver) {
          +  -  +  -  +  
                      + ]
     113   [ +  -  +  -  :         18 :                 int rc = ctx->upgrade->desc[ver].verify(dev, ctx->reg);
          +  -  +  -  +  
          -  +  -  +  -  
          -  +  +  -  +  
                -  +  - ]
     114         [ -  + ]:         18 :                 if (rc) {
     115                 :          0 :                         return rc;
     116                 :            :                 }
     117   [ +  +  +  -  :         18 :                 ftl_bug(ver > ctx->upgrade->desc[ver].new_version);
          +  -  +  -  +  
          -  +  -  +  -  
             -  +  #  # ]
     118   [ +  +  +  -  :         18 :                 ftl_bug(ctx->upgrade->desc[ver].new_version > ctx->upgrade->latest_ver);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   #  # ]
     119   [ +  -  +  -  :         18 :                 ver = ctx->upgrade->desc[ver].new_version;
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     120         [ -  + ]:          3 :         }
     121                 :        465 :         return 0;
     122                 :         16 : }
     123                 :            : 
     124                 :            : int
     125                 :         18 : ftl_region_upgrade(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *ctx)
     126                 :            : {
     127                 :         18 :         int rc = 0;
     128                 :          3 :         uint64_t ver;
     129                 :            : 
     130   [ +  +  +  -  :         18 :         assert(ctx->reg);
             +  -  #  # ]
     131   [ +  +  +  -  :         18 :         assert(ctx->reg->current.version <= ctx->upgrade->latest_ver);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  #  # ]
     132   [ +  -  +  -  :         18 :         ver = ctx->reg->current.version;
          +  -  +  -  +  
                      - ]
     133   [ +  -  +  -  :         18 :         if (ver < ctx->upgrade->latest_ver) {
          +  -  +  -  -  
                      + ]
     134   [ +  -  +  -  :         18 :                 ctx->next_reg_ver = ctx->upgrade->desc[ver].new_version;
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     135   [ +  -  +  -  :         18 :                 rc = ctx->upgrade->desc[ver].upgrade(dev, ctx);
          +  -  +  -  +  
          -  +  -  +  -  
             -  +  +  - ]
     136                 :          3 :         }
     137                 :         21 :         return rc;
     138                 :          3 : }
     139                 :            : 
     140                 :            : void
     141                 :         18 : 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                 :          3 :         int rc;
     145                 :            : 
     146   [ +  +  +  -  :         18 :         assert(ctx->reg);
             +  -  #  # ]
     147   [ +  +  +  -  :         18 :         assert(ctx->reg->current.version < ctx->next_reg_ver);
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  #  # ]
     148   [ +  +  +  -  :         18 :         assert(ctx->next_reg_ver <= ctx->upgrade->latest_ver);
          +  -  +  -  +  
          -  +  -  +  -  
                   #  # ]
     149                 :            : 
     150         [ +  + ]:         18 :         if (!status) {
     151   [ +  -  +  -  :         18 :                 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   [ +  -  +  -  :         18 :                         rc = ftl_superblock_md_layout_upgrade_region(dev, ctx->reg, ctx->next_reg_ver);
             +  -  +  - ]
     154   [ +  +  +  - ]:         18 :                         if (entry_size && num_entries) {
     155   [ +  -  +  -  :          6 :                                 dev->layout.region[ctx->reg->type].entry_size = entry_size;
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     156   [ +  -  +  -  :          6 :                                 dev->layout.region[ctx->reg->type].num_entries = num_entries;
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     157                 :          1 :                         }
     158                 :            : 
     159   [ +  +  #  # ]:         18 :                         ftl_bug(rc != 0);
     160                 :          3 :                 }
     161                 :            : 
     162   [ +  -  +  -  :         18 :                 ctx->reg->current.version = ctx->next_reg_ver;
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     163                 :          3 :         }
     164                 :            : 
     165   [ +  +  +  -  :         18 :         if (ctx->cb) {
                   +  - ]
     166   [ #  #  #  #  :          0 :                 ctx->cb(dev, ctx->cb_ctx, status);
          #  #  #  #  #  
                #  #  # ]
     167                 :          0 :         }
     168                 :         18 : }
     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                 :          0 :         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                 :          0 :         }
     198                 :            : 
     199                 :         22 :         return 0;
     200                 :          0 : }
     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                 :          0 : }
     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                 :          0 :         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                 :          0 : }
     243                 :            : 
     244                 :            : static int
     245                 :         52 : layout_upgrade_select_next_region(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *ctx)
     246                 :            : {
     247                 :          5 :         struct ftl_layout_region *reg;
     248                 :          5 :         uint64_t reg_ver, reg_latest_ver;
     249   [ +  -  +  -  :         52 :         uint32_t reg_type = ctx->reg->type;
             +  -  +  - ]
     250                 :            : 
     251         [ +  - ]:        562 :         while (reg_type != FTL_LAYOUT_REGION_TYPE_MAX) {
     252   [ +  +  +  -  :        562 :                 assert(ctx->reg);
             -  +  #  # ]
     253   [ +  +  +  -  :        562 :                 assert(ctx->upgrade);
             -  +  #  # ]
     254   [ +  -  +  - ]:        562 :                 reg = ctx->reg;
     255   [ +  -  +  -  :        562 :                 reg_latest_ver = ctx->upgrade->latest_ver;
             +  -  +  - ]
     256   [ +  -  +  -  :        562 :                 reg_ver = reg->current.version;
                   +  - ]
     257                 :            : 
     258   [ +  +  +  +  :        562 :                 if (reg_ver == reg_latest_ver || reg->type == FTL_LAYOUT_REGION_TYPE_INVALID) {
             +  -  -  + ]
     259                 :            :                         /* select the next region to upgrade */
     260                 :        544 :                         reg_type++;
     261         [ +  + ]:        544 :                         if (reg_type == FTL_LAYOUT_REGION_TYPE_MAX) {
     262                 :         34 :                                 break;
     263                 :            :                         }
     264   [ +  -  +  - ]:        510 :                         ctx->reg++;
     265   [ +  -  +  - ]:        510 :                         ctx->upgrade++;
     266         [ +  - ]:         48 :                 } else if (reg_ver < reg_latest_ver) {
     267                 :            :                         /* qualify region version to upgrade */
     268                 :         18 :                         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                 :         34 :         return FTL_LAYOUT_UPGRADE_DONE;
     279                 :          5 : }
     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                 :          0 :         }
     289                 :            : 
     290                 :         22 :         return layout_upgrade_select_next_region(dev, ctx);
     291                 :            : }
     292                 :            : 
     293                 :            : uint64_t
     294                 :        222 : ftl_layout_upgrade_region_get_latest_version(enum ftl_layout_region_type reg_type)
     295                 :            : {
     296   [ +  +  #  # ]:        222 :         assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX);
     297   [ +  -  +  -  :        222 :         return layout_upgrade_desc[reg_type].latest_ver;
             +  -  +  - ]
     298                 :            : }

Generated by: LCOV version 1.15