LCOV - code coverage report
Current view: top level - spdk/lib/ftl/upgrade - ftl_sb_v5.c (source / functions) Hit Total Coverage
Test: Combined Lines: 255 300 85.0 %
Date: 2024-07-10 15:22:03 Functions: 29 30 96.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 122 214 57.0 %

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

Generated by: LCOV version 1.14