LCOV - code coverage report
Current view: top level - spdk/lib/ftl/upgrade - ftl_sb_v5.c (source / functions) Hit Total Coverage
Test: Combined Lines: 251 292 86.0 %
Date: 2024-07-13 02:07:07 Functions: 29 30 96.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 115 202 56.9 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright 2023 Solidigm All Rights Reserved
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "spdk/string.h"
       7                 :            : 
       8                 :            : #include "ftl_sb_v5.h"
       9                 :            : #include "ftl_core.h"
      10                 :            : #include "ftl_layout.h"
      11                 :            : #include "ftl_band.h"
      12                 :            : #include "upgrade/ftl_sb_prev.h"
      13                 :            : #include "upgrade/ftl_sb_upgrade.h"
      14                 :            : #include "upgrade/ftl_layout_upgrade.h"
      15                 :            : #include "utils/ftl_layout_tracker_bdev.h"
      16                 :            : 
      17                 :            : typedef size_t (*blob_store_fn)(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_buf_sz);
      18                 :            : typedef int (*blob_load_fn)(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_sz);
      19                 :            : 
      20                 :            : bool
      21                 :         41 : ftl_superblock_v5_is_blob_area_empty(union ftl_superblock_ver *sb_ver)
      22                 :            : {
      23                 :         41 :         return sb_ver->v5.blob_area_end == 0;
      24                 :            : }
      25                 :            : 
      26                 :            : static bool
      27                 :         51 : validate_blob_area(struct ftl_superblock_v5_md_blob_hdr *sb_blob_hdr,
      28                 :            :                    ftl_df_obj_id sb_blob_area_end)
      29                 :            : {
      30         [ +  - ]:        102 :         return sb_blob_hdr->df_id <= sb_blob_area_end &&
      31         [ +  - ]:         51 :                (sb_blob_hdr->df_id + sb_blob_hdr->blob_sz) <= sb_blob_area_end;
      32                 :            : }
      33                 :            : 
      34                 :            : bool
      35                 :         17 : ftl_superblock_v5_validate_blob_area(struct spdk_ftl_dev *dev)
      36                 :            : {
      37                 :         17 :         union ftl_superblock_ver *sb_ver = (union ftl_superblock_ver *)dev->sb;
      38                 :            : 
      39         [ +  - ]:         34 :         return validate_blob_area(&sb_ver->v5.md_layout_nvc, sb_ver->v5.blob_area_end) &&
      40   [ +  -  +  - ]:         34 :                validate_blob_area(&sb_ver->v5.md_layout_base, sb_ver->v5.blob_area_end) &&
      41                 :         17 :                validate_blob_area(&sb_ver->v5.layout_params, sb_ver->v5.blob_area_end);
      42                 :            : }
      43                 :            : 
      44                 :            : static size_t
      45                 :        102 : sb_blob_store(struct spdk_ftl_dev *dev, struct ftl_superblock_v5_md_blob_hdr *sb_blob_hdr,
      46                 :            :               blob_store_fn blob_store, void *sb_blob_area)
      47                 :            : {
      48                 :        102 :         struct ftl_superblock_v5 *sb = (struct ftl_superblock_v5 *)dev->sb;
      49                 :        102 :         uintptr_t sb_end = ((uintptr_t)sb) + FTL_SUPERBLOCK_SIZE;
      50                 :        102 :         size_t blob_sz = sb_end - (uintptr_t)sb_blob_area;
      51                 :            : 
      52                 :            :         /* Test SB blob area overflow */
      53         [ -  + ]:        102 :         if ((uintptr_t)sb_blob_area < (uintptr_t)sb->blob_area) {
      54                 :          0 :                 ftl_bug(true);
      55                 :            :                 return 0;
      56                 :            :         }
      57         [ -  + ]:        102 :         if ((uintptr_t)sb_blob_area >= sb_end) {
      58                 :          0 :                 ftl_bug(true);
      59                 :            :                 return 0;
      60                 :            :         }
      61                 :            : 
      62                 :        102 :         blob_sz = blob_store(dev, sb_blob_area, blob_sz);
      63                 :        102 :         sb_blob_hdr->blob_sz = blob_sz;
      64                 :        102 :         sb_blob_hdr->df_id = ftl_df_get_obj_id(sb->blob_area, sb_blob_area);
      65                 :        102 :         return blob_sz;
      66                 :            : }
      67                 :            : 
      68                 :            : static size_t
      69                 :         34 : base_blob_store(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_buf_sz)
      70                 :            : {
      71                 :         34 :         return ftl_layout_tracker_bdev_blob_store(dev->base_layout_tracker, blob_buf, blob_buf_sz);
      72                 :            : }
      73                 :            : 
      74                 :            : static size_t
      75                 :         34 : nvc_blob_store(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_buf_sz)
      76                 :            : {
      77                 :         34 :         return ftl_layout_tracker_bdev_blob_store(dev->nvc_layout_tracker, blob_buf, blob_buf_sz);
      78                 :            : }
      79                 :            : 
      80                 :            : int
      81                 :         34 : ftl_superblock_v5_store_blob_area(struct spdk_ftl_dev *dev)
      82                 :            : {
      83                 :         34 :         struct ftl_superblock_v5 *sb = (struct ftl_superblock_v5 *)dev->sb;
      84                 :            :         void *sb_blob_area;
      85                 :            :         size_t blob_sz;
      86                 :            : 
      87                 :            :         /* Store the NVC-backed FTL MD layout info */
      88                 :         34 :         sb_blob_area = ftl_df_get_obj_ptr(sb->blob_area, 0);
      89                 :         34 :         spdk_strcpy_pad(sb->nvc_dev_name, dev->nv_cache.nvc_desc->name,
      90                 :            :                         SPDK_COUNTOF(sb->nvc_dev_name), '\0');
      91                 :         34 :         blob_sz = sb_blob_store(dev, &sb->md_layout_nvc, nvc_blob_store, sb_blob_area);
      92         [ +  - ]:         34 :         FTL_NOTICELOG(dev, "nvc layout blob store 0x%"PRIx64" bytes\n", blob_sz);
      93         [ -  + ]:         34 :         if (!blob_sz) {
      94                 :          0 :                 return -1;
      95                 :            :         }
      96                 :            : 
      97                 :            :         /* Store the base dev-backed FTL MD layout info */
      98                 :         34 :         sb_blob_area += blob_sz;
      99                 :         34 :         spdk_strcpy_pad(sb->base_dev_name, dev->base_type->name, SPDK_COUNTOF(sb->base_dev_name), '\0');
     100                 :         34 :         blob_sz = sb_blob_store(dev, &sb->md_layout_base, base_blob_store, sb_blob_area);
     101         [ +  - ]:         34 :         FTL_NOTICELOG(dev, "base layout blob store 0x%"PRIx64" bytes\n", blob_sz);
     102         [ -  + ]:         34 :         if (!blob_sz) {
     103                 :          0 :                 return -1;
     104                 :            :         }
     105                 :            : 
     106                 :            :         /* Store the region props */
     107                 :         34 :         sb_blob_area += blob_sz;
     108                 :         34 :         blob_sz = sb_blob_store(dev, &sb->layout_params, ftl_layout_blob_store, sb_blob_area);
     109         [ +  - ]:         34 :         FTL_NOTICELOG(dev, "layout blob store 0x%"PRIx64" bytes\n", blob_sz);
     110         [ -  + ]:         34 :         if (!blob_sz) {
     111                 :          0 :                 return -1;
     112                 :            :         }
     113                 :            : 
     114                 :            :         /* Update the blob area end */
     115                 :         34 :         sb_blob_area += blob_sz;
     116                 :         34 :         sb->blob_area_end = ftl_df_get_obj_id(sb->blob_area, sb_blob_area);
     117                 :            : 
     118                 :         34 :         return 0;
     119                 :            : }
     120                 :            : 
     121                 :            : static const struct ftl_layout_tracker_bdev_region_props *
     122                 :         84 : sb_md_layout_find_oldest_region(struct spdk_ftl_dev *dev,
     123                 :            :                                 struct ftl_layout_tracker_bdev *layout_tracker,
     124                 :            :                                 enum ftl_layout_region_type reg_type, void *find_filter)
     125                 :            : {
     126                 :         84 :         const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
     127                 :         84 :         const struct ftl_layout_tracker_bdev_region_props *reg_oldest = NULL;
     128                 :            :         uint32_t ver_oldest;
     129                 :            : 
     130                 :            :         while (true) {
     131                 :        144 :                 ftl_layout_tracker_bdev_find_next_region(layout_tracker, reg_type, &reg_search_ctx);
     132         [ +  + ]:        144 :                 if (!reg_search_ctx) {
     133                 :         84 :                         break;
     134                 :            :                 }
     135                 :            : 
     136         [ +  + ]:         60 :                 if (!reg_oldest) {
     137                 :         42 :                         reg_oldest = reg_search_ctx;
     138                 :         42 :                         ver_oldest = reg_search_ctx->ver;
     139                 :         42 :                         continue;
     140                 :            :                 }
     141                 :            : 
     142         [ -  + ]:         18 :                 ftl_bug(ver_oldest == reg_search_ctx->ver);
     143         [ +  + ]:         18 :                 if (ver_oldest > reg_search_ctx->ver) {
     144                 :          6 :                         reg_oldest = reg_search_ctx;
     145                 :          6 :                         ver_oldest = reg_search_ctx->ver;
     146                 :            :                 }
     147                 :            :         }
     148                 :            : 
     149                 :         84 :         return reg_oldest;
     150                 :            : }
     151                 :            : 
     152                 :            : static const struct ftl_layout_tracker_bdev_region_props *
     153                 :         60 : sb_md_layout_find_latest_region(struct spdk_ftl_dev *dev,
     154                 :            :                                 struct ftl_layout_tracker_bdev *layout_tracker, enum ftl_layout_region_type reg_type,
     155                 :            :                                 void *find_filter)
     156                 :            : {
     157                 :         60 :         const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
     158                 :         60 :         const struct ftl_layout_tracker_bdev_region_props *reg_latest = NULL;
     159                 :            :         uint32_t ver_latest;
     160                 :            : 
     161                 :            :         while (true) {
     162                 :        102 :                 ftl_layout_tracker_bdev_find_next_region(layout_tracker, reg_type, &reg_search_ctx);
     163         [ +  + ]:        102 :                 if (!reg_search_ctx) {
     164                 :         60 :                         break;
     165                 :            :                 }
     166                 :            : 
     167         [ +  + ]:         42 :                 if (!reg_latest) {
     168                 :         30 :                         reg_latest = reg_search_ctx;
     169                 :         30 :                         ver_latest = reg_search_ctx->ver;
     170                 :         30 :                         continue;
     171                 :            :                 }
     172                 :            : 
     173         [ -  + ]:         12 :                 ftl_bug(ver_latest == reg_search_ctx->ver);
     174         [ +  + ]:         12 :                 if (ver_latest < reg_search_ctx->ver) {
     175                 :          6 :                         reg_latest = reg_search_ctx;
     176                 :          6 :                         ver_latest = reg_search_ctx->ver;
     177                 :            :                 }
     178                 :            :         }
     179                 :            : 
     180                 :         60 :         return reg_latest;
     181                 :            : }
     182                 :            : 
     183                 :            : static const struct ftl_layout_tracker_bdev_region_props *
     184                 :         48 : sb_md_layout_find_region_version(struct spdk_ftl_dev *dev,
     185                 :            :                                  struct ftl_layout_tracker_bdev *layout_tracker, enum ftl_layout_region_type reg_type,
     186                 :            :                                  void *find_filter)
     187                 :            : {
     188                 :         48 :         const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
     189                 :         48 :         uint32_t *reg_ver = find_filter;
     190                 :            : 
     191         [ +  + ]:         48 :         assert(reg_ver);
     192                 :            : 
     193                 :            :         while (true) {
     194                 :         72 :                 ftl_layout_tracker_bdev_find_next_region(layout_tracker, reg_type, &reg_search_ctx);
     195         [ +  + ]:         72 :                 if (!reg_search_ctx) {
     196                 :         36 :                         break;
     197                 :            :                 }
     198                 :            : 
     199         [ +  + ]:         36 :                 if (reg_search_ctx->ver == *reg_ver) {
     200                 :         12 :                         break;
     201                 :            :                 }
     202                 :            :         }
     203                 :            : 
     204                 :         48 :         return reg_search_ctx;
     205                 :            : }
     206                 :            : 
     207                 :            : typedef const struct ftl_layout_tracker_bdev_region_props *(*sb_md_layout_find_fn)(
     208                 :            :         struct spdk_ftl_dev *dev, struct ftl_layout_tracker_bdev *layout_tracker,
     209                 :            :         enum ftl_layout_region_type reg_type, void *find_filter);
     210                 :            : 
     211                 :            : static const struct ftl_layout_tracker_bdev_region_props *
     212                 :         96 : sb_md_layout_find_region(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type,
     213                 :            :                          sb_md_layout_find_fn find_fn, void *find_filter)
     214                 :            : {
     215                 :            :         const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx;
     216                 :         96 :         struct ftl_layout_tracker_bdev *nvc_layout_tracker = dev->nvc_layout_tracker;
     217                 :         96 :         struct ftl_layout_tracker_bdev *base_layout_tracker = dev->base_layout_tracker;
     218                 :            : 
     219                 :         96 :         reg_search_ctx = find_fn(dev, nvc_layout_tracker, reg_type, find_filter);
     220         [ +  + ]:         96 :         if (reg_search_ctx) {
     221         [ -  + ]:         84 :                 assert(find_fn(dev, base_layout_tracker, reg_type, find_filter) == NULL);
     222                 :         84 :                 return reg_search_ctx;
     223                 :            :         }
     224                 :            : 
     225                 :         12 :         reg_search_ctx = find_fn(dev, base_layout_tracker, reg_type, find_filter);
     226                 :         12 :         return reg_search_ctx;
     227                 :            : }
     228                 :            : 
     229                 :            : static int
     230                 :        225 : sb_blob_load(struct spdk_ftl_dev *dev, struct ftl_superblock_v5_md_blob_hdr *sb_blob_hdr,
     231                 :            :              blob_load_fn blob_load)
     232                 :            : {
     233                 :        225 :         struct ftl_superblock_v5 *sb = (struct ftl_superblock_v5 *)dev->sb;
     234                 :        225 :         uintptr_t sb_end = ((uintptr_t)sb) + FTL_SUPERBLOCK_SIZE;
     235                 :            :         void *blob_area;
     236                 :            : 
     237         [ +  + ]:        225 :         if (sb_blob_hdr->df_id == FTL_DF_OBJ_ID_INVALID) {
     238                 :            :                 /* Uninitialized blob */
     239                 :         12 :                 return -1;
     240                 :            :         }
     241                 :            : 
     242                 :        213 :         blob_area = ftl_df_get_obj_ptr(sb->blob_area, sb_blob_hdr->df_id);
     243                 :            : 
     244                 :            :         /* Test SB blob area overflow */
     245         [ -  + ]:        213 :         if ((uintptr_t)blob_area < (uintptr_t)sb->blob_area) {
     246                 :          0 :                 ftl_bug(true);
     247                 :            :                 return -1;
     248                 :            :         }
     249         [ -  + ]:        213 :         if ((uintptr_t)blob_area + sb_blob_hdr->blob_sz >= sb_end) {
     250                 :          0 :                 ftl_bug(true);
     251                 :            :                 return -1;
     252                 :            :         }
     253                 :            : 
     254                 :        213 :         return blob_load(dev, blob_area, sb_blob_hdr->blob_sz);
     255                 :            : }
     256                 :            : 
     257                 :            : static int
     258                 :         65 : base_blob_load(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_sz)
     259                 :            : {
     260                 :         65 :         return ftl_layout_tracker_bdev_blob_load(dev->base_layout_tracker, blob_buf, blob_sz);
     261                 :            : }
     262                 :            : 
     263                 :            : static int
     264                 :         89 : nvc_blob_load(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_sz)
     265                 :            : {
     266                 :         89 :         return ftl_layout_tracker_bdev_blob_load(dev->nvc_layout_tracker, blob_buf, blob_sz);
     267                 :            : }
     268                 :            : 
     269                 :            : int
     270                 :        101 : ftl_superblock_v5_load_blob_area(struct spdk_ftl_dev *dev)
     271                 :            : {
     272                 :        101 :         struct ftl_superblock_v5 *sb = (struct ftl_superblock_v5 *)dev->sb;
     273                 :            : 
     274                 :            :         /* Load the NVC-backed FTL MD layout info */
     275   [ -  +  -  +  :        101 :         if (strncmp(sb->nvc_dev_name, dev->nv_cache.nvc_desc->name, SPDK_COUNTOF(sb->nvc_dev_name))) {
                   -  + ]
     276                 :          0 :                 return -1;
     277                 :            :         }
     278         [ +  - ]:        101 :         FTL_NOTICELOG(dev, "nvc layout blob load 0x%"PRIx64" bytes\n", (uint64_t)sb->md_layout_nvc.blob_sz);
     279         [ +  + ]:        101 :         if (sb_blob_load(dev, &sb->md_layout_nvc, nvc_blob_load)) {
     280                 :         36 :                 return -1;
     281                 :            :         }
     282                 :            : 
     283                 :            :         /* Load the base dev-backed FTL MD layout info */
     284   [ -  +  -  +  :         65 :         if (strncmp(sb->base_dev_name, dev->base_type->name, SPDK_COUNTOF(sb->base_dev_name))) {
                   -  + ]
     285                 :          0 :                 return -1;
     286                 :            :         }
     287         [ +  - ]:         65 :         FTL_NOTICELOG(dev, "base layout blob load 0x%"PRIx64" bytes\n",
     288                 :            :                       (uint64_t)sb->md_layout_base.blob_sz);
     289         [ +  + ]:         65 :         if (sb_blob_load(dev, &sb->md_layout_base, base_blob_load)) {
     290                 :          6 :                 return -1;
     291                 :            :         }
     292                 :            : 
     293                 :            :         /* Load the region props */
     294         [ +  - ]:         59 :         FTL_NOTICELOG(dev, "layout blob load 0x%"PRIx64" bytes\n", (uint64_t)sb->layout_params.blob_sz);
     295         [ +  + ]:         59 :         if (sb_blob_load(dev, &sb->layout_params, ftl_layout_blob_load)) {
     296                 :          6 :                 return -1;
     297                 :            :         }
     298                 :            : 
     299                 :         53 :         return 0;
     300                 :            : }
     301                 :            : 
     302                 :            : static struct ftl_layout_tracker_bdev *
     303                 :         18 : sb_get_md_layout_tracker(struct spdk_ftl_dev *dev, struct ftl_layout_region *reg)
     304                 :            : {
     305         [ -  + ]:         18 :         return (reg->bdev_desc == dev->base_bdev_desc) ? dev->base_layout_tracker : dev->nvc_layout_tracker;
     306                 :            : }
     307                 :            : 
     308                 :            : static void
     309                 :          6 : sb_md_layout_delete_prev_region(struct spdk_ftl_dev *dev, struct ftl_layout_region *reg)
     310                 :            : {
     311                 :            :         int rc;
     312                 :          6 :         struct ftl_layout_tracker_bdev *layout_tracker = sb_get_md_layout_tracker(dev, reg);
     313                 :            : 
     314                 :          6 :         rc = ftl_layout_tracker_bdev_rm_region(layout_tracker, reg->type, reg->current.version);
     315         [ -  + ]:          6 :         ftl_bug(rc != 0);
     316                 :          6 : }
     317                 :            : 
     318                 :            : static void
     319                 :         12 : sb_md_layout_update_prev_region(struct spdk_ftl_dev *dev, struct ftl_layout_region *reg,
     320                 :            :                                 uint32_t new_version)
     321                 :            : {
     322                 :            :         int rc;
     323                 :         12 :         const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
     324                 :         12 :         struct ftl_layout_tracker_bdev *layout_tracker = sb_get_md_layout_tracker(dev, reg);
     325                 :            :         struct ftl_layout_tracker_bdev_region_props reg_props;
     326                 :            : 
     327                 :            :         /* Get region properties */
     328                 :         12 :         ftl_layout_tracker_bdev_find_next_region(layout_tracker, reg->type, &reg_search_ctx);
     329         [ -  + ]:         12 :         ftl_bug(reg_search_ctx == NULL);
     330                 :         12 :         reg_props = *reg_search_ctx;
     331                 :            : 
     332                 :            :         /* Delete the region */
     333                 :         12 :         rc = ftl_layout_tracker_bdev_rm_region(layout_tracker, reg_props.type, reg_props.ver);
     334         [ -  + ]:         12 :         ftl_bug(rc != 0);
     335                 :            : 
     336                 :            :         /* Insert the same region with new version */
     337                 :         12 :         reg_search_ctx = ftl_layout_tracker_bdev_insert_region(layout_tracker, reg_props.type, new_version,
     338                 :            :                          reg_props.blk_offs, reg_props.blk_sz);
     339         [ -  + ]:         12 :         ftl_bug(reg_search_ctx == NULL);
     340                 :            : 
     341                 :            :         /* Verify the oldest region version stored in the SB is the new_version */
     342                 :         12 :         reg_search_ctx = sb_md_layout_find_region(dev, reg_props.type, sb_md_layout_find_oldest_region,
     343                 :            :                          NULL);
     344         [ -  + ]:         12 :         ftl_bug(reg_search_ctx == NULL);
     345         [ -  + ]:         12 :         ftl_bug(reg_search_ctx->ver != new_version);
     346                 :         12 : }
     347                 :            : 
     348                 :            : int
     349                 :         18 : ftl_superblock_v5_md_layout_upgrade_region(struct spdk_ftl_dev *dev, struct ftl_layout_region *reg,
     350                 :            :                 uint32_t new_version)
     351                 :            : {
     352                 :         18 :         const struct ftl_layout_tracker_bdev_region_props *reg_next = NULL;
     353                 :            :         uint64_t latest_ver;
     354                 :            : 
     355         [ -  + ]:         18 :         ftl_bug(reg->current.version >= new_version);
     356                 :            : 
     357                 :         18 :         reg_next = sb_md_layout_find_region(dev, reg->type, sb_md_layout_find_region_version, &new_version);
     358         [ +  + ]:         18 :         if (reg_next) {
     359                 :            :                 /**
     360                 :            :                  * Major upgrade.
     361                 :            :                  * Found a new MD region allocated for upgrade to the next version.
     362                 :            :                  * Destroy the previous version now that the upgrade is completed.
     363                 :            :                  */
     364         [ -  + ]:          6 :                 ftl_bug(reg_next->ver != new_version);
     365         [ -  + ]:          6 :                 ftl_bug(reg_next->type != reg->type);
     366                 :          6 :                 sb_md_layout_delete_prev_region(dev, reg);
     367                 :          6 :                 reg->current.offset = reg_next->blk_offs;
     368                 :          6 :                 reg->current.blocks = reg_next->blk_sz;
     369                 :            :         } else {
     370                 :            :                 /**
     371                 :            :                  * Minor upgrade.
     372                 :            :                  * Upgraded the MD region in place.
     373                 :            :                  * Update the version in place.
     374                 :            :                  */
     375                 :         12 :                 sb_md_layout_update_prev_region(dev, reg, new_version);
     376                 :            :         }
     377                 :            : 
     378                 :         18 :         reg->current.version = new_version;
     379                 :         18 :         latest_ver = ftl_layout_upgrade_region_get_latest_version(reg->type);
     380         [ +  + ]:         18 :         if (new_version == latest_ver) {
     381                 :            :                 /* Audit the only region version stored in the SB */
     382                 :          6 :                 reg_next = sb_md_layout_find_region(dev, reg->type, sb_md_layout_find_latest_region, NULL);
     383         [ -  + ]:          6 :                 ftl_bug(reg_next == NULL);
     384         [ -  + ]:          6 :                 ftl_bug(reg_next->ver != new_version);
     385                 :            : 
     386                 :          6 :                 reg_next = sb_md_layout_find_region(dev, reg->type, sb_md_layout_find_oldest_region, NULL);
     387         [ -  + ]:          6 :                 ftl_bug(reg_next == NULL);
     388         [ -  + ]:          6 :                 ftl_bug(reg_next->ver != new_version);
     389                 :            : 
     390                 :          6 :                 reg_next = sb_md_layout_find_region(dev, reg->type, sb_md_layout_find_region_version, &new_version);
     391         [ -  + ]:          6 :                 ftl_bug(reg->type != reg_next->type);
     392         [ -  + ]:          6 :                 ftl_bug(reg->current.version != reg_next->ver);
     393         [ -  + ]:          6 :                 ftl_bug(reg->current.offset != reg_next->blk_offs);
     394         [ -  + ]:          6 :                 ftl_bug(reg->current.blocks != reg_next->blk_sz);
     395                 :            :         }
     396                 :            : 
     397                 :         18 :         return 0;
     398                 :            : }
     399                 :            : 
     400                 :            : void
     401                 :         22 : ftl_superblock_v5_md_layout_dump(struct spdk_ftl_dev *dev)
     402                 :            : {
     403                 :         22 :         struct ftl_layout_tracker_bdev *nvc_layout_tracker = dev->nvc_layout_tracker;
     404                 :         22 :         struct ftl_layout_tracker_bdev *base_layout_tracker = dev->base_layout_tracker;
     405                 :         22 :         const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
     406                 :            : 
     407         [ +  - ]:         22 :         FTL_NOTICELOG(dev, "SB metadata layout - nvc:\n");
     408                 :            :         while (true) {
     409                 :        330 :                 ftl_layout_tracker_bdev_find_next_region(nvc_layout_tracker, FTL_LAYOUT_REGION_TYPE_INVALID,
     410                 :            :                                 &reg_search_ctx);
     411         [ +  + ]:        330 :                 if (!reg_search_ctx) {
     412                 :         22 :                         break;
     413                 :            :                 }
     414                 :            : 
     415         [ +  - ]:        308 :                 FTL_NOTICELOG(dev,
     416                 :            :                               "Region type:0x%"PRIx32" ver:%"PRIu32" blk_offs:0x%"PRIx64" blk_sz:0x%"PRIx64"\n",
     417                 :            :                               reg_search_ctx->type, reg_search_ctx->ver, reg_search_ctx->blk_offs, reg_search_ctx->blk_sz);
     418                 :            :         }
     419                 :            : 
     420                 :         22 :         reg_search_ctx = NULL;
     421         [ +  - ]:         22 :         FTL_NOTICELOG(dev, "SB metadata layout - base dev:\n");
     422                 :            :         while (true) {
     423                 :        132 :                 ftl_layout_tracker_bdev_find_next_region(base_layout_tracker, FTL_LAYOUT_REGION_TYPE_INVALID,
     424                 :            :                                 &reg_search_ctx);
     425         [ +  + ]:        132 :                 if (!reg_search_ctx) {
     426                 :         22 :                         break;
     427                 :            :                 }
     428                 :            : 
     429         [ +  - ]:        110 :                 FTL_NOTICELOG(dev,
     430                 :            :                               "Region type:0x%"PRIx32" ver:%"PRIu32" blk_offs:0x%"PRIx64" blk_sz:0x%"PRIx64"\n",
     431                 :            :                               reg_search_ctx->type, reg_search_ctx->ver, reg_search_ctx->blk_offs, reg_search_ctx->blk_sz);
     432                 :            :         }
     433                 :         22 : }
     434                 :            : 
     435                 :            : static int
     436                 :         34 : layout_apply_from_sb_blob(struct spdk_ftl_dev *dev, struct ftl_layout_tracker_bdev *layout_tracker,
     437                 :            :                           int (*filter_region_type_fn)(enum ftl_layout_region_type))
     438                 :            : {
     439                 :            :         struct ftl_layout_region *reg;
     440                 :         34 :         const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
     441                 :            : 
     442                 :            :         while (true) {
     443                 :        357 :                 ftl_layout_tracker_bdev_find_next_region(layout_tracker, FTL_LAYOUT_REGION_TYPE_INVALID,
     444                 :            :                                 &reg_search_ctx);
     445         [ +  + ]:        357 :                 if (!reg_search_ctx) {
     446                 :         34 :                         break;
     447                 :            :                 }
     448         [ +  + ]:        323 :                 if (reg_search_ctx->type == FTL_LAYOUT_REGION_TYPE_FREE) {
     449                 :         51 :                         continue;
     450                 :            :                 }
     451         [ -  + ]:        272 :                 if (filter_region_type_fn(reg_search_ctx->type)) {
     452         [ #  # ]:          0 :                         FTL_ERRLOG(dev, "Unknown region found in layout blob: type 0x%"PRIx32"\n", reg_search_ctx->type);
     453                 :          0 :                         return -1;
     454                 :            :                 }
     455                 :            : 
     456                 :        272 :                 reg = &dev->layout.region[reg_search_ctx->type];
     457                 :            : 
     458                 :            :                 /* First region of a given type found */
     459         [ +  + ]:        272 :                 if (reg->type == FTL_LAYOUT_REGION_TYPE_INVALID) {
     460                 :        238 :                         reg->type = reg_search_ctx->type;
     461                 :        238 :                         reg->current.version = reg_search_ctx->ver;
     462                 :        238 :                         reg->current.offset = reg_search_ctx->blk_offs;
     463                 :        238 :                         reg->current.blocks = reg_search_ctx->blk_sz;
     464                 :        238 :                         continue;
     465                 :            :                 }
     466                 :            : 
     467                 :            :                 /* Update to the oldest region version found */
     468         [ -  + ]:         34 :                 if (reg_search_ctx->ver < reg->current.version) {
     469                 :          0 :                         reg->current.version = reg_search_ctx->ver;
     470                 :          0 :                         reg->current.offset = reg_search_ctx->blk_offs;
     471                 :          0 :                         reg->current.blocks = reg_search_ctx->blk_sz;
     472                 :          0 :                         continue;
     473                 :            :                 }
     474                 :            : 
     475                 :            :                 /* Skip newer region versions */
     476         [ -  + ]:         34 :                 if (reg_search_ctx->ver > reg->current.version) {
     477                 :          0 :                         continue;
     478                 :            :                 }
     479                 :            : 
     480                 :            :                 /* Current region version already found */
     481         [ -  + ]:         34 :                 assert(reg_search_ctx->ver == reg->current.version);
     482         [ +  - ]:         34 :                 if (reg->current.offset != reg_search_ctx->blk_offs ||
     483         [ -  + ]:         34 :                     reg->current.blocks != reg_search_ctx->blk_sz) {
     484         [ #  # ]:          0 :                         FTL_ERRLOG(dev, "Corrupted layout blob: reg type 0x%"PRIx32"\n", reg_search_ctx->type);
     485                 :          0 :                         return -1;
     486                 :            :                 }
     487                 :            :         }
     488                 :         34 :         return 0;
     489                 :            : }
     490                 :            : 
     491                 :            : static int
     492                 :        272 : layout_region_verify(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type,
     493                 :            :                      uint32_t reg_ver)
     494                 :            : {
     495                 :        272 :         struct ftl_layout_region *reg = ftl_layout_region_get(dev, reg_type);
     496                 :            : 
     497         [ -  + ]:        272 :         if (!reg) {
     498         [ #  # ]:          0 :                 FTL_ERRLOG(dev, "Region not found in nvc layout blob: reg type 0x%"PRIx32"\n", reg_type);
     499                 :          0 :                 return -1;
     500                 :            :         }
     501                 :            : 
     502                 :            :         /* Unknown version found in the blob */
     503         [ -  + ]:        272 :         if (reg->current.version > reg_ver) {
     504         [ #  # ]:          0 :                 FTL_ERRLOG(dev, "Unknown region version found in layout blob: reg type 0x%"PRIx32"\n",
     505                 :            :                            reg_type);
     506                 :          0 :                 return -1;
     507                 :            :         }
     508                 :            : 
     509                 :        272 :         return 0;
     510                 :            : }
     511                 :            : 
     512                 :            : static int
     513                 :          0 : layout_fixup_reg_data_base(struct spdk_ftl_dev *dev)
     514                 :            : {
     515                 :          0 :         const struct ftl_md_layout_ops *base_md_ops = &dev->base_type->ops.md_layout_ops;
     516                 :          0 :         struct ftl_layout_region *reg = &dev->layout.region[FTL_LAYOUT_REGION_TYPE_DATA_BASE];
     517                 :          0 :         const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
     518                 :            : 
     519         [ #  # ]:          0 :         assert(reg->type == FTL_LAYOUT_REGION_TYPE_INVALID);
     520                 :            : 
     521         [ #  # ]:          0 :         FTL_NOTICELOG(dev, "Adding a region\n");
     522                 :            : 
     523                 :            :         /* Add the region */
     524         [ #  # ]:          0 :         if (base_md_ops->region_create(dev, FTL_LAYOUT_REGION_TYPE_DATA_BASE, 0,
     525                 :            :                                        ftl_layout_base_offset(dev))) {
     526                 :          0 :                 return -1;
     527                 :            :         }
     528         [ #  # ]:          0 :         if (base_md_ops->region_open(dev, FTL_LAYOUT_REGION_TYPE_DATA_BASE, 0, FTL_BLOCK_SIZE,
     529                 :            :                                      ftl_layout_base_offset(dev), reg)) {
     530                 :          0 :                 return -1;
     531                 :            :         }
     532                 :            : 
     533                 :          0 :         ftl_layout_tracker_bdev_find_next_region(dev->base_layout_tracker, FTL_LAYOUT_REGION_TYPE_DATA_BASE,
     534                 :            :                         &reg_search_ctx);
     535         [ #  # ]:          0 :         assert(reg_search_ctx);
     536                 :          0 :         return 0;
     537                 :            : }
     538                 :            : 
     539                 :            : static int
     540                 :         17 : layout_fixup_base(struct spdk_ftl_dev *dev)
     541                 :            : {
     542                 :            :         struct ftl_layout_region_descr {
     543                 :            :                 enum ftl_layout_region_type type;
     544                 :            :                 uint32_t ver;
     545                 :            :                 int (*on_reg_miss)(struct spdk_ftl_dev *dev);
     546                 :            :         };
     547                 :            :         struct ftl_layout_region_descr *reg_descr;
     548                 :            :         static struct ftl_layout_region_descr nvc_regs[] = {
     549                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_SB_BASE, .ver = FTL_SB_VERSION_CURRENT },
     550                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_DATA_BASE, .ver = 0, .on_reg_miss = layout_fixup_reg_data_base },
     551                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_VALID_MAP, .ver = 0 },
     552                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_INVALID, .ver = 0 },
     553                 :            :         };
     554                 :            : 
     555         [ +  + ]:         68 :         for (reg_descr = nvc_regs; reg_descr->type != FTL_LAYOUT_REGION_TYPE_INVALID; reg_descr++) {
     556                 :            :                 struct ftl_layout_region *region;
     557                 :            : 
     558         [ -  + ]:         51 :                 if (layout_region_verify(dev, reg_descr->type, reg_descr->ver) &&
     559   [ #  #  #  # ]:          0 :                     reg_descr->on_reg_miss && reg_descr->on_reg_miss(dev)) {
     560                 :          0 :                         return -1;
     561                 :            :                 }
     562                 :            : 
     563                 :         51 :                 region = &dev->layout.region[reg_descr->type];
     564                 :         51 :                 region->type = reg_descr->type;
     565                 :         51 :                 region->mirror_type = FTL_LAYOUT_REGION_TYPE_INVALID;
     566                 :         51 :                 region->name = ftl_md_region_name(reg_descr->type);
     567                 :            : 
     568                 :         51 :                 region->bdev_desc = dev->base_bdev_desc;
     569                 :         51 :                 region->ioch = dev->base_ioch;
     570                 :         51 :                 region->vss_blksz = 0;
     571                 :            :         }
     572                 :            : 
     573                 :         17 :         return 0;
     574                 :            : }
     575                 :            : 
     576                 :            : static int
     577                 :         17 : layout_fixup_nvc(struct spdk_ftl_dev *dev)
     578                 :            : {
     579                 :            :         struct ftl_layout_region_descr {
     580                 :            :                 enum ftl_layout_region_type type;
     581                 :            :                 uint32_t ver;
     582                 :            :                 enum ftl_layout_region_type mirror_type;
     583                 :            :         };
     584                 :            :         struct ftl_layout_region_descr *reg_descr;
     585                 :            :         static struct ftl_layout_region_descr nvc_regs[] = {
     586                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_SB, .ver = FTL_SB_VERSION_CURRENT, .mirror_type = FTL_LAYOUT_REGION_TYPE_SB_BASE },
     587                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_L2P, .ver = 0 },
     588                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_BAND_MD, .ver = FTL_BAND_VERSION_CURRENT, .mirror_type = FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR },
     589                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR, .ver = FTL_BAND_VERSION_CURRENT },
     590                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_TRIM_MD, .ver = 0, .mirror_type = FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR },
     591                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR, .ver = 0 },
     592                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_NVC_MD, .ver = FTL_NVC_VERSION_CURRENT, .mirror_type = FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR },
     593                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR, .ver = FTL_NVC_VERSION_CURRENT },
     594                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_DATA_NVC, .ver = 0 },
     595                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC, .ver = FTL_P2L_VERSION_CURRENT },
     596                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC_NEXT, .ver = FTL_P2L_VERSION_CURRENT },
     597                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP, .ver = FTL_P2L_VERSION_CURRENT },
     598                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP_NEXT, .ver = FTL_P2L_VERSION_CURRENT },
     599                 :            :                 { .type = FTL_LAYOUT_REGION_TYPE_INVALID, .ver = 0 },
     600                 :            :         };
     601                 :            : 
     602         [ +  + ]:        238 :         for (reg_descr = nvc_regs; reg_descr->type != FTL_LAYOUT_REGION_TYPE_INVALID; reg_descr++) {
     603                 :            :                 struct ftl_layout_region *region;
     604                 :            : 
     605         [ -  + ]:        221 :                 if (layout_region_verify(dev, reg_descr->type, reg_descr->ver)) {
     606                 :          0 :                         return -1;
     607                 :            :                 }
     608                 :            : 
     609                 :        221 :                 region = &dev->layout.region[reg_descr->type];
     610                 :        221 :                 region->type = reg_descr->type;
     611                 :        221 :                 region->mirror_type = FTL_LAYOUT_REGION_TYPE_INVALID;
     612                 :        221 :                 region->name = ftl_md_region_name(reg_descr->type);
     613                 :            : 
     614                 :        221 :                 region->bdev_desc = dev->nv_cache.bdev_desc;
     615                 :        221 :                 region->ioch = dev->nv_cache.cache_ioch;
     616                 :        221 :                 region->vss_blksz = dev->nv_cache.md_size;
     617                 :            : 
     618         [ +  + ]:        221 :                 if (reg_descr->mirror_type) {
     619                 :         68 :                         dev->layout.region[reg_descr->type].mirror_type = reg_descr->mirror_type;
     620                 :            :                 }
     621                 :            :         }
     622                 :            : 
     623                 :         17 :         return 0;
     624                 :            : }
     625                 :            : 
     626                 :            : static int
     627                 :        272 : filter_region_type_base(enum ftl_layout_region_type reg_type)
     628                 :            : {
     629         [ +  + ]:        272 :         switch (reg_type) {
     630                 :         51 :         case FTL_LAYOUT_REGION_TYPE_SB_BASE:
     631                 :            :         case FTL_LAYOUT_REGION_TYPE_DATA_BASE:
     632                 :            :         case FTL_LAYOUT_REGION_TYPE_VALID_MAP:
     633                 :         51 :                 return 0;
     634                 :            : 
     635                 :        221 :         default:
     636                 :        221 :                 return 1;
     637                 :            :         }
     638                 :            : }
     639                 :            : 
     640                 :            : static int
     641                 :        221 : filter_region_type_nvc(enum ftl_layout_region_type reg_type)
     642                 :            : {
     643                 :        221 :         return filter_region_type_base(reg_type) ? 0 : 1;
     644                 :            : }
     645                 :            : 
     646                 :            : static int
     647                 :         17 : layout_apply_nvc(struct spdk_ftl_dev *dev)
     648                 :            : {
     649   [ +  -  -  + ]:         34 :         if (layout_apply_from_sb_blob(dev, dev->nvc_layout_tracker, filter_region_type_nvc) ||
     650                 :         17 :             layout_fixup_nvc(dev)) {
     651                 :          0 :                 return -1;
     652                 :            :         }
     653                 :         17 :         return 0;
     654                 :            : }
     655                 :            : 
     656                 :            : static int
     657                 :         17 : layout_apply_base(struct spdk_ftl_dev *dev)
     658                 :            : {
     659   [ +  -  -  + ]:         34 :         if (layout_apply_from_sb_blob(dev, dev->base_layout_tracker, filter_region_type_base) ||
     660                 :         17 :             layout_fixup_base(dev)) {
     661                 :          0 :                 return -1;
     662                 :            :         }
     663                 :         17 :         return 0;
     664                 :            : }
     665                 :            : 
     666                 :            : int
     667                 :         17 : ftl_superblock_v5_md_layout_apply(struct spdk_ftl_dev *dev)
     668                 :            : {
     669   [ +  -  -  + ]:         17 :         if (layout_apply_nvc(dev) || layout_apply_base(dev)) {
     670                 :          0 :                 return -1;
     671                 :            :         }
     672                 :         17 :         return 0;
     673                 :            : }

Generated by: LCOV version 1.14