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) ? ftl_md_create_region_flags(dev, 66 region->type) : FTL_MD_CREATE_NO_MEM; 67 layout->md[i] = ftl_md_create(dev, region->current.blocks, region->vss_blksz, region->name, 68 md_flags, region); 69 if (NULL == layout->md[i]) { 70 ftl_mngt_fail_step(mngt); 71 return; 72 } 73 } 74 75 ftl_mngt_next_step(mngt); 76 } 77 78 void 79 ftl_mngt_deinit_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 80 { 81 struct ftl_layout *layout = &dev->layout; 82 struct ftl_layout_region *region = layout->region; 83 uint64_t i; 84 85 for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++, region++) { 86 if (layout->md[i]) { 87 ftl_md_destroy(layout->md[i], ftl_md_destroy_region_flags(dev, layout->region[i].type)); 88 layout->md[i] = NULL; 89 } 90 } 91 92 ftl_mngt_next_step(mngt); 93 } 94 95 static void 96 persist_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status) 97 { 98 struct ftl_mngt_process *mngt = md->owner.cb_ctx; 99 100 if (status) { 101 ftl_mngt_fail_step(mngt); 102 } else { 103 ftl_mngt_next_step(mngt); 104 } 105 } 106 107 static void 108 persist(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt, 109 enum ftl_layout_region_type type) 110 { 111 struct ftl_layout *layout = &dev->layout; 112 struct ftl_md *md; 113 114 assert(type < FTL_LAYOUT_REGION_TYPE_MAX); 115 116 md = layout->md[type]; 117 if (!md) { 118 ftl_mngt_fail_step(mngt); 119 return; 120 } 121 122 md->owner.cb_ctx = mngt; 123 md->cb = persist_cb; 124 ftl_md_persist(md); 125 } 126 127 void 128 ftl_mngt_persist_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 129 { 130 if (ftl_nv_cache_save_state(&dev->nv_cache)) { 131 ftl_mngt_fail_step(mngt); 132 return; 133 } 134 135 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_NVC_MD); 136 } 137 138 void 139 ftl_mngt_persist_band_info_metadata( 140 struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 141 { 142 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_BAND_MD); 143 } 144 145 static uint32_t 146 get_sb_crc(struct ftl_superblock *sb) 147 { 148 uint32_t crc = 0; 149 150 /* Calculate CRC excluding CRC field in superblock */ 151 void *buffer = sb; 152 size_t offset = offsetof(struct ftl_superblock, header.crc); 153 size_t size = offset; 154 crc = spdk_crc32c_update(buffer, size, crc); 155 156 buffer += offset + sizeof(sb->header.crc); 157 size = FTL_SUPERBLOCK_SIZE - offset - sizeof(sb->header.crc); 158 crc = spdk_crc32c_update(buffer, size, crc); 159 160 return crc; 161 } 162 163 void 164 ftl_mngt_init_default_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 165 { 166 struct ftl_superblock *sb = dev->sb; 167 168 sb->header.magic = FTL_SUPERBLOCK_MAGIC; 169 sb->header.version = FTL_METADATA_VERSION_CURRENT; 170 sb->uuid = dev->conf.uuid; 171 sb->clean = 0; 172 dev->sb_shm->shm_clean = false; 173 174 /* Max 16 IO depth per band relocate */ 175 sb->max_reloc_qdepth = 16; 176 177 sb->overprovisioning = dev->conf.overprovisioning; 178 179 ftl_band_init_gc_iter(dev); 180 181 /* md layout isn't initialized yet. 182 * empty region list => all regions in the default location */ 183 sb->md_layout_head.type = FTL_LAYOUT_REGION_TYPE_INVALID; 184 185 sb->header.crc = get_sb_crc(sb); 186 187 ftl_mngt_next_step(mngt); 188 } 189 190 void 191 ftl_mngt_set_dirty(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 192 { 193 struct ftl_superblock *sb = dev->sb; 194 195 sb->clean = 0; 196 dev->sb_shm->shm_clean = false; 197 sb->header.crc = get_sb_crc(sb); 198 persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB); 199 } 200 201 /* 202 * Initializes the superblock fields during first startup of FTL 203 */ 204 static const struct ftl_mngt_process_desc desc_init_sb = { 205 .name = "SB initialize", 206 .steps = { 207 { 208 .name = "Default-initialize superblock", 209 .action = ftl_mngt_init_default_sb, 210 }, 211 {} 212 } 213 }; 214 215 #ifdef SPDK_FTL_VSS_EMU 216 void 217 ftl_mngt_md_init_vss_emu(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 218 { 219 struct ftl_layout *layout = &dev->layout; 220 struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_VSS]; 221 222 /* Initialize VSS layout */ 223 ftl_layout_setup_vss_emu(dev); 224 225 /* Allocate md buf */ 226 layout->md[FTL_LAYOUT_REGION_TYPE_VSS] = ftl_md_create(dev, region->current.blocks, 227 region->vss_blksz, NULL, 0, region); 228 if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_VSS]) { 229 ftl_mngt_fail_step(mngt); 230 return; 231 } 232 ftl_mngt_next_step(mngt); 233 } 234 235 void 236 ftl_mngt_md_deinit_vss_emu(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 237 { 238 struct ftl_layout *layout = &dev->layout; 239 240 if (layout->md[FTL_LAYOUT_REGION_TYPE_VSS]) { 241 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_VSS], 0); 242 layout->md[FTL_LAYOUT_REGION_TYPE_VSS] = NULL; 243 } 244 245 ftl_mngt_next_step(mngt); 246 } 247 #endif 248 249 void 250 ftl_mngt_superblock_init(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 251 { 252 struct ftl_layout *layout = &dev->layout; 253 struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB]; 254 char uuid[SPDK_UUID_STRING_LEN]; 255 int md_create_flags = ftl_md_create_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB); 256 257 /* Must generate UUID before MD create on SHM for the SB */ 258 if (dev->conf.mode & SPDK_FTL_MODE_CREATE) { 259 spdk_uuid_generate(&dev->conf.uuid); 260 spdk_uuid_fmt_lower(uuid, sizeof(uuid), &dev->conf.uuid); 261 FTL_NOTICELOG(dev, "Create new FTL, UUID %s\n", uuid); 262 } 263 264 shm_retry: 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 /* The first attempt may fail when trying to open SHM - try to create new */ 272 if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) { 273 md_create_flags |= FTL_MD_CREATE_SHM_NEW; 274 goto shm_retry; 275 } 276 if (dev->sb_shm_md == NULL) { 277 ftl_mngt_fail_step(mngt); 278 return; 279 } 280 } 281 282 dev->sb_shm = ftl_md_get_buffer(dev->sb_shm_md); 283 284 /* Setup the layout of a superblock */ 285 if (ftl_layout_setup_superblock(dev)) { 286 ftl_mngt_fail_step(mngt); 287 return; 288 } 289 290 /* Allocate md buf */ 291 layout->md[FTL_LAYOUT_REGION_TYPE_SB] = ftl_md_create(dev, region->current.blocks, 292 region->vss_blksz, region->name, 293 md_create_flags, region); 294 if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB]) { 295 /* The first attempt may fail when trying to open SHM - try to create new */ 296 if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) { 297 md_create_flags |= FTL_MD_CREATE_SHM_NEW; 298 ftl_md_destroy(dev->sb_shm_md, 0); 299 goto shm_retry; 300 } 301 ftl_mngt_fail_step(mngt); 302 return; 303 } 304 305 /* Link the md buf to the device */ 306 dev->sb = ftl_md_get_buffer(layout->md[FTL_LAYOUT_REGION_TYPE_SB]); 307 308 /* Setup superblock mirror to QLC */ 309 region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB_BASE]; 310 layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = ftl_md_create(dev, region->current.blocks, 311 region->vss_blksz, NULL, FTL_MD_CREATE_HEAP, region); 312 if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) { 313 ftl_mngt_fail_step(mngt); 314 return; 315 } 316 317 /* Initialize the superblock */ 318 if (dev->conf.mode & SPDK_FTL_MODE_CREATE) { 319 ftl_mngt_call_process(mngt, &desc_init_sb); 320 } else { 321 ftl_mngt_fail_step(mngt); 322 } 323 } 324 325 void 326 ftl_mngt_superblock_deinit(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 327 { 328 struct ftl_layout *layout = &dev->layout; 329 330 if (layout->md[FTL_LAYOUT_REGION_TYPE_SB]) { 331 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB], 332 ftl_md_destroy_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB)); 333 layout->md[FTL_LAYOUT_REGION_TYPE_SB] = NULL; 334 } 335 336 if (layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) { 337 ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE], 0); 338 layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = NULL; 339 } 340 341 ftl_md_destroy(dev->sb_shm_md, ftl_md_destroy_shm_flags(dev)); 342 dev->sb_shm_md = NULL; 343 dev->sb_shm = NULL; 344 345 ftl_mngt_next_step(mngt); 346 } 347