1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/thread.h" 7 #include "spdk/crc32.h" 8 9 #include "ftl_core.h" 10 #include "ftl_mngt.h" 11 #include "ftl_mngt_steps.h" 12 #include "ftl_utils.h" 13 #include "ftl_band.h" 14 #include "ftl_internal.h" 15 #include "ftl_sb.h" 16 17 void 18 ftl_mngt_init_layout(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 19 { 20 if (ftl_layout_setup(dev)) { 21 ftl_mngt_fail_step(mngt); 22 } else { 23 ftl_mngt_next_step(mngt); 24 } 25 } 26 27 static bool 28 is_buffer_needed(enum ftl_layout_region_type type) 29 { 30 switch (type) { 31 #ifdef SPDK_FTL_VSS_EMU 32 case FTL_LAYOUT_REGION_TYPE_VSS: 33 #endif 34 case FTL_LAYOUT_REGION_TYPE_SB: 35 case FTL_LAYOUT_REGION_TYPE_SB_BASE: 36 case FTL_LAYOUT_REGION_TYPE_DATA_NVC: 37 case FTL_LAYOUT_REGION_TYPE_DATA_BASE: 38 case FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR: 39 case FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR: 40 return false; 41 42 default: 43 return true; 44 } 45 } 46 47 void 48 ftl_mngt_init_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 49 { 50 struct ftl_layout *layout = &dev->layout; 51 struct ftl_layout_region *region = layout->region; 52 uint64_t i; 53 int md_flags; 54 55 for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++, region++) { 56 if (layout->md[i]) { 57 /* 58 * Some metadata objects are initialized by other FTL 59 * components. At the moment it's only used by superblock (and its mirror) - 60 * during load time we need to read it earlier in order to get the layout for the 61 * other regions. 62 */ 63 continue; 64 } 65 md_flags = is_buffer_needed(i) ? 66 FTL_MD_CREATE_SHM | FTL_MD_CREATE_SHM_NEW : 67 FTL_MD_CREATE_NO_MEM; 68 layout->md[i] = ftl_md_create(dev, region->current.blocks, region->vss_blksz, region->name, 69 md_flags, region); 70 if (NULL == layout->md[i]) { 71 ftl_mngt_fail_step(mngt); 72 return; 73 } 74 } 75 76 ftl_mngt_next_step(mngt); 77 } 78 79 void 80 ftl_mngt_deinit_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 81 { 82 struct ftl_layout *layout = &dev->layout; 83 struct ftl_layout_region *region = layout->region; 84 uint64_t i; 85 86 for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++, region++) { 87 if (layout->md[i]) { 88 ftl_md_destroy(layout->md[i]); 89 layout->md[i] = NULL; 90 } 91 } 92 93 ftl_mngt_next_step(mngt); 94 } 95 96 static void 97 persist_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status) 98 { 99 struct ftl_mngt_process *mngt = md->owner.cb_ctx; 100 101 if (status) { 102 ftl_mngt_fail_step(mngt); 103 } else { 104 ftl_mngt_next_step(mngt); 105 } 106 } 107 108 static void 109 persist(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt, 110 enum ftl_layout_region_type type) 111 { 112 struct ftl_layout *layout = &dev->layout; 113 struct ftl_md *md; 114 115 assert(type < FTL_LAYOUT_REGION_TYPE_MAX); 116 117 md = layout->md[type]; 118 if (!md) { 119 ftl_mngt_fail_step(mngt); 120 return; 121 } 122 123 md->owner.cb_ctx = mngt; 124 md->cb = persist_cb; 125 ftl_md_persist(md); 126 } 127 128 void 129 ftl_mngt_persist_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 130 { 131 if (ftl_nv_cache_save_state(&dev->nv_cache)) { 132 ftl_mngt_fail_step(mngt); 133 return; 134 } 135 136 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_NVC_MD); 137 } 138 139 void 140 ftl_mngt_persist_band_info_metadata( 141 struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 142 { 143 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_BAND_MD); 144 } 145 146 static uint32_t 147 get_sb_crc(struct ftl_superblock *sb) 148 { 149 uint32_t crc = 0; 150 151 /* Calculate CRC excluding CRC field in superblock */ 152 void *buffer = sb; 153 size_t offset = offsetof(struct ftl_superblock, header.crc); 154 size_t size = offset; 155 crc = spdk_crc32c_update(buffer, size, crc); 156 157 buffer += offset + sizeof(sb->header.crc); 158 size = FTL_SUPERBLOCK_SIZE - offset - sizeof(sb->header.crc); 159 crc = spdk_crc32c_update(buffer, size, crc); 160 161 return crc; 162 } 163 164 void 165 ftl_mngt_init_default_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 166 { 167 struct ftl_superblock *sb = dev->sb; 168 169 sb->header.magic = FTL_SUPERBLOCK_MAGIC; 170 sb->header.version = FTL_METADATA_VERSION_CURRENT; 171 sb->uuid = dev->conf.uuid; 172 sb->clean = 0; 173 dev->sb_shm->shm_clean = false; 174 175 /* Max 16 IO depth per band relocate */ 176 sb->max_reloc_qdepth = 16; 177 178 sb->overprovisioning = dev->conf.overprovisioning; 179 180 ftl_band_init_gc_iter(dev); 181 182 /* md layout isn't initialized yet. 183 * empty region list => all regions in the default location */ 184 sb->md_layout_head.type = FTL_LAYOUT_REGION_TYPE_INVALID; 185 186 sb->header.crc = get_sb_crc(sb); 187 188 ftl_mngt_next_step(mngt); 189 } 190 191 void 192 ftl_mngt_set_dirty(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 193 { 194 struct ftl_superblock *sb = dev->sb; 195 196 sb->clean = 0; 197 dev->sb_shm->shm_clean = false; 198 sb->header.crc = get_sb_crc(sb); 199 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 200 } 201 202 /* 203 * Initializes the superblock fields during first startup of FTL 204 */ 205 static const struct ftl_mngt_process_desc desc_init_sb = { 206 .name = "SB initialize", 207 .steps = { 208 { 209 .name = "Default-initialize superblock", 210 .action = ftl_mngt_init_default_sb, 211 }, 212 {} 213 } 214 }; 215 216 #ifdef SPDK_FTL_VSS_EMU 217 void 218 ftl_mngt_md_init_vss_emu(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 219 { 220 struct ftl_layout *layout = &dev->layout; 221 struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_VSS]; 222 223 /* Initialize VSS layout */ 224 ftl_layout_setup_vss_emu(dev); 225 226 /* Allocate md buf */ 227 layout->md[FTL_LAYOUT_REGION_TYPE_VSS] = ftl_md_create(dev, region->current.blocks, 228 region->vss_blksz, NULL, 0, region); 229 if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_VSS]) { 230 ftl_mngt_fail_step(mngt); 231 return; 232 } 233 ftl_mngt_next_step(mngt); 234 } 235 236 void 237 ftl_mngt_md_deinit_vss_emu(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 238 { 239 struct ftl_layout *layout = &dev->layout; 240 241 if (layout->md[FTL_LAYOUT_REGION_TYPE_VSS]) { 242 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_VSS]); 243 layout->md[FTL_LAYOUT_REGION_TYPE_VSS] = NULL; 244 } 245 246 ftl_mngt_next_step(mngt); 247 } 248 #endif 249 250 void 251 ftl_mngt_superblock_init(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 252 { 253 struct ftl_layout *layout = &dev->layout; 254 struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB]; 255 char uuid[SPDK_UUID_STRING_LEN]; 256 int md_create_flags = FTL_MD_CREATE_SHM | FTL_MD_CREATE_SHM_NEW; 257 258 /* Must generate UUID before MD create on SHM for the SB */ 259 if (dev->conf.mode & SPDK_FTL_MODE_CREATE) { 260 spdk_uuid_generate(&dev->conf.uuid); 261 spdk_uuid_fmt_lower(uuid, sizeof(uuid), &dev->conf.uuid); 262 FTL_NOTICELOG(dev, "Create new FTL, UUID %s\n", uuid); 263 } 264 265 /* Allocate md buf */ 266 dev->sb_shm = NULL; 267 dev->sb_shm_md = ftl_md_create(dev, spdk_divide_round_up(sizeof(*dev->sb_shm), FTL_BLOCK_SIZE), 268 0, "sb_shm", 269 md_create_flags, NULL); 270 if (dev->sb_shm_md == NULL) { 271 ftl_mngt_fail_step(mngt); 272 return; 273 } 274 275 dev->sb_shm = ftl_md_get_buffer(dev->sb_shm_md); 276 277 /* Setup the layout of a superblock */ 278 if (ftl_layout_setup_superblock(dev)) { 279 ftl_mngt_fail_step(mngt); 280 return; 281 } 282 283 /* Allocate md buf */ 284 layout->md[FTL_LAYOUT_REGION_TYPE_SB] = ftl_md_create(dev, region->current.blocks, 285 region->vss_blksz, region->name, 286 md_create_flags, region); 287 if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB]) { 288 ftl_mngt_fail_step(mngt); 289 return; 290 } 291 292 /* Link the md buf to the device */ 293 dev->sb = ftl_md_get_buffer(layout->md[FTL_LAYOUT_REGION_TYPE_SB]); 294 295 /* Setup superblock mirror to QLC */ 296 region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB_BASE]; 297 layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = ftl_md_create(dev, region->current.blocks, 298 region->vss_blksz, NULL, FTL_MD_CREATE_HEAP, region); 299 if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) { 300 ftl_mngt_fail_step(mngt); 301 return; 302 } 303 304 /* Initialize the superblock */ 305 if (dev->conf.mode & SPDK_FTL_MODE_CREATE) { 306 ftl_mngt_call_process(mngt, &desc_init_sb); 307 } else { 308 ftl_mngt_fail_step(mngt); 309 } 310 } 311 312 void 313 ftl_mngt_superblock_deinit(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 314 { 315 struct ftl_layout *layout = &dev->layout; 316 317 if (layout->md[FTL_LAYOUT_REGION_TYPE_SB]) { 318 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB]); 319 layout->md[FTL_LAYOUT_REGION_TYPE_SB] = NULL; 320 } 321 322 if (layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) { 323 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]); 324 layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = NULL; 325 } 326 327 ftl_md_destroy(dev->sb_shm_md); 328 dev->sb_shm_md = NULL; 329 dev->sb_shm = NULL; 330 331 ftl_mngt_next_step(mngt); 332 } 333