Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright 2023 Solidigm All Rights Reserved 3 : : * Copyright (C) 2022 Intel Corporation. 4 : : * All rights reserved. 5 : : */ 6 : : 7 : : #include "ftl_sb_v3.h" 8 : : #include "ftl_core.h" 9 : : #include "ftl_layout.h" 10 : : #include "upgrade/ftl_sb_upgrade.h" 11 : : 12 : : bool 13 : 17 : ftl_superblock_v3_check_magic(union ftl_superblock_ver *sb_ver) 14 : : { 15 : 17 : return sb_ver->header.magic == FTL_SUPERBLOCK_MAGIC; 16 : : } 17 : : 18 : : bool 19 : 15 : ftl_superblock_v3_md_layout_is_empty(union ftl_superblock_ver *sb_ver) 20 : : { 21 : 15 : return sb_ver->v3.md_layout_head.type == FTL_LAYOUT_REGION_TYPE_INVALID; 22 : : } 23 : : 24 : : static bool 25 : 1785 : md_region_is_fixed(int reg_type) 26 : : { 27 [ + + ]: 1785 : switch (reg_type) { 28 : 260 : case FTL_LAYOUT_REGION_TYPE_SB: 29 : : case FTL_LAYOUT_REGION_TYPE_SB_BASE: 30 : : case FTL_LAYOUT_REGION_TYPE_DATA_BASE: 31 : 260 : return true; 32 : : 33 : 1525 : default: 34 : 1525 : return false; 35 : : } 36 : : } 37 : : 38 : : bool 39 : 505 : ftl_superblock_v3_md_region_overflow(struct spdk_ftl_dev *dev, 40 : : struct ftl_superblock_v3_md_region *sb_reg) 41 : : { 42 : : /* sb_reg is part of the sb structure - the pointer should be at a positive offset */ 43 [ - + ]: 505 : if ((uintptr_t)sb_reg < (uintptr_t)dev->sb) { 44 : 0 : return true; 45 : : } 46 : : 47 : : /* Make sure the entry doesn't overflow the pointer value (probably overkill to check) */ 48 [ - + ]: 505 : if (UINT64_MAX - (uintptr_t)sb_reg <= sizeof(*sb_reg)) { 49 : 0 : return true; 50 : : } 51 : : 52 : : /* There's only a finite (FTL_SUPERBLOCK_SIZE) amount of space in the superblock. Make sure the region wholly fits in that space. */ 53 [ + + ]: 505 : if ((uintptr_t)(sb_reg + 1) > ((uintptr_t)(dev->sb) + FTL_SUPERBLOCK_SIZE)) { 54 : 5 : return true; 55 : : } 56 : : 57 : 500 : return false; 58 : : } 59 : : 60 : : int 61 : 80 : ftl_superblock_v3_md_layout_load_all(struct spdk_ftl_dev *dev) 62 : : { 63 : 80 : struct ftl_superblock_v3 *sb = (struct ftl_superblock_v3 *)dev->sb; 64 : 80 : struct ftl_superblock_v3_md_region *sb_reg = &sb->md_layout_head; 65 : 80 : struct ftl_layout *layout = &dev->layout; 66 : : uint32_t regs_found; 67 : : uint32_t n; 68 : 80 : ftl_df_obj_id df_sentinel = FTL_DF_OBJ_ID_INVALID; 69 : 80 : ftl_df_obj_id df_prev = ftl_df_get_obj_id(sb, sb_reg); 70 : : 71 [ + + ]: 1360 : for (n = 0; n < FTL_LAYOUT_REGION_TYPE_MAX_V3; n++) { 72 [ + + ]: 1280 : if (md_region_is_fixed(n)) { 73 : 240 : continue; 74 : : } 75 : 1040 : layout->region[n].type = FTL_LAYOUT_REGION_TYPE_INVALID; 76 : : } 77 : : 78 [ + + ]: 490 : while (sb_reg->type != FTL_LAYOUT_REGION_TYPE_INVALID) { 79 : : struct ftl_layout_region *reg; 80 : : 81 : : /* TODO: major upgrades: add free regions tracking */ 82 [ + + ]: 485 : if (sb_reg->type == FTL_LAYOUT_REGION_TYPE_FREE_NVC || 83 [ + + ]: 460 : sb_reg->type == FTL_LAYOUT_REGION_TYPE_FREE_BASE) { 84 : 50 : goto next_sb_reg; 85 : : } 86 : : 87 [ + + ]: 435 : if (sb_reg->type >= FTL_LAYOUT_REGION_TYPE_MAX_V3) { 88 [ + - ]: 10 : FTL_ERRLOG(dev, "Invalid MD region type found\n"); 89 : 10 : return -1; 90 : : } 91 : : 92 [ + + ]: 425 : if (md_region_is_fixed(sb_reg->type)) { 93 [ + - ]: 5 : FTL_ERRLOG(dev, "Unsupported MD region type found\n"); 94 : 5 : return -1; 95 : : } 96 : : 97 : 420 : reg = &layout->region[sb_reg->type]; 98 : : /* Find the oldest region version */ 99 [ + + + + ]: 420 : if (reg->type == FTL_LAYOUT_REGION_TYPE_INVALID || sb_reg->version < reg->current.version) { 100 : 400 : reg->type = sb_reg->type; 101 : 400 : reg->current.offset = sb_reg->blk_offs; 102 : 400 : reg->current.blocks = sb_reg->blk_sz; 103 : 400 : reg->current.version = sb_reg->version; 104 [ + + ]: 20 : } else if (sb_reg->version == reg->current.version) { 105 [ + - ]: 10 : FTL_ERRLOG(dev, "Multiple/looping regions found\n"); 106 : 10 : return -EAGAIN; 107 : : } 108 : : 109 : 10 : next_sb_reg: 110 [ + + ]: 460 : if (sb_reg->df_next == FTL_DF_OBJ_ID_INVALID) { 111 : 25 : break; 112 : : } 113 : : 114 [ + + ]: 435 : if (UINT64_MAX - (uintptr_t)sb <= sb_reg->df_next) { 115 [ + - ]: 10 : FTL_ERRLOG(dev, "Buffer overflow\n"); 116 : 10 : return -EOVERFLOW; 117 : : } 118 : : 119 [ + + ]: 425 : if (sb_reg->df_next <= df_prev) { 120 : 40 : df_sentinel = df_prev; 121 : : } 122 : 425 : df_prev = sb_reg->df_next; 123 : : 124 [ + + + + ]: 425 : if (df_sentinel != FTL_DF_OBJ_ID_INVALID && sb_reg->df_next == df_sentinel) { 125 [ + - ]: 10 : FTL_ERRLOG(dev, "Looping regions found\n"); 126 : 10 : return -ELOOP; 127 : : } 128 : : 129 : 415 : sb_reg = ftl_df_get_obj_ptr(sb, sb_reg->df_next); 130 [ + + ]: 415 : if (ftl_superblock_v3_md_region_overflow(dev, sb_reg)) { 131 [ + - ]: 5 : FTL_ERRLOG(dev, "Buffer overflow\n"); 132 : 5 : return -EOVERFLOW; 133 : : } 134 : : } 135 : : 136 [ + + ]: 510 : for (regs_found = 0, n = 0; n < FTL_LAYOUT_REGION_TYPE_MAX_V3; n++) { 137 [ + + ]: 480 : if (layout->region[n].type == n) { 138 : 415 : regs_found++; 139 : : } 140 : : } 141 : : 142 [ + + ]: 30 : if (regs_found != FTL_LAYOUT_REGION_TYPE_MAX_V3) { 143 [ + - ]: 5 : FTL_ERRLOG(dev, "Missing regions\n"); 144 : 5 : return -1; 145 : : } 146 : : 147 : 25 : return 0; 148 : : } 149 : : 150 : : void 151 : 0 : ftl_superblock_v3_md_layout_dump(struct spdk_ftl_dev *dev) 152 : : { 153 : 0 : struct ftl_superblock_v3 *sb = (struct ftl_superblock_v3 *)dev->sb; 154 : 0 : struct ftl_superblock_v3_md_region *sb_reg = &sb->md_layout_head; 155 : : 156 [ # # ]: 0 : FTL_NOTICELOG(dev, "SB metadata layout:\n"); 157 [ # # ]: 0 : while (sb_reg->type != FTL_LAYOUT_REGION_TYPE_INVALID) { 158 [ # # ]: 0 : FTL_NOTICELOG(dev, 159 : : "Region df:0x%"PRIx64" type:0x%"PRIx32" ver:%"PRIu32" blk_offs:0x%"PRIx64" blk_sz:0x%"PRIx64"\n", 160 : : ftl_df_get_obj_id(sb, sb_reg), sb_reg->type, sb_reg->version, sb_reg->blk_offs, sb_reg->blk_sz); 161 : : 162 [ # # ]: 0 : if (sb_reg->df_next == FTL_DF_OBJ_ID_INVALID) { 163 : 0 : break; 164 : : } 165 : : 166 : 0 : sb_reg = ftl_df_get_obj_ptr(sb, sb_reg->df_next); 167 [ # # ]: 0 : if (ftl_superblock_v3_md_region_overflow(dev, sb_reg)) { 168 [ # # ]: 0 : FTL_ERRLOG(dev, "Buffer overflow\n"); 169 : 0 : return; 170 : : } 171 : : } 172 : : }