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_core.h" 8 #include "ftl_mngt.h" 9 #include "ftl_mngt_steps.h" 10 11 static const struct ftl_mngt_process_desc desc_startup; 12 static const struct ftl_mngt_process_desc desc_first_start; 13 static const struct ftl_mngt_process_desc desc_restore; 14 static const struct ftl_mngt_process_desc desc_clean_start; 15 16 static void 17 ftl_mngt_select_startup_mode(struct spdk_ftl_dev *dev, 18 struct ftl_mngt_process *mngt) 19 { 20 if (dev->conf.mode & SPDK_FTL_MODE_CREATE) { 21 ftl_mngt_call_process(mngt, &desc_first_start); 22 } else { 23 ftl_mngt_call_process(mngt, &desc_restore); 24 } 25 } 26 27 static void 28 ftl_mngt_select_restore_mode(struct spdk_ftl_dev *dev, 29 struct ftl_mngt_process *mngt) 30 { 31 if (dev->sb->clean) { 32 ftl_mngt_call_process(mngt, &desc_clean_start); 33 } else { 34 ftl_mngt_recover(dev, mngt); 35 } 36 } 37 38 /* 39 * Common startup steps required by FTL in all cases (creation, load, dirty shutdown recovery). 40 * Includes actions like opening the devices, calculating the expected size and version of metadata, etc. 41 */ 42 static const struct ftl_mngt_process_desc desc_startup = { 43 .name = "FTL startup", 44 .steps = { 45 { 46 .name = "Check configuration", 47 .action = ftl_mngt_check_conf, 48 }, 49 { 50 .name = "Open base bdev", 51 .action = ftl_mngt_open_base_bdev, 52 .cleanup = ftl_mngt_close_base_bdev 53 }, 54 { 55 .name = "Open cache bdev", 56 .action = ftl_mngt_open_cache_bdev, 57 .cleanup = ftl_mngt_close_cache_bdev 58 }, 59 { 60 .name = "Initialize superblock", 61 .action = ftl_mngt_superblock_init, 62 .cleanup = ftl_mngt_superblock_deinit 63 }, 64 { 65 .name = "Initialize memory pools", 66 .action = ftl_mngt_init_mem_pools, 67 .cleanup = ftl_mngt_deinit_mem_pools 68 }, 69 { 70 .name = "Initialize bands", 71 .action = ftl_mngt_init_bands, 72 .cleanup = ftl_mngt_deinit_bands 73 }, 74 { 75 .name = "Register IO device", 76 .action = ftl_mngt_register_io_device, 77 .cleanup = ftl_mngt_unregister_io_device 78 }, 79 { 80 .name = "Initialize core IO channel", 81 .action = ftl_mngt_init_io_channel, 82 .cleanup = ftl_mngt_deinit_io_channel 83 }, 84 { 85 .name = "Decorate bands", 86 .action = ftl_mngt_decorate_bands 87 }, 88 { 89 .name = "Initialize layout", 90 .action = ftl_mngt_init_layout 91 }, 92 { 93 .name = "Verify layout", 94 .action = ftl_mngt_layout_verify, 95 }, 96 { 97 .name = "Upgrade layout", 98 .action = ftl_mngt_layout_upgrade, 99 }, 100 { 101 .name = "Scrub NV cache", 102 .action = ftl_mngt_scrub_nv_cache, 103 }, 104 { 105 .name = "Initialize metadata", 106 .action = ftl_mngt_init_md, 107 .cleanup = ftl_mngt_deinit_md 108 }, 109 { 110 .name = "Initialize band addresses", 111 .action = ftl_mngt_initialize_band_address 112 }, 113 { 114 .name = "Initialize NV cache", 115 .action = ftl_mngt_init_nv_cache, 116 .cleanup = ftl_mngt_deinit_nv_cache 117 }, 118 { 119 .name = "Initialize valid map", 120 .action = ftl_mngt_init_vld_map, 121 .cleanup = ftl_mngt_deinit_vld_map 122 }, 123 { 124 .name = "Initialize trim map", 125 .action = ftl_mngt_init_unmap_map, 126 .cleanup = ftl_mngt_deinit_unmap_map 127 }, 128 { 129 .name = "Initialize bands metadata", 130 .action = ftl_mngt_init_bands_md, 131 .cleanup = ftl_mngt_deinit_bands_md 132 }, 133 { 134 .name = "Initialize reloc", 135 .action = ftl_mngt_init_reloc, 136 .cleanup = ftl_mngt_deinit_reloc 137 }, 138 { 139 .name = "Select startup mode", 140 .action = ftl_mngt_select_startup_mode 141 }, 142 {} 143 } 144 }; 145 146 /* 147 * Steps executed when creating FTL for the first time - most important being scrubbing 148 * old data/metadata (so it's not leaked during dirty shutdown recovery) and laying out 149 * regions for the new metadata (initializing band states, etc). 150 */ 151 static const struct ftl_mngt_process_desc desc_first_start = { 152 .name = "FTL first start", 153 .steps = { 154 { 155 .name = "Initialize L2P", 156 .action = ftl_mngt_init_l2p, 157 .cleanup = ftl_mngt_deinit_l2p 158 }, 159 { 160 .name = "Clear L2P", 161 .action = ftl_mngt_clear_l2p, 162 }, 163 { 164 .name = "Finalize band initialization", 165 .action = ftl_mngt_finalize_init_bands, 166 }, 167 { 168 .name = "Save initial band info metadata", 169 .action = ftl_mngt_persist_band_info_metadata, 170 }, 171 { 172 .name = "Save initial chunk info metadata", 173 .action = ftl_mngt_persist_nv_cache_metadata, 174 }, 175 { 176 .name = "Initialize P2L checkpointing", 177 .action = ftl_mngt_p2l_init_ckpt, 178 .cleanup = ftl_mngt_p2l_deinit_ckpt 179 }, 180 { 181 .name = "Wipe P2L region", 182 .action = ftl_mngt_p2l_wipe, 183 }, 184 { 185 .name = "Clear trim map", 186 .action = ftl_mngt_unmap_clear, 187 }, 188 { 189 .name = "Set FTL dirty state", 190 .action = ftl_mngt_set_dirty, 191 }, 192 { 193 .name = "Start core poller", 194 .action = ftl_mngt_start_core_poller, 195 .cleanup = ftl_mngt_stop_core_poller 196 }, 197 { 198 .name = "Finalize initialization", 199 .action = ftl_mngt_finalize_startup, 200 }, 201 {} 202 } 203 }; 204 205 /* 206 * Step utilized on loading of an FTL instance - decides on dirty/clean shutdown path. 207 */ 208 static const struct ftl_mngt_process_desc desc_restore = { 209 .name = "FTL restore", 210 .steps = { 211 { 212 .name = "Select recovery mode", 213 .action = ftl_mngt_select_restore_mode, 214 }, 215 {} 216 } 217 }; 218 219 /* 220 * Loading of FTL after clean shutdown. 221 */ 222 static const struct ftl_mngt_process_desc desc_clean_start = { 223 .name = "Clean startup", 224 .steps = { 225 { 226 .name = "Restore metadata", 227 .action = ftl_mngt_restore_md 228 }, 229 { 230 .name = "Initialize P2L checkpointing", 231 .action = ftl_mngt_p2l_init_ckpt, 232 .cleanup = ftl_mngt_p2l_deinit_ckpt 233 }, 234 { 235 .name = "Restore P2L checkpoints", 236 .action = ftl_mngt_p2l_restore_ckpt 237 }, 238 { 239 .name = "Initialize L2P", 240 .action = ftl_mngt_init_l2p, 241 .cleanup = ftl_mngt_deinit_l2p 242 }, 243 { 244 .name = "Restore L2P", 245 .action = ftl_mngt_restore_l2p, 246 }, 247 { 248 .name = "Finalize band initialization", 249 .action = ftl_mngt_finalize_init_bands, 250 }, 251 { 252 .name = "Start core poller", 253 .action = ftl_mngt_start_core_poller, 254 .cleanup = ftl_mngt_stop_core_poller 255 }, 256 { 257 .name = "Self test on startup", 258 .action = ftl_mngt_self_test, 259 }, 260 { 261 .name = "Set FTL dirty state", 262 .action = ftl_mngt_set_dirty, 263 }, 264 { 265 .name = "Finalize initialization", 266 .action = ftl_mngt_finalize_startup, 267 }, 268 {} 269 } 270 }; 271 272 int 273 ftl_mngt_call_dev_startup(struct spdk_ftl_dev *dev, ftl_mngt_completion cb, void *cb_cntx) 274 { 275 return ftl_mngt_process_execute(dev, &desc_startup, cb, cb_cntx); 276 } 277 278 struct ftl_unmap_ctx { 279 uint64_t lba; 280 uint64_t num_blocks; 281 spdk_ftl_fn cb_fn; 282 void *cb_arg; 283 struct spdk_thread *thread; 284 int status; 285 }; 286 287 static void 288 ftl_mngt_process_unmap_cb(void *ctx, int status) 289 { 290 struct ftl_mngt_process *mngt = ctx; 291 292 if (status) { 293 ftl_mngt_fail_step(ctx); 294 } else { 295 ftl_mngt_next_step(mngt); 296 } 297 } 298 299 static void 300 ftl_mngt_process_unmap(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 301 { 302 struct ftl_io *io = ftl_mngt_get_process_ctx(mngt); 303 struct ftl_unmap_ctx *ctx = ftl_mngt_get_caller_ctx(mngt); 304 int rc; 305 306 if (!dev->ioch) { 307 ftl_mngt_fail_step(mngt); 308 return; 309 } 310 311 rc = spdk_ftl_unmap(dev, io, dev->ioch, ctx->lba, ctx->num_blocks, ftl_mngt_process_unmap_cb, mngt); 312 if (rc == -EAGAIN) { 313 ftl_mngt_continue_step(mngt); 314 } 315 } 316 317 /* 318 * RPC unmap path. 319 */ 320 static const struct ftl_mngt_process_desc g_desc_unmap = { 321 .name = "FTL unmap", 322 .ctx_size = sizeof(struct ftl_io), 323 .steps = { 324 { 325 .name = "Process unmap", 326 .action = ftl_mngt_process_unmap, 327 }, 328 {} 329 } 330 }; 331 332 static void 333 unmap_user_cb(void *_ctx) 334 { 335 struct ftl_unmap_ctx *ctx = _ctx; 336 337 ctx->cb_fn(ctx->cb_arg, ctx->status); 338 free(ctx); 339 } 340 341 static void 342 ftl_mngt_unmap_cb(struct spdk_ftl_dev *dev, void *_ctx, int status) 343 { 344 struct ftl_unmap_ctx *ctx = _ctx; 345 ctx->status = status; 346 347 if (spdk_thread_send_msg(ctx->thread, unmap_user_cb, ctx)) { 348 ftl_abort(); 349 } 350 } 351 352 int 353 ftl_mngt_unmap(struct spdk_ftl_dev *dev, uint64_t lba, uint64_t num_blocks, spdk_ftl_fn cb, 354 void *cb_cntx) 355 { 356 struct ftl_unmap_ctx *ctx; 357 358 ctx = calloc(1, sizeof(*ctx)); 359 if (ctx == NULL) { 360 return -EAGAIN; 361 } 362 363 ctx->lba = lba; 364 ctx->num_blocks = num_blocks; 365 ctx->cb_fn = cb; 366 ctx->cb_arg = cb_cntx; 367 ctx->thread = spdk_get_thread(); 368 369 return ftl_mngt_process_execute(dev, &g_desc_unmap, ftl_mngt_unmap_cb, ctx); 370 } 371 372 void 373 ftl_mngt_rollback_device(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 374 { 375 ftl_mngt_call_process_rollback(mngt, &desc_startup); 376 } 377