1c8ab874dSKozlowski Mateusz /* SPDX-License-Identifier: BSD-3-Clause 2a6dbe372Spaul luse * Copyright (C) 2022 Intel Corporation. 3d9f2ae9dSMateusz Kozlowski * Copyright 2023 Solidigm All Rights Reserved 4c8ab874dSKozlowski Mateusz * All rights reserved. 5c8ab874dSKozlowski Mateusz */ 6c8ab874dSKozlowski Mateusz 7c8ab874dSKozlowski Mateusz #include <sys/queue.h> 8c8ab874dSKozlowski Mateusz 9c8ab874dSKozlowski Mateusz #include "spdk/stdinc.h" 10ae431e31SKonrad Sztyber #include "spdk_internal/cunit.h" 11c8ab874dSKozlowski Mateusz #include "common/lib/test_env.c" 12c8ab874dSKozlowski Mateusz 132bb1753bSLukasz Lasek #include "ftl/utils/ftl_layout_tracker_bdev.c" 14fa1fc76cSLukasz Lasek #include "ftl/upgrade/ftl_sb_v3.c" 152bb1753bSLukasz Lasek #include "ftl/upgrade/ftl_sb_v5.c" 16c8ab874dSKozlowski Mateusz #include "ftl/ftl_sb.c" 172bb1753bSLukasz Lasek #include "ftl/ftl_layout.c" 18c8ab874dSKozlowski Mateusz #include "ftl/upgrade/ftl_sb_upgrade.c" 192bb1753bSLukasz Lasek 202bb1753bSLukasz Lasek static struct ftl_layout_upgrade_desc_list layout_upgrade_desc[] = { 212bb1753bSLukasz Lasek [FTL_LAYOUT_REGION_TYPE_SB] = { 222bb1753bSLukasz Lasek .latest_ver = FTL_SB_VERSION_CURRENT, 232bb1753bSLukasz Lasek .count = FTL_SB_VERSION_CURRENT, 242bb1753bSLukasz Lasek }, 252bb1753bSLukasz Lasek [FTL_LAYOUT_REGION_TYPE_SB_BASE] = { 262bb1753bSLukasz Lasek .latest_ver = FTL_SB_VERSION_CURRENT, 272bb1753bSLukasz Lasek .count = FTL_SB_VERSION_CURRENT, 282bb1753bSLukasz Lasek }, 292bb1753bSLukasz Lasek [FTL_LAYOUT_REGION_TYPE_L2P] = {}, 302bb1753bSLukasz Lasek [FTL_LAYOUT_REGION_TYPE_BAND_MD] = { 312bb1753bSLukasz Lasek .latest_ver = FTL_BAND_VERSION_CURRENT, 322bb1753bSLukasz Lasek .count = FTL_BAND_VERSION_CURRENT, 332bb1753bSLukasz Lasek }, 342bb1753bSLukasz Lasek [FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR] = { 352bb1753bSLukasz Lasek .latest_ver = FTL_BAND_VERSION_CURRENT, 362bb1753bSLukasz Lasek .count = FTL_BAND_VERSION_CURRENT, 372bb1753bSLukasz Lasek }, 382bb1753bSLukasz Lasek [FTL_LAYOUT_REGION_TYPE_VALID_MAP] = {}, 392bb1753bSLukasz Lasek [FTL_LAYOUT_REGION_TYPE_NVC_MD] = { 402bb1753bSLukasz Lasek .latest_ver = FTL_NVC_VERSION_CURRENT, 412bb1753bSLukasz Lasek .count = FTL_NVC_VERSION_CURRENT, 422bb1753bSLukasz Lasek }, 432bb1753bSLukasz Lasek [FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR] = { 442bb1753bSLukasz Lasek .latest_ver = FTL_NVC_VERSION_CURRENT, 452bb1753bSLukasz Lasek .count = FTL_NVC_VERSION_CURRENT, 462bb1753bSLukasz Lasek }, 472bb1753bSLukasz Lasek [FTL_LAYOUT_REGION_TYPE_DATA_NVC] = {}, 482bb1753bSLukasz Lasek [FTL_LAYOUT_REGION_TYPE_DATA_BASE] = {}, 492bb1753bSLukasz Lasek [FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC] = { 502bb1753bSLukasz Lasek .latest_ver = FTL_P2L_VERSION_CURRENT, 512bb1753bSLukasz Lasek .count = FTL_P2L_VERSION_CURRENT, 522bb1753bSLukasz Lasek }, 532bb1753bSLukasz Lasek [FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC_NEXT] = { 542bb1753bSLukasz Lasek .latest_ver = FTL_P2L_VERSION_CURRENT, 552bb1753bSLukasz Lasek .count = FTL_P2L_VERSION_CURRENT, 562bb1753bSLukasz Lasek }, 572bb1753bSLukasz Lasek [FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP] = { 582bb1753bSLukasz Lasek .latest_ver = FTL_P2L_VERSION_CURRENT, 592bb1753bSLukasz Lasek .count = FTL_P2L_VERSION_CURRENT, 602bb1753bSLukasz Lasek }, 612bb1753bSLukasz Lasek [FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP_NEXT] = { 622bb1753bSLukasz Lasek .latest_ver = FTL_P2L_VERSION_CURRENT, 632bb1753bSLukasz Lasek .count = FTL_P2L_VERSION_CURRENT, 642bb1753bSLukasz Lasek }, 652bb1753bSLukasz Lasek [FTL_LAYOUT_REGION_TYPE_TRIM_MD] = {}, 662bb1753bSLukasz Lasek [FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR] = {}, 672d613454SMateusz Kozlowski [FTL_LAYOUT_REGION_TYPE_TRIM_LOG] = {}, 682d613454SMateusz Kozlowski [FTL_LAYOUT_REGION_TYPE_TRIM_LOG_MIRROR] = {}, 69*6d6179ffSMateusz Kozlowski [FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MIN] = {}, 70*6d6179ffSMateusz Kozlowski [FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MAX] = {}, 712bb1753bSLukasz Lasek }; 722bb1753bSLukasz Lasek 73c8ab874dSKozlowski Mateusz #include "ftl/upgrade/ftl_layout_upgrade.c" 74c8ab874dSKozlowski Mateusz #include "ftl/mngt/ftl_mngt_md.c" 75c8ab874dSKozlowski Mateusz 76c8ab874dSKozlowski Mateusz DEFINE_STUB_V(ftl_mngt_fail_step, (struct ftl_mngt_process *mngt)); 77c8ab874dSKozlowski Mateusz DEFINE_STUB_V(ftl_mngt_next_step, (struct ftl_mngt_process *mngt)); 78c8ab874dSKozlowski Mateusz DEFINE_STUB_V(ftl_md_persist, (struct ftl_md *md)); 79c8ab874dSKozlowski Mateusz DEFINE_STUB(ftl_nv_cache_load_state, int, (struct ftl_nv_cache *nv_cache), 0); 80c8ab874dSKozlowski Mateusz DEFINE_STUB_V(ftl_valid_map_load_state, (struct spdk_ftl_dev *dev)); 81cb00e90aSMateusz Kozlowski DEFINE_STUB(ftl_bands_load_state, int, (struct spdk_ftl_dev *dev), 0); 82c8ab874dSKozlowski Mateusz DEFINE_STUB(ftl_md_get_region, const struct ftl_layout_region *, (struct ftl_md *md), 0); 83c8ab874dSKozlowski Mateusz DEFINE_STUB_V(ftl_md_restore, (struct ftl_md *md)); 84c8ab874dSKozlowski Mateusz DEFINE_STUB(ftl_nv_cache_save_state, int, (struct ftl_nv_cache *nv_cache), 0); 85c8ab874dSKozlowski Mateusz DEFINE_STUB(ftl_mngt_get_step_ctx, void *, (struct ftl_mngt_process *mngt), 0); 86c8ab874dSKozlowski Mateusz DEFINE_STUB_V(ftl_mngt_persist_bands_p2l, (struct ftl_mngt_process *mngt)); 87c8ab874dSKozlowski Mateusz DEFINE_STUB_V(ftl_band_init_gc_iter, (struct spdk_ftl_dev *dev)); 88c8ab874dSKozlowski Mateusz DEFINE_STUB(ftl_md_create_region_flags, int, (struct spdk_ftl_dev *dev, int region_type), 0); 89c8ab874dSKozlowski Mateusz DEFINE_STUB(ftl_md_create, struct ftl_md *, (struct spdk_ftl_dev *dev, uint64_t blocks, 90c8ab874dSKozlowski Mateusz uint64_t vss_blksz, const char *name, int flags, const struct ftl_layout_region *region), NULL); 91c8ab874dSKozlowski Mateusz DEFINE_STUB(ftl_md_destroy_region_flags, int, (struct spdk_ftl_dev *dev, int region_type), 0); 92c8ab874dSKozlowski Mateusz DEFINE_STUB(ftl_md_destroy_shm_flags, int, (struct spdk_ftl_dev *dev), 0); 93c8ab874dSKozlowski Mateusz DEFINE_STUB_V(ftl_md_destroy, (struct ftl_md *md, int flags)); 94c8ab874dSKozlowski Mateusz DEFINE_STUB_V(ftl_mngt_call_process, (struct ftl_mngt_process *mngt, 959452abe6SMateusz Kozlowski const struct ftl_mngt_process_desc *process, 969452abe6SMateusz Kozlowski void *init_ctx)); 97c8ab874dSKozlowski Mateusz DEFINE_STUB(ftl_md_get_buffer, void *, (struct ftl_md *md), NULL); 982bb1753bSLukasz Lasek DEFINE_STUB(spdk_bdev_desc_get_bdev, struct spdk_bdev *, (struct spdk_bdev_desc *desc), NULL); 992bb1753bSLukasz Lasek DEFINE_STUB(spdk_bdev_get_write_unit_size, uint32_t, (const struct spdk_bdev *bdev), 0); 1002bb1753bSLukasz Lasek DEFINE_STUB(spdk_bdev_get_num_blocks, uint64_t, (const struct spdk_bdev *bdev), 0); 1012bb1753bSLukasz Lasek DEFINE_STUB(ftl_nv_cache_chunk_tail_md_num_blocks, size_t, (const struct ftl_nv_cache *nv_cache), 1022bb1753bSLukasz Lasek 0); 1032bb1753bSLukasz Lasek DEFINE_STUB(ftl_band_user_blocks, size_t, (const struct ftl_band *band), 0); 1042bb1753bSLukasz Lasek 1052bb1753bSLukasz Lasek struct spdk_bdev_desc { 1062bb1753bSLukasz Lasek int dummy; 1072bb1753bSLukasz Lasek }; 108c8ab874dSKozlowski Mateusz 109c8ab874dSKozlowski Mateusz struct spdk_ftl_dev g_dev; 110c8ab874dSKozlowski Mateusz struct ftl_superblock_shm g_sb_shm = {0}; 1112bb1753bSLukasz Lasek struct ftl_base_device_type g_base_type = { .name = "base_dev" }; 11226f3b551SMateusz Kozlowski struct ftl_nv_cache_device_type g_nvc_type = { .name = "nvc_dev" }; 1132bb1753bSLukasz Lasek struct spdk_bdev_desc g_base_bdev_desc = {0}; 1142bb1753bSLukasz Lasek struct spdk_bdev_desc g_nvc_bdev_desc = {0}; 115c8ab874dSKozlowski Mateusz static uint8_t g_sb_buf[FTL_SUPERBLOCK_SIZE] = {0}; 116c8ab874dSKozlowski Mateusz 117c8ab874dSKozlowski Mateusz struct ftl_region_upgrade_desc p2l_upgrade_desc[0]; 118c8ab874dSKozlowski Mateusz struct ftl_region_upgrade_desc nvc_upgrade_desc[0]; 119c8ab874dSKozlowski Mateusz struct ftl_region_upgrade_desc band_upgrade_desc[0]; 120c8ab874dSKozlowski Mateusz 121c8ab874dSKozlowski Mateusz #define TEST_OP 0x1984 122c8ab874dSKozlowski Mateusz #define TEST_REG_BLKS 0x10000 123c8ab874dSKozlowski Mateusz #define TEST_NVC_BLKS 0x1000000; 124c8ab874dSKozlowski Mateusz #define TEST_BASE_BLKS 0x1000000000; 125c8ab874dSKozlowski Mateusz 126c8ab874dSKozlowski Mateusz static int 127c8ab874dSKozlowski Mateusz test_setup(void) 128c8ab874dSKozlowski Mateusz { 1292bb1753bSLukasz Lasek int regno_nvc = 0, regno_base = 0, *regno_dev; 1302bb1753bSLukasz Lasek 131c8ab874dSKozlowski Mateusz /* setup a dummy dev: */ 132c8ab874dSKozlowski Mateusz g_dev.sb = (void *)g_sb_buf; 133c8ab874dSKozlowski Mateusz g_dev.sb_shm = &g_sb_shm; 134c8ab874dSKozlowski Mateusz g_dev.conf.overprovisioning = TEST_OP; 135c8ab874dSKozlowski Mateusz for (uint64_t n = 0; n < sizeof(g_dev.conf.uuid); n++) { 136c8ab874dSKozlowski Mateusz g_dev.conf.uuid.u.raw[n] = n; 137c8ab874dSKozlowski Mateusz } 138c8ab874dSKozlowski Mateusz 139c8ab874dSKozlowski Mateusz g_dev.layout.nvc.total_blocks = TEST_NVC_BLKS; 140c8ab874dSKozlowski Mateusz g_dev.layout.base.total_blocks = TEST_BASE_BLKS; 1412bb1753bSLukasz Lasek g_dev.base_type = &g_base_type; 14226f3b551SMateusz Kozlowski g_dev.nv_cache.nvc_type = &g_nvc_type; 1432bb1753bSLukasz Lasek g_dev.base_layout_tracker = ftl_layout_tracker_bdev_init(UINT32_MAX); 1442bb1753bSLukasz Lasek g_dev.nvc_layout_tracker = ftl_layout_tracker_bdev_init(UINT32_MAX); 1452bb1753bSLukasz Lasek g_dev.base_bdev_desc = &g_base_bdev_desc; 1462bb1753bSLukasz Lasek g_dev.nv_cache.bdev_desc = &g_nvc_bdev_desc; 147c8ab874dSKozlowski Mateusz 148c8ab874dSKozlowski Mateusz for (int regno = 0; regno < FTL_LAYOUT_REGION_TYPE_MAX; regno++) { 149c8ab874dSKozlowski Mateusz struct ftl_layout_region *reg = &g_dev.layout.region[regno]; 1502bb1753bSLukasz Lasek 151c8ab874dSKozlowski Mateusz reg->current.blocks = TEST_REG_BLKS; 1522bb1753bSLukasz Lasek regno_dev = sb_v3_md_region_is_nvc(regno) ? ®no_nvc : ®no_base; 1532bb1753bSLukasz Lasek reg->current.offset = *regno_dev * TEST_REG_BLKS; 1542bb1753bSLukasz Lasek (*regno_dev)++; 1552bb1753bSLukasz Lasek reg->current.version = ftl_layout_upgrade_region_get_latest_version(regno); 156c8ab874dSKozlowski Mateusz reg->type = regno; 157c8ab874dSKozlowski Mateusz reg->name = "region_test"; 1582bb1753bSLukasz Lasek reg->bdev_desc = sb_v3_md_region_is_nvc(regno) ? &g_nvc_bdev_desc : &g_base_bdev_desc; 159c8ab874dSKozlowski Mateusz reg->ioch = 0; 160c8ab874dSKozlowski Mateusz } 161c8ab874dSKozlowski Mateusz return 0; 162c8ab874dSKozlowski Mateusz } 163c8ab874dSKozlowski Mateusz 1642bb1753bSLukasz Lasek static int 1652bb1753bSLukasz Lasek test_teardown(void) 1662bb1753bSLukasz Lasek { 1672bb1753bSLukasz Lasek if (g_dev.base_layout_tracker) { 1682bb1753bSLukasz Lasek ftl_layout_tracker_bdev_fini(g_dev.base_layout_tracker); 1692bb1753bSLukasz Lasek g_dev.base_layout_tracker = NULL; 1702bb1753bSLukasz Lasek } 1712bb1753bSLukasz Lasek if (g_dev.nvc_layout_tracker) { 1722bb1753bSLukasz Lasek ftl_layout_tracker_bdev_fini(g_dev.nvc_layout_tracker); 1732bb1753bSLukasz Lasek g_dev.nvc_layout_tracker = NULL; 1742bb1753bSLukasz Lasek } 1752bb1753bSLukasz Lasek return 0; 1762bb1753bSLukasz Lasek } 1772bb1753bSLukasz Lasek 178c8ab874dSKozlowski Mateusz static void 179c8ab874dSKozlowski Mateusz test_setup_sb_ver(uint64_t ver, uint64_t clean) 180c8ab874dSKozlowski Mateusz { 181c8ab874dSKozlowski Mateusz union ftl_superblock_ver *sb = (void *)g_sb_buf; 1822bb1753bSLukasz Lasek uint64_t zero_offs; 183c8ab874dSKozlowski Mateusz 184c8ab874dSKozlowski Mateusz memset(&g_sb_buf, 0, sizeof(g_sb_buf)); 185c8ab874dSKozlowski Mateusz ftl_mngt_init_default_sb(&g_dev, NULL); 186c8ab874dSKozlowski Mateusz if (ver <= FTL_SB_VERSION_3) { 187c8ab874dSKozlowski Mateusz sb->header.magic = FTL_SUPERBLOCK_MAGIC_V2; 188c8ab874dSKozlowski Mateusz } 189c8ab874dSKozlowski Mateusz sb->header.version = ver; 1902bb1753bSLukasz Lasek 1912bb1753bSLukasz Lasek switch (ver) { 1922bb1753bSLukasz Lasek case FTL_SB_VERSION_0: 1932bb1753bSLukasz Lasek case FTL_SB_VERSION_1: 1942bb1753bSLukasz Lasek case FTL_SB_VERSION_2: 1952bb1753bSLukasz Lasek zero_offs = sizeof(struct ftl_superblock_v2); 1962bb1753bSLukasz Lasek memset(g_sb_buf + zero_offs, 0, sizeof(g_sb_buf) - zero_offs); 197c8ab874dSKozlowski Mateusz sb->v2.clean = clean; 1982bb1753bSLukasz Lasek break; 1992bb1753bSLukasz Lasek 2002bb1753bSLukasz Lasek case FTL_SB_VERSION_3: 2012bb1753bSLukasz Lasek case FTL_SB_VERSION_4: 2022bb1753bSLukasz Lasek zero_offs = sizeof(struct ftl_superblock_v3); 2032bb1753bSLukasz Lasek memset(g_sb_buf + zero_offs, 0, sizeof(g_sb_buf) - zero_offs); 2042bb1753bSLukasz Lasek sb->v3.clean = clean; 2052bb1753bSLukasz Lasek sb->v3.md_layout_head.type = FTL_LAYOUT_REGION_TYPE_INVALID; 2062bb1753bSLukasz Lasek break; 2072bb1753bSLukasz Lasek 2082bb1753bSLukasz Lasek case FTL_SB_VERSION_5: 2092bb1753bSLukasz Lasek zero_offs = sizeof(struct ftl_superblock_v5); 2102bb1753bSLukasz Lasek memset(g_sb_buf + zero_offs, 0, sizeof(g_sb_buf) - zero_offs); 2112bb1753bSLukasz Lasek sb->v5.clean = clean; 2122bb1753bSLukasz Lasek break; 2132bb1753bSLukasz Lasek } 2142bb1753bSLukasz Lasek 215fa1fc76cSLukasz Lasek sb->header.crc = get_sb_crc(&sb->current); 216c8ab874dSKozlowski Mateusz } 217c8ab874dSKozlowski Mateusz 218c8ab874dSKozlowski Mateusz static void 219c8ab874dSKozlowski Mateusz test_setup_sb_v2(uint64_t clean) 220c8ab874dSKozlowski Mateusz { 221c8ab874dSKozlowski Mateusz test_setup_sb_ver(FTL_SB_VERSION_2, clean); 222c8ab874dSKozlowski Mateusz } 223c8ab874dSKozlowski Mateusz 224c8ab874dSKozlowski Mateusz static void 225c8ab874dSKozlowski Mateusz test_setup_sb_v3(uint64_t clean) 226c8ab874dSKozlowski Mateusz { 2272bb1753bSLukasz Lasek test_setup_sb_ver(FTL_SB_VERSION_3, clean); 2282bb1753bSLukasz Lasek } 229c8ab874dSKozlowski Mateusz 2302bb1753bSLukasz Lasek static void 2312bb1753bSLukasz Lasek test_setup_sb_v5(uint64_t clean) 2322bb1753bSLukasz Lasek { 2332bb1753bSLukasz Lasek test_setup_sb_ver(FTL_SB_VERSION_5, clean); 234c8ab874dSKozlowski Mateusz } 235c8ab874dSKozlowski Mateusz 236c8ab874dSKozlowski Mateusz static void 237c8ab874dSKozlowski Mateusz test_sb_crc_v2(void) 238c8ab874dSKozlowski Mateusz { 239c8ab874dSKozlowski Mateusz union ftl_superblock_ver *sb = (void *)g_sb_buf; 240c8ab874dSKozlowski Mateusz uint64_t crc; 241c8ab874dSKozlowski Mateusz 242c8ab874dSKozlowski Mateusz /* v2-specific crc: it's not really working */ 243c8ab874dSKozlowski Mateusz test_setup_sb_v2(true); 244c8ab874dSKozlowski Mateusz crc = sb->header.crc; 245c8ab874dSKozlowski Mateusz 246c8ab874dSKozlowski Mateusz sb->header.crc++; 247fa1fc76cSLukasz Lasek sb->header.crc = get_sb_crc(&sb->current); 248c8ab874dSKozlowski Mateusz CU_ASSERT_EQUAL(crc, sb->header.crc); 249c8ab874dSKozlowski Mateusz 250c8ab874dSKozlowski Mateusz g_sb_buf[sizeof(struct ftl_superblock_v2)]++; 251fa1fc76cSLukasz Lasek sb->header.crc = get_sb_crc(&sb->current); 252c8ab874dSKozlowski Mateusz CU_ASSERT_EQUAL(crc, sb->header.crc); 253c8ab874dSKozlowski Mateusz 254c8ab874dSKozlowski Mateusz g_sb_buf[sizeof(g_sb_buf) - 1]++; 255fa1fc76cSLukasz Lasek sb->header.crc = get_sb_crc(&sb->current); 256c8ab874dSKozlowski Mateusz CU_ASSERT_EQUAL(crc, sb->header.crc); 257c8ab874dSKozlowski Mateusz } 258c8ab874dSKozlowski Mateusz 259c8ab874dSKozlowski Mateusz static void 260c8ab874dSKozlowski Mateusz test_sb_crc_v3(void) 261c8ab874dSKozlowski Mateusz { 262c8ab874dSKozlowski Mateusz union ftl_superblock_ver *sb = (void *)g_sb_buf; 263c8ab874dSKozlowski Mateusz uint64_t crc; 264c8ab874dSKozlowski Mateusz 265c8ab874dSKozlowski Mateusz /* v3 crc: covers the entire buf */ 266c8ab874dSKozlowski Mateusz test_setup_sb_v3(true); 267c8ab874dSKozlowski Mateusz crc = sb->header.crc; 268c8ab874dSKozlowski Mateusz 269c8ab874dSKozlowski Mateusz sb->header.crc++; 270fa1fc76cSLukasz Lasek sb->header.crc = get_sb_crc(&sb->current); 271c8ab874dSKozlowski Mateusz CU_ASSERT_EQUAL(crc, sb->header.crc); 272c8ab874dSKozlowski Mateusz crc = sb->header.crc; 273c8ab874dSKozlowski Mateusz 274c8ab874dSKozlowski Mateusz g_sb_buf[sizeof(struct ftl_superblock_v2)]++; 275fa1fc76cSLukasz Lasek sb->header.crc = get_sb_crc(&sb->current); 276c8ab874dSKozlowski Mateusz CU_ASSERT_NOT_EQUAL(crc, sb->header.crc); 277c8ab874dSKozlowski Mateusz crc = sb->header.crc; 278c8ab874dSKozlowski Mateusz 279c8ab874dSKozlowski Mateusz g_sb_buf[sizeof(g_sb_buf) - 1]++; 280fa1fc76cSLukasz Lasek sb->header.crc = get_sb_crc(&sb->current); 281c8ab874dSKozlowski Mateusz CU_ASSERT_NOT_EQUAL(crc, sb->header.crc); 282c8ab874dSKozlowski Mateusz crc = sb->header.crc; 283c8ab874dSKozlowski Mateusz 284c8ab874dSKozlowski Mateusz CU_ASSERT_EQUAL(crc, sb->header.crc); 2852bb1753bSLukasz Lasek } 2862bb1753bSLukasz Lasek 2872bb1753bSLukasz Lasek static int 2882bb1753bSLukasz Lasek test_superblock_v3_md_layout_add(struct spdk_ftl_dev *dev, 2892bb1753bSLukasz Lasek struct ftl_superblock_v3_md_region *sb_reg, 2902bb1753bSLukasz Lasek uint32_t reg_type, uint32_t reg_version, uint64_t blk_offs, uint64_t blk_sz) 2912bb1753bSLukasz Lasek { 2922bb1753bSLukasz Lasek if (ftl_superblock_v3_md_region_overflow(dev, sb_reg)) { 2932bb1753bSLukasz Lasek return -EOVERFLOW; 2942bb1753bSLukasz Lasek } 2952bb1753bSLukasz Lasek 2962bb1753bSLukasz Lasek sb_reg->type = reg_type; 2972bb1753bSLukasz Lasek sb_reg->version = reg_version; 2982bb1753bSLukasz Lasek sb_reg->blk_offs = blk_offs; 2992bb1753bSLukasz Lasek sb_reg->blk_sz = blk_sz; 3002bb1753bSLukasz Lasek return 0; 3012bb1753bSLukasz Lasek } 3022bb1753bSLukasz Lasek 3032bb1753bSLukasz Lasek static int 3042bb1753bSLukasz Lasek test_superblock_v3_md_layout_add_free(struct spdk_ftl_dev *dev, 3052bb1753bSLukasz Lasek struct ftl_superblock_v3_md_region **sb_reg, 3062bb1753bSLukasz Lasek uint32_t reg_type, uint32_t free_type, uint64_t total_blocks) 3072bb1753bSLukasz Lasek { 3082bb1753bSLukasz Lasek struct ftl_layout *layout = &dev->layout; 3092bb1753bSLukasz Lasek struct ftl_layout_region *reg = &layout->region[reg_type]; 3102bb1753bSLukasz Lasek uint64_t blks_left = total_blocks - reg->current.offset - reg->current.blocks; 3112bb1753bSLukasz Lasek 3122bb1753bSLukasz Lasek if (blks_left == 0) { 3132bb1753bSLukasz Lasek return 0; 3142bb1753bSLukasz Lasek } 3152bb1753bSLukasz Lasek 3162bb1753bSLukasz Lasek (*sb_reg)->df_next = ftl_df_get_obj_id(dev->sb, (*sb_reg) + 1); 3172bb1753bSLukasz Lasek (*sb_reg) = (*sb_reg) + 1; 3182bb1753bSLukasz Lasek 3192bb1753bSLukasz Lasek if (test_superblock_v3_md_layout_add(dev, *sb_reg, free_type, 0, 3202bb1753bSLukasz Lasek reg->current.offset + reg->current.blocks, blks_left)) { 3212bb1753bSLukasz Lasek return -1; 3222bb1753bSLukasz Lasek } 3232bb1753bSLukasz Lasek 3242bb1753bSLukasz Lasek (*sb_reg)->df_next = FTL_DF_OBJ_ID_INVALID; 3252bb1753bSLukasz Lasek 3262bb1753bSLukasz Lasek return 0; 3272bb1753bSLukasz Lasek } 3282bb1753bSLukasz Lasek 3292bb1753bSLukasz Lasek static int 3302bb1753bSLukasz Lasek test_ftl_superblock_v3_md_layout_build(struct spdk_ftl_dev *dev) 3312bb1753bSLukasz Lasek { 3322bb1753bSLukasz Lasek union ftl_superblock_ver *sb_ver = (union ftl_superblock_ver *)dev->sb; 3332bb1753bSLukasz Lasek struct ftl_layout *layout = &dev->layout; 3342bb1753bSLukasz Lasek struct ftl_layout_region *reg; 3352bb1753bSLukasz Lasek int n = 0; 3362bb1753bSLukasz Lasek bool is_empty = ftl_superblock_v3_md_layout_is_empty(sb_ver); 3372bb1753bSLukasz Lasek struct ftl_superblock_v3_md_region *sb_reg = &sb_ver->v3.md_layout_head; 3382bb1753bSLukasz Lasek 3392bb1753bSLukasz Lasek /* TODO: major upgrades: add all free regions being tracked 3402bb1753bSLukasz Lasek * For now SB MD layout must be empty - otherwise md free regions may be lost */ 3412bb1753bSLukasz Lasek assert(is_empty); 3422bb1753bSLukasz Lasek 3432bb1753bSLukasz Lasek for (; n < FTL_LAYOUT_REGION_TYPE_MAX_V3;) { 3442bb1753bSLukasz Lasek reg = ftl_layout_region_get(dev, n); 3452bb1753bSLukasz Lasek assert(reg); 3462bb1753bSLukasz Lasek if (md_region_is_fixed(reg->type)) { 3472bb1753bSLukasz Lasek n++; 3482bb1753bSLukasz Lasek 3492bb1753bSLukasz Lasek if (n >= FTL_LAYOUT_REGION_TYPE_MAX_V3) { 3502bb1753bSLukasz Lasek /* 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 */ 3512bb1753bSLukasz Lasek sb_reg--; 3522bb1753bSLukasz Lasek break; 3532bb1753bSLukasz Lasek } 3542bb1753bSLukasz Lasek continue; 3552bb1753bSLukasz Lasek } 3562bb1753bSLukasz Lasek 3572bb1753bSLukasz Lasek if (test_superblock_v3_md_layout_add(dev, sb_reg, reg->type, reg->current.version, 3582bb1753bSLukasz Lasek reg->current.offset, reg->current.blocks)) { 3592bb1753bSLukasz Lasek return -1; 3602bb1753bSLukasz Lasek } 3612bb1753bSLukasz Lasek 3622bb1753bSLukasz Lasek n++; 3632bb1753bSLukasz Lasek if (n < FTL_LAYOUT_REGION_TYPE_MAX_V3) { 3642bb1753bSLukasz Lasek /* next region */ 3652bb1753bSLukasz Lasek sb_reg->df_next = ftl_df_get_obj_id(sb_ver, sb_reg + 1); 3662bb1753bSLukasz Lasek sb_reg++; 3672bb1753bSLukasz Lasek } 3682bb1753bSLukasz Lasek } 3692bb1753bSLukasz Lasek 3702bb1753bSLukasz Lasek /* terminate the list */ 3712bb1753bSLukasz Lasek sb_reg->df_next = FTL_DF_OBJ_ID_INVALID; 3722bb1753bSLukasz Lasek 3732bb1753bSLukasz Lasek /* create free_nvc/free_base regions on the first run */ 3742bb1753bSLukasz Lasek if (is_empty) { 3752bb1753bSLukasz Lasek test_superblock_v3_md_layout_add_free(dev, &sb_reg, FTL_LAYOUT_REGION_LAST_NVC, 3762bb1753bSLukasz Lasek FTL_LAYOUT_REGION_TYPE_FREE_NVC, layout->nvc.total_blocks); 3772bb1753bSLukasz Lasek 3782bb1753bSLukasz Lasek test_superblock_v3_md_layout_add_free(dev, &sb_reg, FTL_LAYOUT_REGION_LAST_BASE, 3792bb1753bSLukasz Lasek FTL_LAYOUT_REGION_TYPE_FREE_BASE, layout->base.total_blocks); 3802bb1753bSLukasz Lasek } 3812bb1753bSLukasz Lasek 3822bb1753bSLukasz Lasek return 0; 3832bb1753bSLukasz Lasek } 3842bb1753bSLukasz Lasek 3852bb1753bSLukasz Lasek static void 3862bb1753bSLukasz Lasek test_sb_v3_region_reinit(void) 3872bb1753bSLukasz Lasek { 3882bb1753bSLukasz Lasek uint32_t reg_type; 3892bb1753bSLukasz Lasek 3902bb1753bSLukasz Lasek for (reg_type = 0; reg_type < FTL_LAYOUT_REGION_TYPE_MAX; reg_type++) { 3912bb1753bSLukasz Lasek g_dev.layout.region[reg_type].type = reg_type; 3922bb1753bSLukasz Lasek } 3932bb1753bSLukasz Lasek } 3942bb1753bSLukasz Lasek 3952bb1753bSLukasz Lasek static struct ftl_superblock_v3_md_region * 3962bb1753bSLukasz Lasek test_sb_v3_find_region_ver(enum ftl_layout_region_type reg_type, uint32_t reg_ver) 3972bb1753bSLukasz Lasek { 3982bb1753bSLukasz Lasek union ftl_superblock_ver *sb = (void *)g_sb_buf; 3992bb1753bSLukasz Lasek struct ftl_superblock_v3_md_region *sb_reg = &sb->v3.md_layout_head; 4002bb1753bSLukasz Lasek 4012bb1753bSLukasz Lasek while (sb_reg->type != FTL_LAYOUT_REGION_TYPE_INVALID) { 4022bb1753bSLukasz Lasek if (sb_reg->type == reg_type && sb_reg->version == reg_ver) { 4032bb1753bSLukasz Lasek return sb_reg; 4042bb1753bSLukasz Lasek } 4052bb1753bSLukasz Lasek 4062bb1753bSLukasz Lasek if (sb_reg->df_next == FTL_DF_OBJ_ID_INVALID) { 4072bb1753bSLukasz Lasek break; 4082bb1753bSLukasz Lasek } 4092bb1753bSLukasz Lasek 4102bb1753bSLukasz Lasek if (UINT64_MAX - (uintptr_t)sb <= sb_reg->df_next) { 4112bb1753bSLukasz Lasek return NULL; 4122bb1753bSLukasz Lasek } 4132bb1753bSLukasz Lasek 4142bb1753bSLukasz Lasek sb_reg = ftl_df_get_obj_ptr(sb, sb_reg->df_next); 4152bb1753bSLukasz Lasek if (ftl_superblock_v3_md_region_overflow(&g_dev, sb_reg)) { 4162bb1753bSLukasz Lasek return NULL; 4172bb1753bSLukasz Lasek } 4182bb1753bSLukasz Lasek } 4192bb1753bSLukasz Lasek 4202bb1753bSLukasz Lasek return NULL; 4212bb1753bSLukasz Lasek } 4222bb1753bSLukasz Lasek 4232bb1753bSLukasz Lasek static struct ftl_superblock_v3_md_region * 4242bb1753bSLukasz Lasek test_sb_v3_find_region_latest(enum ftl_layout_region_type reg_type) 4252bb1753bSLukasz Lasek { 4262bb1753bSLukasz Lasek return test_sb_v3_find_region_ver(reg_type, ftl_layout_upgrade_region_get_latest_version(reg_type)); 427c8ab874dSKozlowski Mateusz } 428c8ab874dSKozlowski Mateusz 429c8ab874dSKozlowski Mateusz static void 430c8ab874dSKozlowski Mateusz test_sb_v3_md_layout(void) 431c8ab874dSKozlowski Mateusz { 4322bb1753bSLukasz Lasek struct ftl_superblock_v3_md_region *sb_reg, *sb_reg_next, *sb_reg_next2; 4332bb1753bSLukasz Lasek struct ftl_layout_region *reg_head, *reg; 434c8ab874dSKozlowski Mateusz union ftl_superblock_ver *sb = (void *)g_sb_buf; 4352bb1753bSLukasz Lasek ftl_df_obj_id df_next_head, df_next_reg; 4362bb1753bSLukasz Lasek uint32_t md_type_head; 437c8ab874dSKozlowski Mateusz int rc; 438c8ab874dSKozlowski Mateusz 439c8ab874dSKozlowski Mateusz test_setup_sb_v3(false); 4402bb1753bSLukasz Lasek CU_ASSERT_EQUAL(ftl_superblock_is_blob_area_empty(&sb->current), true); 441c8ab874dSKozlowski Mateusz 442c8ab874dSKozlowski Mateusz /* load failed: empty md list: */ 443fa1fc76cSLukasz Lasek rc = ftl_superblock_v3_md_layout_load_all(&g_dev); 444c8ab874dSKozlowski Mateusz CU_ASSERT_NOT_EQUAL(rc, 0); 4452bb1753bSLukasz Lasek test_sb_v3_region_reinit(); 446c8ab874dSKozlowski Mateusz 447c8ab874dSKozlowski Mateusz /* create md layout: */ 4482bb1753bSLukasz Lasek test_ftl_superblock_v3_md_layout_build(&g_dev); 4492bb1753bSLukasz Lasek CU_ASSERT_EQUAL(ftl_superblock_is_blob_area_empty(&sb->current), false); 450c8ab874dSKozlowski Mateusz 451c8ab874dSKozlowski Mateusz /* buf overflow, sb_reg = 1 byte overflow: */ 4522bb1753bSLukasz Lasek df_next_head = sb->v3.md_layout_head.df_next; 453c8ab874dSKozlowski Mateusz sb->v3.md_layout_head.df_next = FTL_SUPERBLOCK_SIZE - sizeof(sb->v3.md_layout_head) + 1; 454fa1fc76cSLukasz Lasek rc = ftl_superblock_v3_md_layout_load_all(&g_dev); 455c8ab874dSKozlowski Mateusz CU_ASSERT_EQUAL(rc, -EOVERFLOW); 4562bb1753bSLukasz Lasek test_sb_v3_region_reinit(); 457c8ab874dSKozlowski Mateusz 458c8ab874dSKozlowski Mateusz /* buf underflow, sb_reg = -1: */ 459c8ab874dSKozlowski Mateusz sb->v3.md_layout_head.df_next = UINTPTR_MAX - (uintptr_t)sb; 460fa1fc76cSLukasz Lasek rc = ftl_superblock_v3_md_layout_load_all(&g_dev); 461c8ab874dSKozlowski Mateusz CU_ASSERT_EQUAL(rc, -EOVERFLOW); 4622bb1753bSLukasz Lasek test_sb_v3_region_reinit(); 463c8ab874dSKozlowski Mateusz 464c8ab874dSKozlowski Mateusz /* buf underflow, sb_reg = 2 bytes underflow */ 465c8ab874dSKozlowski Mateusz sb->v3.md_layout_head.df_next = UINTPTR_MAX - 1; 466fa1fc76cSLukasz Lasek rc = ftl_superblock_v3_md_layout_load_all(&g_dev); 467c8ab874dSKozlowski Mateusz CU_ASSERT_EQUAL(rc, -EOVERFLOW); 4682bb1753bSLukasz Lasek test_sb_v3_region_reinit(); 469c8ab874dSKozlowski Mateusz 470c8ab874dSKozlowski Mateusz /* looping md layout list: */ 471c8ab874dSKozlowski Mateusz sb->v3.md_layout_head.df_next = ftl_df_get_obj_id(sb, &sb->v3.md_layout_head); 472fa1fc76cSLukasz Lasek rc = ftl_superblock_v3_md_layout_load_all(&g_dev); 473c8ab874dSKozlowski Mateusz CU_ASSERT_NOT_EQUAL(rc, 0); 4742bb1753bSLukasz Lasek test_sb_v3_region_reinit(); 475c8ab874dSKozlowski Mateusz 4762bb1753bSLukasz Lasek sb->v3.md_layout_head.df_next = df_next_head; 477c8ab874dSKozlowski Mateusz 478c8ab874dSKozlowski Mateusz /* unsupported/fixed md region: */ 4792bb1753bSLukasz Lasek md_type_head = sb->v3.md_layout_head.type; 480c8ab874dSKozlowski Mateusz sb->v3.md_layout_head.type = FTL_LAYOUT_REGION_TYPE_SB; 481fa1fc76cSLukasz Lasek rc = ftl_superblock_v3_md_layout_load_all(&g_dev); 482c8ab874dSKozlowski Mateusz CU_ASSERT_NOT_EQUAL(rc, 0); 4832bb1753bSLukasz Lasek test_sb_v3_region_reinit(); 484c8ab874dSKozlowski Mateusz 485c8ab874dSKozlowski Mateusz /* unsupported/invalid md region: */ 486c8ab874dSKozlowski Mateusz sb->v3.md_layout_head.type = FTL_LAYOUT_REGION_TYPE_MAX; 487fa1fc76cSLukasz Lasek rc = ftl_superblock_v3_md_layout_load_all(&g_dev); 488c8ab874dSKozlowski Mateusz CU_ASSERT_NOT_EQUAL(rc, 0); 4892bb1753bSLukasz Lasek test_sb_v3_region_reinit(); 4902bb1753bSLukasz Lasek 4912bb1753bSLukasz Lasek /* unsupported/invalid md region: */ 4922bb1753bSLukasz Lasek sb->v3.md_layout_head.type = FTL_LAYOUT_REGION_TYPE_MAX_V3; 4932bb1753bSLukasz Lasek rc = ftl_superblock_v3_md_layout_load_all(&g_dev); 4942bb1753bSLukasz Lasek CU_ASSERT_NOT_EQUAL(rc, 0); 4952bb1753bSLukasz Lasek test_sb_v3_region_reinit(); 496c8ab874dSKozlowski Mateusz 497c8ab874dSKozlowski Mateusz /* restore the sb: */ 4982bb1753bSLukasz Lasek sb->v3.md_layout_head.type = md_type_head; 499c8ab874dSKozlowski Mateusz 500c8ab874dSKozlowski Mateusz /* load succeeded, no prev version found: */ 5012bb1753bSLukasz Lasek reg_head = &g_dev.layout.region[md_type_head]; 502fa1fc76cSLukasz Lasek rc = ftl_superblock_v3_md_layout_load_all(&g_dev); 503c8ab874dSKozlowski Mateusz CU_ASSERT_EQUAL(rc, 0); 5042bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg_head->current.version, 5052bb1753bSLukasz Lasek ftl_layout_upgrade_region_get_latest_version(md_type_head)); 5062bb1753bSLukasz Lasek test_sb_v3_region_reinit(); 507c8ab874dSKozlowski Mateusz 508c8ab874dSKozlowski Mateusz /* load succeeded, prev (upgrade, i.e. no current) version discovery: */ 5092bb1753bSLukasz Lasek reg = &g_dev.layout.region[FTL_LAYOUT_REGION_TYPE_BAND_MD]; 5102bb1753bSLukasz Lasek sb_reg = test_sb_v3_find_region_latest(FTL_LAYOUT_REGION_TYPE_BAND_MD); 5112bb1753bSLukasz Lasek CU_ASSERT_NOT_EQUAL(sb_reg, NULL); 5122bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg->type, sb_reg->type); 5132bb1753bSLukasz Lasek df_next_reg = sb_reg->df_next; 514c8ab874dSKozlowski Mateusz 5152bb1753bSLukasz Lasek sb_reg->version--; 516fa1fc76cSLukasz Lasek rc = ftl_superblock_v3_md_layout_load_all(&g_dev); 5172bb1753bSLukasz Lasek CU_ASSERT_EQUAL(rc, 0); 5182bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg->current.version, sb_reg->version); 5192bb1753bSLukasz Lasek sb_reg->version++; 5202bb1753bSLukasz Lasek test_sb_v3_region_reinit(); 5212bb1753bSLukasz Lasek 5222bb1753bSLukasz Lasek /* load succeeded, newer version found: */ 5232bb1753bSLukasz Lasek sb_reg->df_next = FTL_SUPERBLOCK_SIZE - sizeof(*sb_reg_next); 5242bb1753bSLukasz Lasek sb_reg_next = ftl_df_get_obj_ptr(sb, sb_reg->df_next); 5252bb1753bSLukasz Lasek rc = test_superblock_v3_md_layout_add(&g_dev, sb_reg_next, sb_reg->type, sb_reg->version + 1, 5262bb1753bSLukasz Lasek sb_reg->blk_offs, sb_reg->blk_sz); 5272bb1753bSLukasz Lasek CU_ASSERT_EQUAL(rc, 0); 5282bb1753bSLukasz Lasek sb_reg_next->df_next = df_next_reg; 5292bb1753bSLukasz Lasek rc = ftl_superblock_v3_md_layout_load_all(&g_dev); 5302bb1753bSLukasz Lasek CU_ASSERT_EQUAL(rc, 0); 5312bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg->current.version, sb_reg->version); 5322bb1753bSLukasz Lasek test_sb_v3_region_reinit(); 533c8ab874dSKozlowski Mateusz 534c8ab874dSKozlowski Mateusz /* load succeeded, prev version discovery: */ 5352bb1753bSLukasz Lasek sb_reg_next->version = sb_reg->version - 1; 536fa1fc76cSLukasz Lasek rc = ftl_superblock_v3_md_layout_load_all(&g_dev); 537c8ab874dSKozlowski Mateusz CU_ASSERT_EQUAL(rc, 0); 5382bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg->current.version, sb_reg_next->version); 5392bb1753bSLukasz Lasek test_sb_v3_region_reinit(); 540c8ab874dSKozlowski Mateusz 5412bb1753bSLukasz Lasek /* looping regions found: */ 5422bb1753bSLukasz Lasek sb_reg_next->df_next = FTL_SUPERBLOCK_SIZE - 2 * sizeof(*sb_reg_next); 5432bb1753bSLukasz Lasek sb_reg_next2 = ftl_df_get_obj_ptr(sb, sb_reg_next->df_next); 5442bb1753bSLukasz Lasek rc = test_superblock_v3_md_layout_add(&g_dev, sb_reg_next2, sb_reg_next->type, 5452bb1753bSLukasz Lasek sb_reg_next->version + 2, 5462bb1753bSLukasz Lasek sb_reg_next->blk_offs, sb_reg_next->blk_sz); 547c8ab874dSKozlowski Mateusz CU_ASSERT_EQUAL(rc, 0); 5482bb1753bSLukasz Lasek sb_reg_next2->df_next = FTL_SUPERBLOCK_SIZE - 2 * sizeof(*sb_reg_next); 549fa1fc76cSLukasz Lasek rc = ftl_superblock_v3_md_layout_load_all(&g_dev); 5502bb1753bSLukasz Lasek CU_ASSERT_EQUAL(rc, -ELOOP); 5512bb1753bSLukasz Lasek test_sb_v3_region_reinit(); 552c8ab874dSKozlowski Mateusz 5532bb1753bSLukasz Lasek /* multiple (same ver) regions found: */ 5542bb1753bSLukasz Lasek sb_reg_next2->version = sb_reg_next->version; 5552bb1753bSLukasz Lasek sb_reg_next2->df_next = df_next_reg; 556fa1fc76cSLukasz Lasek rc = ftl_superblock_v3_md_layout_load_all(&g_dev); 5572bb1753bSLukasz Lasek CU_ASSERT_EQUAL(rc, -EAGAIN); 5582bb1753bSLukasz Lasek test_sb_v3_region_reinit(); 559c8ab874dSKozlowski Mateusz 560d9f2ae9dSMateusz Kozlowski /* multiple (different ver) prev regions found: */ 561d9f2ae9dSMateusz Kozlowski sb_reg_next2->version = sb_reg_next->version - 1; 562d9f2ae9dSMateusz Kozlowski rc = ftl_superblock_v3_md_layout_load_all(&g_dev); 563d9f2ae9dSMateusz Kozlowski CU_ASSERT_EQUAL(rc, 0); 564d9f2ae9dSMateusz Kozlowski CU_ASSERT_EQUAL(reg->current.version, sb_reg_next2->version); 565d9f2ae9dSMateusz Kozlowski test_sb_v3_region_reinit(); 566d9f2ae9dSMateusz Kozlowski 567c8ab874dSKozlowski Mateusz /* multiple current regions found: */ 5682bb1753bSLukasz Lasek sb_reg_next->version = sb_reg->version; 5692bb1753bSLukasz Lasek sb_reg_next->df_next = df_next_reg; 570fa1fc76cSLukasz Lasek rc = ftl_superblock_v3_md_layout_load_all(&g_dev); 5712bb1753bSLukasz Lasek CU_ASSERT_EQUAL(rc, -EAGAIN); 572c8ab874dSKozlowski Mateusz 573c8ab874dSKozlowski Mateusz /* restore the sb: */ 5742bb1753bSLukasz Lasek sb->v3.md_layout_head.df_next = df_next_head; 5752bb1753bSLukasz Lasek test_sb_v3_region_reinit(); 5762bb1753bSLukasz Lasek } 5772bb1753bSLukasz Lasek 5782bb1753bSLukasz Lasek static void 5792bb1753bSLukasz Lasek test_sb_v5_md_layout(void) 5802bb1753bSLukasz Lasek { 5812bb1753bSLukasz Lasek struct layout_tracker_blob_entry *tbe; 5822bb1753bSLukasz Lasek struct layout_blob_entry *lbe; 5832bb1753bSLukasz Lasek struct ftl_layout_region *reg; 5842bb1753bSLukasz Lasek union ftl_superblock_ver *sb = (void *)g_sb_buf; 5852bb1753bSLukasz Lasek int rc; 5862bb1753bSLukasz Lasek const struct ftl_layout_tracker_bdev_region_props *reg_props; 5872bb1753bSLukasz Lasek void *blob_nvc, *blob_base, *blob_regs; 5882bb1753bSLukasz Lasek 5892bb1753bSLukasz Lasek test_setup_sb_v5(false); 5902bb1753bSLukasz Lasek CU_ASSERT_EQUAL(ftl_superblock_is_blob_area_empty(&sb->current), true); 5912bb1753bSLukasz Lasek 5922bb1753bSLukasz Lasek /* load failed: empty md list: */ 5932bb1753bSLukasz Lasek rc = ftl_superblock_v5_load_blob_area(&g_dev); 5942bb1753bSLukasz Lasek CU_ASSERT_NOT_EQUAL(rc, 0); 5952bb1753bSLukasz Lasek 5962bb1753bSLukasz Lasek /* create md layout: */ 5972bb1753bSLukasz Lasek for (enum ftl_layout_region_type regno = 0; regno < FTL_LAYOUT_REGION_TYPE_MAX; regno++) { 5982bb1753bSLukasz Lasek struct ftl_layout_region *reg = &g_dev.layout.region[regno]; 5992bb1753bSLukasz Lasek CU_ASSERT_EQUAL(regno, reg->type); 6002bb1753bSLukasz Lasek struct ftl_layout_tracker_bdev *tracker = sb_v3_md_region_is_nvc(regno) ? g_dev.nvc_layout_tracker : 6012bb1753bSLukasz Lasek g_dev.base_layout_tracker; 6022bb1753bSLukasz Lasek const struct ftl_layout_tracker_bdev_region_props *reg_props = ftl_layout_tracker_bdev_add_region( 6032bb1753bSLukasz Lasek tracker, reg->type, reg->current.version, reg->current.blocks, TEST_REG_BLKS); 6042bb1753bSLukasz Lasek 6052bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg->type, reg_props->type); 6062bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg->current.version, reg_props->ver); 6072bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg->current.offset, reg_props->blk_offs); 6082bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg->current.blocks, reg_props->blk_sz); 6092bb1753bSLukasz Lasek } 6102bb1753bSLukasz Lasek ftl_superblock_v5_store_blob_area(&g_dev); 6112bb1753bSLukasz Lasek CU_ASSERT_EQUAL(ftl_superblock_is_blob_area_empty(&sb->current), false); 6122bb1753bSLukasz Lasek 6132bb1753bSLukasz Lasek blob_nvc = ftl_df_get_obj_ptr(sb->v5.blob_area, sb->v5.md_layout_nvc.df_id); 6142bb1753bSLukasz Lasek blob_base = ftl_df_get_obj_ptr(sb->v5.blob_area, sb->v5.md_layout_base.df_id); 6152bb1753bSLukasz Lasek blob_regs = ftl_df_get_obj_ptr(sb->v5.blob_area, sb->v5.layout_params.df_id); 6162bb1753bSLukasz Lasek 6172bb1753bSLukasz Lasek /* unsupported nvc md region type: */ 6182bb1753bSLukasz Lasek tbe = blob_nvc; 6192bb1753bSLukasz Lasek tbe->type += FTL_LAYOUT_REGION_TYPE_MAX; 6202bb1753bSLukasz Lasek sb->v3.md_layout_head.type = FTL_LAYOUT_REGION_TYPE_SB; 6212bb1753bSLukasz Lasek rc = ftl_superblock_v5_load_blob_area(&g_dev); 6222bb1753bSLukasz Lasek CU_ASSERT_NOT_EQUAL(rc, 0); 6232bb1753bSLukasz Lasek tbe->type -= FTL_LAYOUT_REGION_TYPE_MAX; 6242bb1753bSLukasz Lasek 6252bb1753bSLukasz Lasek /* unsupported base md region type: */ 6262bb1753bSLukasz Lasek tbe = blob_base; 6272bb1753bSLukasz Lasek tbe->type += FTL_LAYOUT_REGION_TYPE_MAX; 6282bb1753bSLukasz Lasek sb->v3.md_layout_head.type = FTL_LAYOUT_REGION_TYPE_SB; 6292bb1753bSLukasz Lasek rc = ftl_superblock_v5_load_blob_area(&g_dev); 6302bb1753bSLukasz Lasek CU_ASSERT_NOT_EQUAL(rc, 0); 6312bb1753bSLukasz Lasek tbe->type -= FTL_LAYOUT_REGION_TYPE_MAX; 6322bb1753bSLukasz Lasek 6332bb1753bSLukasz Lasek /* load succeeded, no prev version found: */ 6342bb1753bSLukasz Lasek reg = &g_dev.layout.region[FTL_LAYOUT_REGION_TYPE_BAND_MD]; 6352bb1753bSLukasz Lasek rc = ftl_superblock_v5_load_blob_area(&g_dev); 6362bb1753bSLukasz Lasek CU_ASSERT_EQUAL(rc, 0); 6372bb1753bSLukasz Lasek reg_props = sb_md_layout_find_region(&g_dev, reg->type, sb_md_layout_find_latest_region, NULL); 6382bb1753bSLukasz Lasek CU_ASSERT_NOT_EQUAL(reg_props, NULL); 6392bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg_props->ver, reg->current.version); 6402bb1753bSLukasz Lasek reg_props = sb_md_layout_find_region(&g_dev, reg->type, sb_md_layout_find_oldest_region, NULL); 6412bb1753bSLukasz Lasek CU_ASSERT_NOT_EQUAL(reg_props, NULL); 6422bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg_props->ver, reg->current.version); 6432bb1753bSLukasz Lasek 6442bb1753bSLukasz Lasek /* move the sb-stored blobs around: */ 6452bb1753bSLukasz Lasek CU_ASSERT(blob_nvc < blob_base); 6462bb1753bSLukasz Lasek CU_ASSERT(blob_base < blob_regs); 6472bb1753bSLukasz Lasek blob_regs = memmove(blob_regs + 8192, blob_regs, sb->v5.layout_params.blob_sz); 6482bb1753bSLukasz Lasek sb->v5.layout_params.df_id += 8192; 6492bb1753bSLukasz Lasek blob_base = memmove(blob_base + 4096, blob_base, sb->v5.md_layout_base.blob_sz); 6502bb1753bSLukasz Lasek sb->v5.md_layout_base.df_id += 4096; 6512bb1753bSLukasz Lasek 6522bb1753bSLukasz Lasek /* load succeeded again, no prev version found: */ 6532bb1753bSLukasz Lasek rc = ftl_superblock_v5_load_blob_area(&g_dev); 6542bb1753bSLukasz Lasek CU_ASSERT_EQUAL(rc, 0); 6552bb1753bSLukasz Lasek reg_props = sb_md_layout_find_region(&g_dev, reg->type, sb_md_layout_find_latest_region, NULL); 6562bb1753bSLukasz Lasek CU_ASSERT_NOT_EQUAL(reg_props, NULL); 6572bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg_props->ver, reg->current.version); 6582bb1753bSLukasz Lasek reg_props = sb_md_layout_find_region(&g_dev, reg->type, sb_md_layout_find_oldest_region, NULL); 6592bb1753bSLukasz Lasek CU_ASSERT_NOT_EQUAL(reg_props, NULL); 6602bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg_props->ver, reg->current.version); 6612bb1753bSLukasz Lasek 6622bb1753bSLukasz Lasek /* load failed, regs overlap: */ 6632bb1753bSLukasz Lasek tbe = blob_nvc; 6642bb1753bSLukasz Lasek tbe++; 6652bb1753bSLukasz Lasek tbe->blk_offs -= tbe->blk_sz; 6662bb1753bSLukasz Lasek rc = ftl_superblock_v5_load_blob_area(&g_dev); 6672bb1753bSLukasz Lasek CU_ASSERT_NOT_EQUAL(rc, 0); 6682bb1753bSLukasz Lasek tbe->blk_offs += tbe->blk_sz; 6692bb1753bSLukasz Lasek 6702bb1753bSLukasz Lasek /* load failed, the same region version found twice: */ 6712bb1753bSLukasz Lasek tbe = (blob_nvc + sb->v5.md_layout_nvc.blob_sz); 6722bb1753bSLukasz Lasek sb->v5.md_layout_nvc.blob_sz += sizeof(*tbe); 6732bb1753bSLukasz Lasek tbe->type = reg->type; 6742bb1753bSLukasz Lasek tbe->ver = reg->current.version; 6752bb1753bSLukasz Lasek tbe->blk_offs = reg->current.offset + FTL_LAYOUT_REGION_TYPE_MAX * reg->current.blocks; 6762bb1753bSLukasz Lasek tbe->blk_sz = reg->current.blocks; 6772bb1753bSLukasz Lasek rc = ftl_superblock_v5_load_blob_area(&g_dev); 6782bb1753bSLukasz Lasek CU_ASSERT_NOT_EQUAL(rc, 0); 6792bb1753bSLukasz Lasek 6802bb1753bSLukasz Lasek /* load succeeded, prev (upgrade, i.e. no current) version discovery: */ 6812bb1753bSLukasz Lasek tbe->type = reg->type; 6822bb1753bSLukasz Lasek tbe->ver = reg->current.version - 1; 6832bb1753bSLukasz Lasek tbe->blk_offs = reg->current.offset + FTL_LAYOUT_REGION_TYPE_MAX * reg->current.blocks; 6842bb1753bSLukasz Lasek tbe->blk_sz = reg->current.blocks; 6852bb1753bSLukasz Lasek rc = ftl_superblock_v5_load_blob_area(&g_dev); 6862bb1753bSLukasz Lasek CU_ASSERT_EQUAL(rc, 0); 6872bb1753bSLukasz Lasek reg_props = sb_md_layout_find_region(&g_dev, reg->type, sb_md_layout_find_latest_region, NULL); 6882bb1753bSLukasz Lasek CU_ASSERT_NOT_EQUAL(reg_props, NULL); 6892bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg_props->ver, reg->current.version); 6902bb1753bSLukasz Lasek reg_props = sb_md_layout_find_region(&g_dev, reg->type, sb_md_layout_find_oldest_region, NULL); 6912bb1753bSLukasz Lasek CU_ASSERT_NOT_EQUAL(reg_props, NULL); 6922bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg_props->ver, reg->current.version - 1); 6932bb1753bSLukasz Lasek 6942bb1753bSLukasz Lasek /* load succeeded, newer version found: */ 6952bb1753bSLukasz Lasek tbe->ver = reg->current.version + 1; 6962bb1753bSLukasz Lasek rc = ftl_superblock_v5_load_blob_area(&g_dev); 6972bb1753bSLukasz Lasek CU_ASSERT_EQUAL(rc, 0); 6982bb1753bSLukasz Lasek reg_props = sb_md_layout_find_region(&g_dev, reg->type, sb_md_layout_find_latest_region, NULL); 6992bb1753bSLukasz Lasek CU_ASSERT_NOT_EQUAL(reg_props, NULL); 7002bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg_props->ver, reg->current.version + 1); 7012bb1753bSLukasz Lasek reg_props = sb_md_layout_find_region(&g_dev, reg->type, sb_md_layout_find_oldest_region, NULL); 7022bb1753bSLukasz Lasek CU_ASSERT_NOT_EQUAL(reg_props, NULL); 7032bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg_props->ver, reg->current.version); 7042bb1753bSLukasz Lasek 7052bb1753bSLukasz Lasek /* load failed, invalid type in layout properties: */ 7062bb1753bSLukasz Lasek lbe = blob_regs; 7072bb1753bSLukasz Lasek lbe += FTL_LAYOUT_REGION_TYPE_BAND_MD; 7082bb1753bSLukasz Lasek CU_ASSERT_EQUAL(lbe->type, FTL_LAYOUT_REGION_TYPE_BAND_MD); 7092bb1753bSLukasz Lasek lbe->type = FTL_LAYOUT_REGION_TYPE_MAX; 7102bb1753bSLukasz Lasek rc = ftl_superblock_v5_load_blob_area(&g_dev); 7112bb1753bSLukasz Lasek CU_ASSERT_NOT_EQUAL(rc, 0); 7122bb1753bSLukasz Lasek lbe->type = FTL_LAYOUT_REGION_TYPE_BAND_MD; 7132bb1753bSLukasz Lasek 7142bb1753bSLukasz Lasek /* load succeeded, restore layout properties: */ 7152bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg->num_entries, 0); 7162bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg->entry_size, 0); 7172bb1753bSLukasz Lasek lbe->num_entries = 0x1984; 7182bb1753bSLukasz Lasek lbe->entry_size = 0x1405; 7192bb1753bSLukasz Lasek rc = ftl_superblock_v5_load_blob_area(&g_dev); 7202bb1753bSLukasz Lasek CU_ASSERT_EQUAL(rc, 0); 7212bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg->num_entries, 0x1984); 7222bb1753bSLukasz Lasek CU_ASSERT_EQUAL(reg->entry_size, 0x1405); 7232bb1753bSLukasz Lasek 7242bb1753bSLukasz Lasek /* restore the sb: */ 7252bb1753bSLukasz Lasek sb->v5.md_layout_nvc.blob_sz -= sizeof(*tbe); 726c8ab874dSKozlowski Mateusz } 727c8ab874dSKozlowski Mateusz 728c8ab874dSKozlowski Mateusz int 729c8ab874dSKozlowski Mateusz main(int argc, char **argv) 730c8ab874dSKozlowski Mateusz { 731c8ab874dSKozlowski Mateusz CU_pSuite suite = NULL; 7322bb1753bSLukasz Lasek unsigned int num_failures = 0; 733c8ab874dSKozlowski Mateusz 7342bb1753bSLukasz Lasek CU_set_error_action(CUEA_ABORT); 735c8ab874dSKozlowski Mateusz CU_initialize_registry(); 736c8ab874dSKozlowski Mateusz 7372bb1753bSLukasz Lasek suite = CU_add_suite("ftl_sb", test_setup, test_teardown); 738c8ab874dSKozlowski Mateusz 739c8ab874dSKozlowski Mateusz CU_ADD_TEST(suite, test_sb_crc_v2); 740c8ab874dSKozlowski Mateusz CU_ADD_TEST(suite, test_sb_crc_v3); 741c8ab874dSKozlowski Mateusz CU_ADD_TEST(suite, test_sb_v3_md_layout); 7422bb1753bSLukasz Lasek CU_ADD_TEST(suite, test_sb_v5_md_layout); 743c8ab874dSKozlowski Mateusz 7442bb1753bSLukasz Lasek CU_basic_set_mode(CU_BRM_VERBOSE); 7452bb1753bSLukasz Lasek CU_basic_run_tests(); 7462bb1753bSLukasz Lasek num_failures = CU_get_number_of_failures(); 747c8ab874dSKozlowski Mateusz CU_cleanup_registry(); 748c8ab874dSKozlowski Mateusz 749c8ab874dSKozlowski Mateusz return num_failures; 750c8ab874dSKozlowski Mateusz } 751