LCOV - code coverage report
Current view: top level - spdk/test/unit/lib/ftl/ftl_sb - ftl_sb_ut.c (source / functions) Hit Total Coverage
Test: Combined Lines: 382 414 92.3 %
Date: 2024-07-12 16:53:48 Functions: 19 56 33.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 50 104 48.1 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2022 Intel Corporation.
       3                 :            :  *   Copyright 2023 Solidigm All Rights Reserved
       4                 :            :  *   All rights reserved.
       5                 :            :  */
       6                 :            : 
       7                 :            : #include <sys/queue.h>
       8                 :            : 
       9                 :            : #include "spdk/stdinc.h"
      10                 :            : #include "spdk_internal/cunit.h"
      11                 :            : #include "common/lib/test_env.c"
      12                 :            : 
      13                 :            : #include "ftl/utils/ftl_layout_tracker_bdev.c"
      14                 :            : #include "ftl/upgrade/ftl_sb_v3.c"
      15                 :            : #include "ftl/upgrade/ftl_sb_v5.c"
      16                 :            : #include "ftl/ftl_sb.c"
      17                 :            : #include "ftl/ftl_layout.c"
      18                 :            : #include "ftl/upgrade/ftl_sb_upgrade.c"
      19                 :            : 
      20                 :            : static struct ftl_layout_upgrade_desc_list layout_upgrade_desc[] = {
      21                 :            :         [FTL_LAYOUT_REGION_TYPE_SB] = {
      22                 :            :                 .latest_ver = FTL_SB_VERSION_CURRENT,
      23                 :            :                 .count = FTL_SB_VERSION_CURRENT,
      24                 :            :         },
      25                 :            :         [FTL_LAYOUT_REGION_TYPE_SB_BASE] = {
      26                 :            :                 .latest_ver = FTL_SB_VERSION_CURRENT,
      27                 :            :                 .count = FTL_SB_VERSION_CURRENT,
      28                 :            :         },
      29                 :            :         [FTL_LAYOUT_REGION_TYPE_L2P] = {},
      30                 :            :         [FTL_LAYOUT_REGION_TYPE_BAND_MD] = {
      31                 :            :                 .latest_ver = FTL_BAND_VERSION_CURRENT,
      32                 :            :                 .count = FTL_BAND_VERSION_CURRENT,
      33                 :            :         },
      34                 :            :         [FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR] = {
      35                 :            :                 .latest_ver = FTL_BAND_VERSION_CURRENT,
      36                 :            :                 .count = FTL_BAND_VERSION_CURRENT,
      37                 :            :         },
      38                 :            :         [FTL_LAYOUT_REGION_TYPE_VALID_MAP] = {},
      39                 :            :         [FTL_LAYOUT_REGION_TYPE_NVC_MD] = {
      40                 :            :                 .latest_ver = FTL_NVC_VERSION_CURRENT,
      41                 :            :                 .count = FTL_NVC_VERSION_CURRENT,
      42                 :            :         },
      43                 :            :         [FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR] = {
      44                 :            :                 .latest_ver = FTL_NVC_VERSION_CURRENT,
      45                 :            :                 .count = FTL_NVC_VERSION_CURRENT,
      46                 :            :         },
      47                 :            :         [FTL_LAYOUT_REGION_TYPE_DATA_NVC] = {},
      48                 :            :         [FTL_LAYOUT_REGION_TYPE_DATA_BASE] = {},
      49                 :            :         [FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC] = {
      50                 :            :                 .latest_ver = FTL_P2L_VERSION_CURRENT,
      51                 :            :                 .count = FTL_P2L_VERSION_CURRENT,
      52                 :            :         },
      53                 :            :         [FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC_NEXT] = {
      54                 :            :                 .latest_ver = FTL_P2L_VERSION_CURRENT,
      55                 :            :                 .count = FTL_P2L_VERSION_CURRENT,
      56                 :            :         },
      57                 :            :         [FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP] = {
      58                 :            :                 .latest_ver = FTL_P2L_VERSION_CURRENT,
      59                 :            :                 .count = FTL_P2L_VERSION_CURRENT,
      60                 :            :         },
      61                 :            :         [FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP_NEXT] = {
      62                 :            :                 .latest_ver = FTL_P2L_VERSION_CURRENT,
      63                 :            :                 .count = FTL_P2L_VERSION_CURRENT,
      64                 :            :         },
      65                 :            :         [FTL_LAYOUT_REGION_TYPE_TRIM_MD] = {},
      66                 :            :         [FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR] = {},
      67                 :            :         [FTL_LAYOUT_REGION_TYPE_TRIM_LOG] = {},
      68                 :            :         [FTL_LAYOUT_REGION_TYPE_TRIM_LOG_MIRROR] = {},
      69                 :            : };
      70                 :            : 
      71                 :            : #include "ftl/upgrade/ftl_layout_upgrade.c"
      72                 :            : #include "ftl/mngt/ftl_mngt_md.c"
      73                 :            : 
      74                 :          0 : DEFINE_STUB_V(ftl_mngt_fail_step, (struct ftl_mngt_process *mngt));
      75                 :         16 : DEFINE_STUB_V(ftl_mngt_next_step, (struct ftl_mngt_process *mngt));
      76                 :          0 : DEFINE_STUB_V(ftl_md_persist, (struct ftl_md *md));
      77         [ #  # ]:          0 : DEFINE_STUB(ftl_nv_cache_load_state, int, (struct ftl_nv_cache *nv_cache), 0);
      78                 :          0 : DEFINE_STUB_V(ftl_valid_map_load_state, (struct spdk_ftl_dev *dev));
      79         [ #  # ]:          0 : DEFINE_STUB(ftl_bands_load_state, int, (struct spdk_ftl_dev *dev), 0);
      80         [ #  # ]:          0 : DEFINE_STUB(ftl_md_get_region, const struct ftl_layout_region *, (struct ftl_md *md), 0);
      81                 :          0 : DEFINE_STUB_V(ftl_md_restore, (struct ftl_md *md));
      82         [ #  # ]:          0 : DEFINE_STUB(ftl_nv_cache_save_state, int, (struct ftl_nv_cache *nv_cache), 0);
      83         [ #  # ]:          0 : DEFINE_STUB(ftl_mngt_get_step_ctx, void *, (struct ftl_mngt_process *mngt), 0);
      84                 :          0 : DEFINE_STUB_V(ftl_mngt_persist_bands_p2l, (struct ftl_mngt_process *mngt));
      85                 :         16 : DEFINE_STUB_V(ftl_band_init_gc_iter, (struct spdk_ftl_dev *dev));
      86         [ #  # ]:          0 : DEFINE_STUB(ftl_md_create_region_flags, int, (struct spdk_ftl_dev *dev, int region_type), 0);
      87         [ #  # ]:          0 : DEFINE_STUB(ftl_md_create, struct ftl_md *, (struct spdk_ftl_dev *dev, uint64_t blocks,
      88                 :            :                 uint64_t vss_blksz, const char *name, int flags, const struct ftl_layout_region *region), NULL);
      89         [ #  # ]:          0 : DEFINE_STUB(ftl_md_destroy_region_flags, int, (struct spdk_ftl_dev *dev, int region_type), 0);
      90         [ #  # ]:          0 : DEFINE_STUB(ftl_md_destroy_shm_flags, int, (struct spdk_ftl_dev *dev), 0);
      91                 :          0 : DEFINE_STUB_V(ftl_md_destroy, (struct ftl_md *md, int flags));
      92                 :          0 : DEFINE_STUB_V(ftl_mngt_call_process, (struct ftl_mngt_process *mngt,
      93                 :            :                                       const struct ftl_mngt_process_desc *process,
      94                 :            :                                       void *init_ctx));
      95         [ #  # ]:          0 : DEFINE_STUB(ftl_md_get_buffer, void *, (struct ftl_md *md), NULL);
      96         [ #  # ]:          0 : DEFINE_STUB(spdk_bdev_desc_get_bdev, struct spdk_bdev *, (struct spdk_bdev_desc *desc), NULL);
      97         [ #  # ]:          0 : DEFINE_STUB(spdk_bdev_get_write_unit_size, uint32_t, (const struct spdk_bdev *bdev), 0);
      98         [ #  # ]:          0 : DEFINE_STUB(spdk_bdev_get_num_blocks, uint64_t, (const struct spdk_bdev *bdev), 0);
      99         [ #  # ]:          0 : DEFINE_STUB(ftl_nv_cache_chunk_tail_md_num_blocks, size_t, (const struct ftl_nv_cache *nv_cache),
     100                 :            :             0);
     101         [ #  # ]:          0 : DEFINE_STUB(ftl_band_user_blocks, size_t, (const struct ftl_band *band), 0);
     102                 :            : 
     103                 :            : struct spdk_bdev_desc {
     104                 :            :         int dummy;
     105                 :            : };
     106                 :            : 
     107                 :            : struct spdk_ftl_dev g_dev;
     108                 :            : struct ftl_superblock_shm g_sb_shm = {0};
     109                 :            : struct ftl_base_device_type g_base_type = { .name = "base_dev" };
     110                 :            : struct ftl_nv_cache_device_type g_nvc_type = { .name = "nvc_dev" };
     111                 :            : struct spdk_bdev_desc g_base_bdev_desc = {0};
     112                 :            : struct spdk_bdev_desc g_nvc_bdev_desc = {0};
     113                 :            : static uint8_t g_sb_buf[FTL_SUPERBLOCK_SIZE] = {0};
     114                 :            : 
     115                 :            : struct ftl_region_upgrade_desc p2l_upgrade_desc[0];
     116                 :            : struct ftl_region_upgrade_desc nvc_upgrade_desc[0];
     117                 :            : struct ftl_region_upgrade_desc band_upgrade_desc[0];
     118                 :            : 
     119                 :            : #define TEST_OP 0x1984
     120                 :            : #define TEST_REG_BLKS 0x10000
     121                 :            : #define TEST_NVC_BLKS 0x1000000;
     122                 :            : #define TEST_BASE_BLKS 0x1000000000;
     123                 :            : 
     124                 :            : static int
     125                 :          4 : test_setup(void)
     126                 :            : {
     127                 :          4 :         int regno_nvc = 0, regno_base = 0, *regno_dev;
     128                 :            : 
     129                 :            :         /* setup a dummy dev: */
     130                 :          4 :         g_dev.sb = (void *)g_sb_buf;
     131                 :          4 :         g_dev.sb_shm = &g_sb_shm;
     132                 :          4 :         g_dev.conf.overprovisioning = TEST_OP;
     133         [ +  + ]:         68 :         for (uint64_t n = 0; n < sizeof(g_dev.conf.uuid); n++) {
     134                 :         64 :                 g_dev.conf.uuid.u.raw[n] = n;
     135                 :            :         }
     136                 :            : 
     137                 :          4 :         g_dev.layout.nvc.total_blocks = TEST_NVC_BLKS;
     138                 :          4 :         g_dev.layout.base.total_blocks = TEST_BASE_BLKS;
     139                 :          4 :         g_dev.base_type = &g_base_type;
     140                 :          4 :         g_dev.nv_cache.nvc_type = &g_nvc_type;
     141                 :          4 :         g_dev.base_layout_tracker = ftl_layout_tracker_bdev_init(UINT32_MAX);
     142                 :          4 :         g_dev.nvc_layout_tracker = ftl_layout_tracker_bdev_init(UINT32_MAX);
     143                 :          4 :         g_dev.base_bdev_desc = &g_base_bdev_desc;
     144                 :          4 :         g_dev.nv_cache.bdev_desc = &g_nvc_bdev_desc;
     145                 :            : 
     146         [ +  + ]:         76 :         for (int regno = 0; regno < FTL_LAYOUT_REGION_TYPE_MAX; regno++) {
     147                 :         72 :                 struct ftl_layout_region *reg = &g_dev.layout.region[regno];
     148                 :            : 
     149                 :         72 :                 reg->current.blocks = TEST_REG_BLKS;
     150         [ +  + ]:         72 :                 regno_dev = sb_v3_md_region_is_nvc(regno) ? &regno_nvc : &regno_base;
     151                 :         72 :                 reg->current.offset = *regno_dev * TEST_REG_BLKS;
     152                 :         72 :                 (*regno_dev)++;
     153                 :         72 :                 reg->current.version = ftl_layout_upgrade_region_get_latest_version(regno);
     154                 :         72 :                 reg->type = regno;
     155                 :         72 :                 reg->name = "region_test";
     156         [ +  + ]:         72 :                 reg->bdev_desc = sb_v3_md_region_is_nvc(regno) ? &g_nvc_bdev_desc : &g_base_bdev_desc;
     157                 :         72 :                 reg->ioch = 0;
     158                 :            :         }
     159                 :          4 :         return 0;
     160                 :            : }
     161                 :            : 
     162                 :            : static int
     163                 :          4 : test_teardown(void)
     164                 :            : {
     165         [ +  - ]:          4 :         if (g_dev.base_layout_tracker) {
     166                 :          4 :                 ftl_layout_tracker_bdev_fini(g_dev.base_layout_tracker);
     167                 :          4 :                 g_dev.base_layout_tracker = NULL;
     168                 :            :         }
     169         [ +  - ]:          4 :         if (g_dev.nvc_layout_tracker) {
     170                 :          4 :                 ftl_layout_tracker_bdev_fini(g_dev.nvc_layout_tracker);
     171                 :          4 :                 g_dev.nvc_layout_tracker = NULL;
     172                 :            :         }
     173                 :          4 :         return 0;
     174                 :            : }
     175                 :            : 
     176                 :            : static void
     177                 :         16 : test_setup_sb_ver(uint64_t ver, uint64_t clean)
     178                 :            : {
     179                 :         16 :         union ftl_superblock_ver *sb = (void *)g_sb_buf;
     180                 :            :         uint64_t zero_offs;
     181                 :            : 
     182         [ -  + ]:         16 :         memset(&g_sb_buf, 0, sizeof(g_sb_buf));
     183                 :         16 :         ftl_mngt_init_default_sb(&g_dev, NULL);
     184         [ +  + ]:         16 :         if (ver <= FTL_SB_VERSION_3) {
     185                 :         12 :                 sb->header.magic = FTL_SUPERBLOCK_MAGIC_V2;
     186                 :            :         }
     187                 :         16 :         sb->header.version = ver;
     188                 :            : 
     189   [ +  +  +  - ]:         16 :         switch (ver) {
     190                 :          4 :         case FTL_SB_VERSION_0:
     191                 :            :         case FTL_SB_VERSION_1:
     192                 :            :         case FTL_SB_VERSION_2:
     193                 :          4 :                 zero_offs = sizeof(struct ftl_superblock_v2);
     194         [ -  + ]:          4 :                 memset(g_sb_buf + zero_offs, 0, sizeof(g_sb_buf) - zero_offs);
     195                 :          4 :                 sb->v2.clean = clean;
     196                 :          4 :                 break;
     197                 :            : 
     198                 :          8 :         case FTL_SB_VERSION_3:
     199                 :            :         case FTL_SB_VERSION_4:
     200                 :          8 :                 zero_offs = sizeof(struct ftl_superblock_v3);
     201         [ -  + ]:          8 :                 memset(g_sb_buf + zero_offs, 0, sizeof(g_sb_buf) - zero_offs);
     202                 :          8 :                 sb->v3.clean = clean;
     203                 :          8 :                 sb->v3.md_layout_head.type = FTL_LAYOUT_REGION_TYPE_INVALID;
     204                 :          8 :                 break;
     205                 :            : 
     206                 :          4 :         case FTL_SB_VERSION_5:
     207                 :          4 :                 zero_offs = sizeof(struct ftl_superblock_v5);
     208         [ -  + ]:          4 :                 memset(g_sb_buf + zero_offs, 0, sizeof(g_sb_buf) - zero_offs);
     209                 :          4 :                 sb->v5.clean = clean;
     210                 :          4 :                 break;
     211                 :            :         }
     212                 :            : 
     213                 :         16 :         sb->header.crc = get_sb_crc(&sb->current);
     214                 :         16 : }
     215                 :            : 
     216                 :            : static void
     217                 :          4 : test_setup_sb_v2(uint64_t clean)
     218                 :            : {
     219                 :          4 :         test_setup_sb_ver(FTL_SB_VERSION_2, clean);
     220                 :          4 : }
     221                 :            : 
     222                 :            : static void
     223                 :          8 : test_setup_sb_v3(uint64_t clean)
     224                 :            : {
     225                 :          8 :         test_setup_sb_ver(FTL_SB_VERSION_3, clean);
     226                 :          8 : }
     227                 :            : 
     228                 :            : static void
     229                 :          4 : test_setup_sb_v5(uint64_t clean)
     230                 :            : {
     231                 :          4 :         test_setup_sb_ver(FTL_SB_VERSION_5, clean);
     232                 :          4 : }
     233                 :            : 
     234                 :            : static void
     235                 :          4 : test_sb_crc_v2(void)
     236                 :            : {
     237                 :          4 :         union ftl_superblock_ver *sb = (void *)g_sb_buf;
     238                 :            :         uint64_t crc;
     239                 :            : 
     240                 :            :         /* v2-specific crc: it's not really working */
     241                 :          4 :         test_setup_sb_v2(true);
     242                 :          4 :         crc = sb->header.crc;
     243                 :            : 
     244                 :          4 :         sb->header.crc++;
     245                 :          4 :         sb->header.crc = get_sb_crc(&sb->current);
     246                 :          4 :         CU_ASSERT_EQUAL(crc, sb->header.crc);
     247                 :            : 
     248                 :          4 :         g_sb_buf[sizeof(struct ftl_superblock_v2)]++;
     249                 :          4 :         sb->header.crc = get_sb_crc(&sb->current);
     250                 :          4 :         CU_ASSERT_EQUAL(crc, sb->header.crc);
     251                 :            : 
     252                 :          4 :         g_sb_buf[sizeof(g_sb_buf) - 1]++;
     253                 :          4 :         sb->header.crc = get_sb_crc(&sb->current);
     254                 :          4 :         CU_ASSERT_EQUAL(crc, sb->header.crc);
     255                 :          4 : }
     256                 :            : 
     257                 :            : static void
     258                 :          4 : test_sb_crc_v3(void)
     259                 :            : {
     260                 :          4 :         union ftl_superblock_ver *sb = (void *)g_sb_buf;
     261                 :            :         uint64_t crc;
     262                 :            : 
     263                 :            :         /* v3 crc: covers the entire buf */
     264                 :          4 :         test_setup_sb_v3(true);
     265                 :          4 :         crc = sb->header.crc;
     266                 :            : 
     267                 :          4 :         sb->header.crc++;
     268                 :          4 :         sb->header.crc = get_sb_crc(&sb->current);
     269                 :          4 :         CU_ASSERT_EQUAL(crc, sb->header.crc);
     270                 :          4 :         crc = sb->header.crc;
     271                 :            : 
     272                 :          4 :         g_sb_buf[sizeof(struct ftl_superblock_v2)]++;
     273                 :          4 :         sb->header.crc = get_sb_crc(&sb->current);
     274                 :          4 :         CU_ASSERT_NOT_EQUAL(crc, sb->header.crc);
     275                 :          4 :         crc = sb->header.crc;
     276                 :            : 
     277                 :          4 :         g_sb_buf[sizeof(g_sb_buf) - 1]++;
     278                 :          4 :         sb->header.crc = get_sb_crc(&sb->current);
     279                 :          4 :         CU_ASSERT_NOT_EQUAL(crc, sb->header.crc);
     280                 :          4 :         crc = sb->header.crc;
     281                 :            : 
     282                 :          4 :         CU_ASSERT_EQUAL(crc, sb->header.crc);
     283                 :          4 : }
     284                 :            : 
     285                 :            : static int
     286                 :         68 : test_superblock_v3_md_layout_add(struct spdk_ftl_dev *dev,
     287                 :            :                                  struct ftl_superblock_v3_md_region *sb_reg,
     288                 :            :                                  uint32_t reg_type, uint32_t reg_version, uint64_t blk_offs, uint64_t blk_sz)
     289                 :            : {
     290         [ -  + ]:         68 :         if (ftl_superblock_v3_md_region_overflow(dev, sb_reg)) {
     291                 :          0 :                 return -EOVERFLOW;
     292                 :            :         }
     293                 :            : 
     294                 :         68 :         sb_reg->type = reg_type;
     295                 :         68 :         sb_reg->version = reg_version;
     296                 :         68 :         sb_reg->blk_offs = blk_offs;
     297                 :         68 :         sb_reg->blk_sz = blk_sz;
     298                 :         68 :         return 0;
     299                 :            : }
     300                 :            : 
     301                 :            : static int
     302                 :          8 : test_superblock_v3_md_layout_add_free(struct spdk_ftl_dev *dev,
     303                 :            :                                       struct ftl_superblock_v3_md_region **sb_reg,
     304                 :            :                                       uint32_t reg_type, uint32_t free_type, uint64_t total_blocks)
     305                 :            : {
     306                 :          8 :         struct ftl_layout *layout = &dev->layout;
     307                 :          8 :         struct ftl_layout_region *reg = &layout->region[reg_type];
     308                 :          8 :         uint64_t blks_left = total_blocks - reg->current.offset - reg->current.blocks;
     309                 :            : 
     310         [ -  + ]:          8 :         if (blks_left == 0) {
     311                 :          0 :                 return 0;
     312                 :            :         }
     313                 :            : 
     314                 :          8 :         (*sb_reg)->df_next = ftl_df_get_obj_id(dev->sb, (*sb_reg) + 1);
     315                 :          8 :         (*sb_reg) = (*sb_reg) + 1;
     316                 :            : 
     317         [ -  + ]:          8 :         if (test_superblock_v3_md_layout_add(dev, *sb_reg, free_type, 0,
     318                 :          8 :                                              reg->current.offset + reg->current.blocks, blks_left)) {
     319                 :          0 :                 return -1;
     320                 :            :         }
     321                 :            : 
     322                 :          8 :         (*sb_reg)->df_next = FTL_DF_OBJ_ID_INVALID;
     323                 :            : 
     324                 :          8 :         return 0;
     325                 :            : }
     326                 :            : 
     327                 :            : static int
     328                 :          4 : test_ftl_superblock_v3_md_layout_build(struct spdk_ftl_dev *dev)
     329                 :            : {
     330                 :          4 :         union ftl_superblock_ver *sb_ver = (union ftl_superblock_ver *)dev->sb;
     331                 :          4 :         struct ftl_layout *layout = &dev->layout;
     332                 :            :         struct ftl_layout_region *reg;
     333                 :          4 :         int n = 0;
     334                 :          4 :         bool is_empty = ftl_superblock_v3_md_layout_is_empty(sb_ver);
     335                 :          4 :         struct ftl_superblock_v3_md_region *sb_reg = &sb_ver->v3.md_layout_head;
     336                 :            : 
     337                 :            :         /* TODO: major upgrades: add all free regions being tracked
     338                 :            :          * For now SB MD layout must be empty - otherwise md free regions may be lost */
     339         [ -  + ]:          4 :         assert(is_empty);
     340                 :            : 
     341         [ +  + ]:         68 :         for (; n < FTL_LAYOUT_REGION_TYPE_MAX_V3;) {
     342                 :         64 :                 reg = ftl_layout_region_get(dev, n);
     343         [ -  + ]:         64 :                 assert(reg);
     344         [ +  + ]:         64 :                 if (md_region_is_fixed(reg->type)) {
     345                 :         12 :                         n++;
     346                 :            : 
     347         [ -  + ]:         12 :                         if (n >= FTL_LAYOUT_REGION_TYPE_MAX_V3) {
     348                 :            :                                 /* For VSS emulation the last layout type is a fixed region, we need to move back the list and end the list on previous entry */
     349                 :          0 :                                 sb_reg--;
     350                 :          0 :                                 break;
     351                 :            :                         }
     352                 :         12 :                         continue;
     353                 :            :                 }
     354                 :            : 
     355         [ -  + ]:         52 :                 if (test_superblock_v3_md_layout_add(dev, sb_reg, reg->type, reg->current.version,
     356                 :            :                                                      reg->current.offset, reg->current.blocks)) {
     357                 :          0 :                         return -1;
     358                 :            :                 }
     359                 :            : 
     360                 :         52 :                 n++;
     361         [ +  + ]:         52 :                 if (n < FTL_LAYOUT_REGION_TYPE_MAX_V3) {
     362                 :            :                         /* next region */
     363                 :         48 :                         sb_reg->df_next = ftl_df_get_obj_id(sb_ver, sb_reg + 1);
     364                 :         48 :                         sb_reg++;
     365                 :            :                 }
     366                 :            :         }
     367                 :            : 
     368                 :            :         /* terminate the list */
     369                 :          4 :         sb_reg->df_next = FTL_DF_OBJ_ID_INVALID;
     370                 :            : 
     371                 :            :         /* create free_nvc/free_base regions on the first run */
     372         [ +  - ]:          4 :         if (is_empty) {
     373                 :          4 :                 test_superblock_v3_md_layout_add_free(dev, &sb_reg, FTL_LAYOUT_REGION_LAST_NVC,
     374                 :            :                                                       FTL_LAYOUT_REGION_TYPE_FREE_NVC, layout->nvc.total_blocks);
     375                 :            : 
     376                 :          4 :                 test_superblock_v3_md_layout_add_free(dev, &sb_reg, FTL_LAYOUT_REGION_LAST_BASE,
     377                 :            :                                                       FTL_LAYOUT_REGION_TYPE_FREE_BASE, layout->base.total_blocks);
     378                 :            :         }
     379                 :            : 
     380                 :          4 :         return 0;
     381                 :            : }
     382                 :            : 
     383                 :            : static void
     384                 :         64 : test_sb_v3_region_reinit(void)
     385                 :            : {
     386                 :            :         uint32_t reg_type;
     387                 :            : 
     388         [ +  + ]:       1216 :         for (reg_type = 0; reg_type < FTL_LAYOUT_REGION_TYPE_MAX; reg_type++) {
     389                 :       1152 :                 g_dev.layout.region[reg_type].type = reg_type;
     390                 :            :         }
     391                 :         64 : }
     392                 :            : 
     393                 :            : static struct ftl_superblock_v3_md_region *
     394                 :          4 : test_sb_v3_find_region_ver(enum ftl_layout_region_type reg_type, uint32_t reg_ver)
     395                 :            : {
     396                 :          4 :         union ftl_superblock_ver *sb = (void *)g_sb_buf;
     397                 :          4 :         struct ftl_superblock_v3_md_region *sb_reg = &sb->v3.md_layout_head;
     398                 :            : 
     399         [ +  - ]:          8 :         while (sb_reg->type != FTL_LAYOUT_REGION_TYPE_INVALID) {
     400   [ +  +  +  - ]:          8 :                 if (sb_reg->type == reg_type && sb_reg->version == reg_ver) {
     401                 :          4 :                         return sb_reg;
     402                 :            :                 }
     403                 :            : 
     404         [ -  + ]:          4 :                 if (sb_reg->df_next == FTL_DF_OBJ_ID_INVALID) {
     405                 :          0 :                         break;
     406                 :            :                 }
     407                 :            : 
     408         [ -  + ]:          4 :                 if (UINT64_MAX - (uintptr_t)sb <= sb_reg->df_next) {
     409                 :          0 :                         return NULL;
     410                 :            :                 }
     411                 :            : 
     412                 :          4 :                 sb_reg = ftl_df_get_obj_ptr(sb, sb_reg->df_next);
     413         [ -  + ]:          4 :                 if (ftl_superblock_v3_md_region_overflow(&g_dev, sb_reg)) {
     414                 :          0 :                         return NULL;
     415                 :            :                 }
     416                 :            :         }
     417                 :            : 
     418                 :          0 :         return NULL;
     419                 :            : }
     420                 :            : 
     421                 :            : static struct ftl_superblock_v3_md_region *
     422                 :          4 : test_sb_v3_find_region_latest(enum ftl_layout_region_type reg_type)
     423                 :            : {
     424                 :          4 :         return test_sb_v3_find_region_ver(reg_type, ftl_layout_upgrade_region_get_latest_version(reg_type));
     425                 :            : }
     426                 :            : 
     427                 :            : static void
     428                 :          4 : test_sb_v3_md_layout(void)
     429                 :            : {
     430                 :            :         struct ftl_superblock_v3_md_region *sb_reg, *sb_reg_next, *sb_reg_next2;
     431                 :            :         struct ftl_layout_region *reg_head, *reg;
     432                 :          4 :         union ftl_superblock_ver *sb = (void *)g_sb_buf;
     433                 :            :         ftl_df_obj_id df_next_head, df_next_reg;
     434                 :            :         uint32_t md_type_head;
     435                 :            :         int rc;
     436                 :            : 
     437                 :          4 :         test_setup_sb_v3(false);
     438                 :          4 :         CU_ASSERT_EQUAL(ftl_superblock_is_blob_area_empty(&sb->current), true);
     439                 :            : 
     440                 :            :         /* load failed: empty md list: */
     441                 :          4 :         rc = ftl_superblock_v3_md_layout_load_all(&g_dev);
     442                 :          4 :         CU_ASSERT_NOT_EQUAL(rc, 0);
     443                 :          4 :         test_sb_v3_region_reinit();
     444                 :            : 
     445                 :            :         /* create md layout: */
     446                 :          4 :         test_ftl_superblock_v3_md_layout_build(&g_dev);
     447                 :          4 :         CU_ASSERT_EQUAL(ftl_superblock_is_blob_area_empty(&sb->current), false);
     448                 :            : 
     449                 :            :         /* buf overflow, sb_reg = 1 byte overflow: */
     450                 :          4 :         df_next_head = sb->v3.md_layout_head.df_next;
     451                 :          4 :         sb->v3.md_layout_head.df_next = FTL_SUPERBLOCK_SIZE - sizeof(sb->v3.md_layout_head) + 1;
     452                 :          4 :         rc = ftl_superblock_v3_md_layout_load_all(&g_dev);
     453                 :          4 :         CU_ASSERT_EQUAL(rc, -EOVERFLOW);
     454                 :          4 :         test_sb_v3_region_reinit();
     455                 :            : 
     456                 :            :         /* buf underflow, sb_reg = -1: */
     457                 :          4 :         sb->v3.md_layout_head.df_next = UINTPTR_MAX - (uintptr_t)sb;
     458                 :          4 :         rc = ftl_superblock_v3_md_layout_load_all(&g_dev);
     459                 :          4 :         CU_ASSERT_EQUAL(rc, -EOVERFLOW);
     460                 :          4 :         test_sb_v3_region_reinit();
     461                 :            : 
     462                 :            :         /* buf underflow, sb_reg = 2 bytes underflow */
     463                 :          4 :         sb->v3.md_layout_head.df_next = UINTPTR_MAX - 1;
     464                 :          4 :         rc = ftl_superblock_v3_md_layout_load_all(&g_dev);
     465                 :          4 :         CU_ASSERT_EQUAL(rc, -EOVERFLOW);
     466                 :          4 :         test_sb_v3_region_reinit();
     467                 :            : 
     468                 :            :         /* looping md layout list: */
     469                 :          4 :         sb->v3.md_layout_head.df_next = ftl_df_get_obj_id(sb, &sb->v3.md_layout_head);
     470                 :          4 :         rc = ftl_superblock_v3_md_layout_load_all(&g_dev);
     471                 :          4 :         CU_ASSERT_NOT_EQUAL(rc, 0);
     472                 :          4 :         test_sb_v3_region_reinit();
     473                 :            : 
     474                 :          4 :         sb->v3.md_layout_head.df_next = df_next_head;
     475                 :            : 
     476                 :            :         /* unsupported/fixed md region: */
     477                 :          4 :         md_type_head = sb->v3.md_layout_head.type;
     478                 :          4 :         sb->v3.md_layout_head.type = FTL_LAYOUT_REGION_TYPE_SB;
     479                 :          4 :         rc = ftl_superblock_v3_md_layout_load_all(&g_dev);
     480                 :          4 :         CU_ASSERT_NOT_EQUAL(rc, 0);
     481                 :          4 :         test_sb_v3_region_reinit();
     482                 :            : 
     483                 :            :         /* unsupported/invalid md region: */
     484                 :          4 :         sb->v3.md_layout_head.type = FTL_LAYOUT_REGION_TYPE_MAX;
     485                 :          4 :         rc = ftl_superblock_v3_md_layout_load_all(&g_dev);
     486                 :          4 :         CU_ASSERT_NOT_EQUAL(rc, 0);
     487                 :          4 :         test_sb_v3_region_reinit();
     488                 :            : 
     489                 :            :         /* unsupported/invalid md region: */
     490                 :          4 :         sb->v3.md_layout_head.type = FTL_LAYOUT_REGION_TYPE_MAX_V3;
     491                 :          4 :         rc = ftl_superblock_v3_md_layout_load_all(&g_dev);
     492                 :          4 :         CU_ASSERT_NOT_EQUAL(rc, 0);
     493                 :          4 :         test_sb_v3_region_reinit();
     494                 :            : 
     495                 :            :         /* restore the sb: */
     496                 :          4 :         sb->v3.md_layout_head.type = md_type_head;
     497                 :            : 
     498                 :            :         /* load succeeded, no prev version found: */
     499                 :          4 :         reg_head = &g_dev.layout.region[md_type_head];
     500                 :          4 :         rc = ftl_superblock_v3_md_layout_load_all(&g_dev);
     501                 :          4 :         CU_ASSERT_EQUAL(rc, 0);
     502                 :          4 :         CU_ASSERT_EQUAL(reg_head->current.version,
     503                 :            :                         ftl_layout_upgrade_region_get_latest_version(md_type_head));
     504                 :          4 :         test_sb_v3_region_reinit();
     505                 :            : 
     506                 :            :         /* load succeeded, prev (upgrade, i.e. no current) version discovery: */
     507                 :          4 :         reg = &g_dev.layout.region[FTL_LAYOUT_REGION_TYPE_BAND_MD];
     508                 :          4 :         sb_reg = test_sb_v3_find_region_latest(FTL_LAYOUT_REGION_TYPE_BAND_MD);
     509                 :          4 :         CU_ASSERT_NOT_EQUAL(sb_reg, NULL);
     510                 :          4 :         CU_ASSERT_EQUAL(reg->type, sb_reg->type);
     511                 :          4 :         df_next_reg = sb_reg->df_next;
     512                 :            : 
     513                 :          4 :         sb_reg->version--;
     514                 :          4 :         rc = ftl_superblock_v3_md_layout_load_all(&g_dev);
     515                 :          4 :         CU_ASSERT_EQUAL(rc, 0);
     516                 :          4 :         CU_ASSERT_EQUAL(reg->current.version, sb_reg->version);
     517                 :          4 :         sb_reg->version++;
     518                 :          4 :         test_sb_v3_region_reinit();
     519                 :            : 
     520                 :            :         /* load succeeded, newer version found: */
     521                 :          4 :         sb_reg->df_next = FTL_SUPERBLOCK_SIZE - sizeof(*sb_reg_next);
     522                 :          4 :         sb_reg_next = ftl_df_get_obj_ptr(sb, sb_reg->df_next);
     523                 :          4 :         rc = test_superblock_v3_md_layout_add(&g_dev, sb_reg_next, sb_reg->type, sb_reg->version + 1,
     524                 :            :                                               sb_reg->blk_offs, sb_reg->blk_sz);
     525                 :          4 :         CU_ASSERT_EQUAL(rc, 0);
     526                 :          4 :         sb_reg_next->df_next = df_next_reg;
     527                 :          4 :         rc = ftl_superblock_v3_md_layout_load_all(&g_dev);
     528                 :          4 :         CU_ASSERT_EQUAL(rc, 0);
     529                 :          4 :         CU_ASSERT_EQUAL(reg->current.version, sb_reg->version);
     530                 :          4 :         test_sb_v3_region_reinit();
     531                 :            : 
     532                 :            :         /* load succeeded, prev version discovery: */
     533                 :          4 :         sb_reg_next->version = sb_reg->version - 1;
     534                 :          4 :         rc = ftl_superblock_v3_md_layout_load_all(&g_dev);
     535                 :          4 :         CU_ASSERT_EQUAL(rc, 0);
     536                 :          4 :         CU_ASSERT_EQUAL(reg->current.version, sb_reg_next->version);
     537                 :          4 :         test_sb_v3_region_reinit();
     538                 :            : 
     539                 :            :         /* looping regions found: */
     540                 :          4 :         sb_reg_next->df_next = FTL_SUPERBLOCK_SIZE - 2 * sizeof(*sb_reg_next);
     541                 :          4 :         sb_reg_next2 = ftl_df_get_obj_ptr(sb, sb_reg_next->df_next);
     542                 :          6 :         rc = test_superblock_v3_md_layout_add(&g_dev, sb_reg_next2, sb_reg_next->type,
     543                 :          4 :                                               sb_reg_next->version + 2,
     544                 :            :                                               sb_reg_next->blk_offs, sb_reg_next->blk_sz);
     545                 :          4 :         CU_ASSERT_EQUAL(rc, 0);
     546                 :          4 :         sb_reg_next2->df_next = FTL_SUPERBLOCK_SIZE - 2 * sizeof(*sb_reg_next);
     547                 :          4 :         rc = ftl_superblock_v3_md_layout_load_all(&g_dev);
     548                 :          4 :         CU_ASSERT_EQUAL(rc, -ELOOP);
     549                 :          4 :         test_sb_v3_region_reinit();
     550                 :            : 
     551                 :            :         /* multiple (same ver) regions found: */
     552                 :          4 :         sb_reg_next2->version = sb_reg_next->version;
     553                 :          4 :         sb_reg_next2->df_next = df_next_reg;
     554                 :          4 :         rc = ftl_superblock_v3_md_layout_load_all(&g_dev);
     555                 :          4 :         CU_ASSERT_EQUAL(rc, -EAGAIN);
     556                 :          4 :         test_sb_v3_region_reinit();
     557                 :            : 
     558                 :            :         /* multiple (different ver) prev regions found: */
     559                 :          4 :         sb_reg_next2->version = sb_reg_next->version - 1;
     560                 :          4 :         rc = ftl_superblock_v3_md_layout_load_all(&g_dev);
     561                 :          4 :         CU_ASSERT_EQUAL(rc, 0);
     562                 :          4 :         CU_ASSERT_EQUAL(reg->current.version, sb_reg_next2->version);
     563                 :          4 :         test_sb_v3_region_reinit();
     564                 :            : 
     565                 :            :         /* multiple current regions found: */
     566                 :          4 :         sb_reg_next->version = sb_reg->version;
     567                 :          4 :         sb_reg_next->df_next = df_next_reg;
     568                 :          4 :         rc = ftl_superblock_v3_md_layout_load_all(&g_dev);
     569                 :          4 :         CU_ASSERT_EQUAL(rc, -EAGAIN);
     570                 :            : 
     571                 :            :         /* restore the sb: */
     572                 :          4 :         sb->v3.md_layout_head.df_next = df_next_head;
     573                 :          4 :         test_sb_v3_region_reinit();
     574                 :          4 : }
     575                 :            : 
     576                 :            : static void
     577                 :          4 : test_sb_v5_md_layout(void)
     578                 :            : {
     579                 :            :         struct layout_tracker_blob_entry *tbe;
     580                 :            :         struct layout_blob_entry *lbe;
     581                 :            :         struct ftl_layout_region *reg;
     582                 :          4 :         union ftl_superblock_ver *sb = (void *)g_sb_buf;
     583                 :            :         int rc;
     584                 :            :         const struct ftl_layout_tracker_bdev_region_props *reg_props;
     585                 :            :         void *blob_nvc, *blob_base, *blob_regs;
     586                 :            : 
     587                 :          4 :         test_setup_sb_v5(false);
     588                 :          4 :         CU_ASSERT_EQUAL(ftl_superblock_is_blob_area_empty(&sb->current), true);
     589                 :            : 
     590                 :            :         /* load failed: empty md list: */
     591                 :          4 :         rc = ftl_superblock_v5_load_blob_area(&g_dev);
     592                 :          4 :         CU_ASSERT_NOT_EQUAL(rc, 0);
     593                 :            : 
     594                 :            :         /* create md layout: */
     595         [ +  + ]:         76 :         for (enum ftl_layout_region_type regno = 0; regno < FTL_LAYOUT_REGION_TYPE_MAX; regno++) {
     596                 :         72 :                 struct ftl_layout_region *reg = &g_dev.layout.region[regno];
     597                 :         72 :                 CU_ASSERT_EQUAL(regno, reg->type);
     598         [ +  + ]:         72 :                 struct ftl_layout_tracker_bdev *tracker = sb_v3_md_region_is_nvc(regno) ? g_dev.nvc_layout_tracker :
     599                 :            :                                 g_dev.base_layout_tracker;
     600                 :        108 :                 const struct ftl_layout_tracker_bdev_region_props *reg_props = ftl_layout_tracker_bdev_add_region(
     601                 :         72 :                                         tracker, reg->type, reg->current.version, reg->current.blocks, TEST_REG_BLKS);
     602                 :            : 
     603                 :         72 :                 CU_ASSERT_EQUAL(reg->type, reg_props->type);
     604                 :         72 :                 CU_ASSERT_EQUAL(reg->current.version, reg_props->ver);
     605                 :         72 :                 CU_ASSERT_EQUAL(reg->current.offset, reg_props->blk_offs);
     606                 :         72 :                 CU_ASSERT_EQUAL(reg->current.blocks, reg_props->blk_sz);
     607                 :            :         }
     608                 :          4 :         ftl_superblock_v5_store_blob_area(&g_dev);
     609                 :          4 :         CU_ASSERT_EQUAL(ftl_superblock_is_blob_area_empty(&sb->current), false);
     610                 :            : 
     611                 :          4 :         blob_nvc = ftl_df_get_obj_ptr(sb->v5.blob_area, sb->v5.md_layout_nvc.df_id);
     612                 :          4 :         blob_base = ftl_df_get_obj_ptr(sb->v5.blob_area, sb->v5.md_layout_base.df_id);
     613                 :          4 :         blob_regs = ftl_df_get_obj_ptr(sb->v5.blob_area, sb->v5.layout_params.df_id);
     614                 :            : 
     615                 :            :         /* unsupported nvc md region type: */
     616                 :          4 :         tbe = blob_nvc;
     617                 :          4 :         tbe->type += FTL_LAYOUT_REGION_TYPE_MAX;
     618                 :          4 :         sb->v3.md_layout_head.type = FTL_LAYOUT_REGION_TYPE_SB;
     619                 :          4 :         rc = ftl_superblock_v5_load_blob_area(&g_dev);
     620                 :          4 :         CU_ASSERT_NOT_EQUAL(rc, 0);
     621                 :          4 :         tbe->type -= FTL_LAYOUT_REGION_TYPE_MAX;
     622                 :            : 
     623                 :            :         /* unsupported base md region type: */
     624                 :          4 :         tbe = blob_base;
     625                 :          4 :         tbe->type += FTL_LAYOUT_REGION_TYPE_MAX;
     626                 :          4 :         sb->v3.md_layout_head.type = FTL_LAYOUT_REGION_TYPE_SB;
     627                 :          4 :         rc = ftl_superblock_v5_load_blob_area(&g_dev);
     628                 :          4 :         CU_ASSERT_NOT_EQUAL(rc, 0);
     629                 :          4 :         tbe->type -= FTL_LAYOUT_REGION_TYPE_MAX;
     630                 :            : 
     631                 :            :         /* load succeeded, no prev version found: */
     632                 :          4 :         reg = &g_dev.layout.region[FTL_LAYOUT_REGION_TYPE_BAND_MD];
     633                 :          4 :         rc = ftl_superblock_v5_load_blob_area(&g_dev);
     634                 :          4 :         CU_ASSERT_EQUAL(rc, 0);
     635                 :          4 :         reg_props = sb_md_layout_find_region(&g_dev, reg->type, sb_md_layout_find_latest_region, NULL);
     636                 :          4 :         CU_ASSERT_NOT_EQUAL(reg_props, NULL);
     637                 :          4 :         CU_ASSERT_EQUAL(reg_props->ver, reg->current.version);
     638                 :          4 :         reg_props = sb_md_layout_find_region(&g_dev, reg->type, sb_md_layout_find_oldest_region, NULL);
     639                 :          4 :         CU_ASSERT_NOT_EQUAL(reg_props, NULL);
     640                 :          4 :         CU_ASSERT_EQUAL(reg_props->ver, reg->current.version);
     641                 :            : 
     642                 :            :         /* move the sb-stored blobs around: */
     643                 :          4 :         CU_ASSERT(blob_nvc < blob_base);
     644                 :          4 :         CU_ASSERT(blob_base < blob_regs);
     645   [ -  +  -  + ]:          4 :         blob_regs = memmove(blob_regs + 8192, blob_regs, sb->v5.layout_params.blob_sz);
     646                 :          4 :         sb->v5.layout_params.df_id += 8192;
     647   [ -  +  -  + ]:          4 :         blob_base = memmove(blob_base + 4096, blob_base, sb->v5.md_layout_base.blob_sz);
     648                 :          4 :         sb->v5.md_layout_base.df_id += 4096;
     649                 :            : 
     650                 :            :         /* load succeeded again, no prev version found: */
     651                 :          4 :         rc = ftl_superblock_v5_load_blob_area(&g_dev);
     652                 :          4 :         CU_ASSERT_EQUAL(rc, 0);
     653                 :          4 :         reg_props = sb_md_layout_find_region(&g_dev, reg->type, sb_md_layout_find_latest_region, NULL);
     654                 :          4 :         CU_ASSERT_NOT_EQUAL(reg_props, NULL);
     655                 :          4 :         CU_ASSERT_EQUAL(reg_props->ver, reg->current.version);
     656                 :          4 :         reg_props = sb_md_layout_find_region(&g_dev, reg->type, sb_md_layout_find_oldest_region, NULL);
     657                 :          4 :         CU_ASSERT_NOT_EQUAL(reg_props, NULL);
     658                 :          4 :         CU_ASSERT_EQUAL(reg_props->ver, reg->current.version);
     659                 :            : 
     660                 :            :         /* load failed, regs overlap: */
     661                 :          4 :         tbe = blob_nvc;
     662                 :          4 :         tbe++;
     663                 :          4 :         tbe->blk_offs -= tbe->blk_sz;
     664                 :          4 :         rc = ftl_superblock_v5_load_blob_area(&g_dev);
     665                 :          4 :         CU_ASSERT_NOT_EQUAL(rc, 0);
     666                 :          4 :         tbe->blk_offs += tbe->blk_sz;
     667                 :            : 
     668                 :            :         /* load failed, the same region version found twice: */
     669                 :          4 :         tbe = (blob_nvc + sb->v5.md_layout_nvc.blob_sz);
     670                 :          4 :         sb->v5.md_layout_nvc.blob_sz += sizeof(*tbe);
     671                 :          4 :         tbe->type = reg->type;
     672                 :          4 :         tbe->ver = reg->current.version;
     673                 :          4 :         tbe->blk_offs = reg->current.offset + FTL_LAYOUT_REGION_TYPE_MAX * reg->current.blocks;
     674                 :          4 :         tbe->blk_sz = reg->current.blocks;
     675                 :          4 :         rc = ftl_superblock_v5_load_blob_area(&g_dev);
     676                 :          4 :         CU_ASSERT_NOT_EQUAL(rc, 0);
     677                 :            : 
     678                 :            :         /* load succeeded, prev (upgrade, i.e. no current) version discovery: */
     679                 :          4 :         tbe->type = reg->type;
     680                 :          4 :         tbe->ver = reg->current.version - 1;
     681                 :          4 :         tbe->blk_offs = reg->current.offset + FTL_LAYOUT_REGION_TYPE_MAX * reg->current.blocks;
     682                 :          4 :         tbe->blk_sz = reg->current.blocks;
     683                 :          4 :         rc = ftl_superblock_v5_load_blob_area(&g_dev);
     684                 :          4 :         CU_ASSERT_EQUAL(rc, 0);
     685                 :          4 :         reg_props = sb_md_layout_find_region(&g_dev, reg->type, sb_md_layout_find_latest_region, NULL);
     686                 :          4 :         CU_ASSERT_NOT_EQUAL(reg_props, NULL);
     687                 :          4 :         CU_ASSERT_EQUAL(reg_props->ver, reg->current.version);
     688                 :          4 :         reg_props = sb_md_layout_find_region(&g_dev, reg->type, sb_md_layout_find_oldest_region, NULL);
     689                 :          4 :         CU_ASSERT_NOT_EQUAL(reg_props, NULL);
     690                 :          4 :         CU_ASSERT_EQUAL(reg_props->ver, reg->current.version - 1);
     691                 :            : 
     692                 :            :         /* load succeeded, newer version found: */
     693                 :          4 :         tbe->ver = reg->current.version + 1;
     694                 :          4 :         rc = ftl_superblock_v5_load_blob_area(&g_dev);
     695                 :          4 :         CU_ASSERT_EQUAL(rc, 0);
     696                 :          4 :         reg_props = sb_md_layout_find_region(&g_dev, reg->type, sb_md_layout_find_latest_region, NULL);
     697                 :          4 :         CU_ASSERT_NOT_EQUAL(reg_props, NULL);
     698                 :          4 :         CU_ASSERT_EQUAL(reg_props->ver, reg->current.version + 1);
     699                 :          4 :         reg_props = sb_md_layout_find_region(&g_dev, reg->type, sb_md_layout_find_oldest_region, NULL);
     700                 :          4 :         CU_ASSERT_NOT_EQUAL(reg_props, NULL);
     701                 :          4 :         CU_ASSERT_EQUAL(reg_props->ver, reg->current.version);
     702                 :            : 
     703                 :            :         /* load failed, invalid type in layout properties: */
     704                 :          4 :         lbe = blob_regs;
     705                 :          4 :         lbe += FTL_LAYOUT_REGION_TYPE_BAND_MD;
     706                 :          4 :         CU_ASSERT_EQUAL(lbe->type, FTL_LAYOUT_REGION_TYPE_BAND_MD);
     707                 :          4 :         lbe->type = FTL_LAYOUT_REGION_TYPE_MAX;
     708                 :          4 :         rc = ftl_superblock_v5_load_blob_area(&g_dev);
     709                 :          4 :         CU_ASSERT_NOT_EQUAL(rc, 0);
     710                 :          4 :         lbe->type = FTL_LAYOUT_REGION_TYPE_BAND_MD;
     711                 :            : 
     712                 :            :         /* load succeeded, restore layout properties: */
     713                 :          4 :         CU_ASSERT_EQUAL(reg->num_entries, 0);
     714                 :          4 :         CU_ASSERT_EQUAL(reg->entry_size, 0);
     715                 :          4 :         lbe->num_entries = 0x1984;
     716                 :          4 :         lbe->entry_size = 0x1405;
     717                 :          4 :         rc = ftl_superblock_v5_load_blob_area(&g_dev);
     718                 :          4 :         CU_ASSERT_EQUAL(rc, 0);
     719                 :          4 :         CU_ASSERT_EQUAL(reg->num_entries, 0x1984);
     720                 :          4 :         CU_ASSERT_EQUAL(reg->entry_size, 0x1405);
     721                 :            : 
     722                 :            :         /* restore the sb: */
     723                 :          4 :         sb->v5.md_layout_nvc.blob_sz -= sizeof(*tbe);
     724                 :          4 : }
     725                 :            : 
     726                 :            : int
     727                 :          4 : main(int argc, char **argv)
     728                 :            : {
     729                 :          4 :         CU_pSuite suite = NULL;
     730                 :          4 :         unsigned int num_failures = 0;
     731                 :            : 
     732                 :          4 :         CU_set_error_action(CUEA_ABORT);
     733                 :          4 :         CU_initialize_registry();
     734                 :            : 
     735                 :          4 :         suite = CU_add_suite("ftl_sb", test_setup, test_teardown);
     736                 :            : 
     737                 :          4 :         CU_ADD_TEST(suite, test_sb_crc_v2);
     738                 :          4 :         CU_ADD_TEST(suite, test_sb_crc_v3);
     739                 :          4 :         CU_ADD_TEST(suite, test_sb_v3_md_layout);
     740                 :          4 :         CU_ADD_TEST(suite, test_sb_v5_md_layout);
     741                 :            : 
     742                 :          4 :         CU_basic_set_mode(CU_BRM_VERBOSE);
     743                 :          4 :         CU_basic_run_tests();
     744                 :          4 :         num_failures = CU_get_number_of_failures();
     745                 :          4 :         CU_cleanup_registry();
     746                 :            : 
     747                 :          4 :         return num_failures;
     748                 :            : }

Generated by: LCOV version 1.14