1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "ftl_core.h" 7 #include "ftl_mngt.h" 8 #include "ftl_mngt_steps.h" 9 10 static const struct ftl_mngt_process_desc desc_startup; 11 static const struct ftl_mngt_process_desc desc_first_start; 12 static const struct ftl_mngt_process_desc desc_restore; 13 static const struct ftl_mngt_process_desc desc_clean_start; 14 15 static void 16 ftl_mngt_select_startup_mode(struct spdk_ftl_dev *dev, 17 struct ftl_mngt_process *mngt) 18 { 19 if (dev->conf.mode & SPDK_FTL_MODE_CREATE) { 20 ftl_mngt_call_process(mngt, &desc_first_start); 21 } else { 22 ftl_mngt_call_process(mngt, &desc_restore); 23 } 24 } 25 26 static void 27 ftl_mngt_select_restore_mode(struct spdk_ftl_dev *dev, 28 struct ftl_mngt_process *mngt) 29 { 30 if (dev->sb->clean) { 31 ftl_mngt_call_process(mngt, &desc_clean_start); 32 } else { 33 ftl_mngt_recover(dev, mngt); 34 } 35 } 36 37 /* 38 * Common startup steps required by FTL in all cases (creation, load, dirty shutdown recovery). 39 * Includes actions like opening the devices, calculating the expected size and version of metadata, etc. 40 */ 41 static const struct ftl_mngt_process_desc desc_startup = { 42 .name = "FTL startup", 43 .steps = { 44 { 45 .name = "Check configuration", 46 .action = ftl_mngt_check_conf, 47 }, 48 { 49 .name = "Open base bdev", 50 .action = ftl_mngt_open_base_bdev, 51 .cleanup = ftl_mngt_close_base_bdev 52 }, 53 { 54 .name = "Open cache bdev", 55 .action = ftl_mngt_open_cache_bdev, 56 .cleanup = ftl_mngt_close_cache_bdev 57 }, 58 #ifdef SPDK_FTL_VSS_EMU 59 { 60 .name = "Initialize VSS emu", 61 .action = ftl_mngt_md_init_vss_emu, 62 .cleanup = ftl_mngt_md_deinit_vss_emu 63 }, 64 #endif 65 { 66 .name = "Initialize superblock", 67 .action = ftl_mngt_superblock_init, 68 .cleanup = ftl_mngt_superblock_deinit 69 }, 70 { 71 .name = "Initialize memory pools", 72 .action = ftl_mngt_init_mem_pools, 73 .cleanup = ftl_mngt_deinit_mem_pools 74 }, 75 { 76 .name = "Initialize bands", 77 .action = ftl_mngt_init_bands, 78 .cleanup = ftl_mngt_deinit_bands 79 }, 80 { 81 .name = "Register IO device", 82 .action = ftl_mngt_register_io_device, 83 .cleanup = ftl_mngt_unregister_io_device 84 }, 85 { 86 .name = "Initialize core IO channel", 87 .action = ftl_mngt_init_io_channel, 88 .cleanup = ftl_mngt_deinit_io_channel 89 }, 90 { 91 .name = "Decorate bands", 92 .action = ftl_mngt_decorate_bands 93 }, 94 { 95 .name = "Initialize layout", 96 .action = ftl_mngt_init_layout 97 }, 98 { 99 .name = "Initialize metadata", 100 .action = ftl_mngt_init_md, 101 .cleanup = ftl_mngt_deinit_md 102 }, 103 { 104 .name = "Initialize NV cache", 105 .action = ftl_mngt_init_nv_cache, 106 .cleanup = ftl_mngt_deinit_nv_cache 107 }, 108 { 109 .name = "Initialize valid map", 110 .action = ftl_mngt_init_vld_map, 111 .cleanup = ftl_mngt_deinit_vld_map 112 }, 113 { 114 .name = "Initialize bands metadata", 115 .action = ftl_mngt_init_bands_md, 116 .cleanup = ftl_mngt_deinit_bands_md 117 }, 118 { 119 .name = "Initialize reloc", 120 .action = ftl_mngt_init_reloc, 121 .cleanup = ftl_mngt_deinit_reloc 122 }, 123 { 124 .name = "Select startup mode", 125 .action = ftl_mngt_select_startup_mode 126 }, 127 {} 128 } 129 }; 130 131 /* 132 * Steps executed when creating FTL for the first time - most important being scrubbing 133 * old data/metadata (so it's not leaked during dirty shutdown recovery) and laying out 134 * regions for the new metadata (initializing band states, etc). 135 */ 136 static const struct ftl_mngt_process_desc desc_first_start = { 137 .name = "FTL first start", 138 .steps = { 139 { 140 .name = "Initialize L2P", 141 .action = ftl_mngt_init_l2p, 142 .cleanup = ftl_mngt_deinit_l2p 143 }, 144 { 145 .name = "Clear L2P", 146 .action = ftl_mngt_clear_l2p, 147 .cleanup = ftl_mngt_clear_l2p 148 }, 149 { 150 .name = "Scrub NV cache", 151 .action = ftl_mngt_scrub_nv_cache, 152 }, 153 { 154 .name = "Finalize band initialization", 155 .action = ftl_mngt_finalize_init_bands, 156 }, 157 { 158 .name = "Save initial band info metadata", 159 .action = ftl_mngt_persist_band_info_metadata, 160 }, 161 { 162 .name = "Save initial chunk info metadata", 163 .action = ftl_mngt_persist_nv_cache_metadata, 164 }, 165 { 166 .name = "Initialize P2L checkpointing", 167 .action = ftl_mngt_p2l_init_ckpt, 168 .cleanup = ftl_mngt_p2l_deinit_ckpt 169 }, 170 { 171 .name = "Wipe P2L region", 172 .action = ftl_mngt_p2l_wipe, 173 }, 174 { 175 .name = "Free P2L region bufs", 176 .action = ftl_mngt_p2l_free_bufs, 177 }, 178 { 179 .name = "Set FTL dirty state", 180 .action = ftl_mngt_set_dirty, 181 }, 182 { 183 .name = "Start core poller", 184 .action = ftl_mngt_start_core_poller, 185 .cleanup = ftl_mngt_stop_core_poller 186 }, 187 { 188 .name = "Finalize initialization", 189 .action = ftl_mngt_finalize_startup, 190 }, 191 {} 192 } 193 }; 194 195 /* 196 * Step utilized on loading of an FTL instance - decides on dirty/clean shutdown path. 197 */ 198 static const struct ftl_mngt_process_desc desc_restore = { 199 .name = "FTL restore", 200 .steps = { 201 { 202 .name = "Select recovery mode", 203 .action = ftl_mngt_select_restore_mode, 204 }, 205 {} 206 } 207 }; 208 209 /* 210 * Loading of FTL after clean shutdown. 211 */ 212 static const struct ftl_mngt_process_desc desc_clean_start = { 213 .name = "Clean startup", 214 .steps = { 215 { 216 .name = "Restore metadata", 217 .action = ftl_mngt_restore_md 218 }, 219 { 220 .name = "Initialize P2L checkpointing", 221 .action = ftl_mngt_p2l_init_ckpt, 222 .cleanup = ftl_mngt_p2l_deinit_ckpt 223 }, 224 { 225 .name = "Restore P2L checkpoints", 226 .action = ftl_mngt_p2l_restore_ckpt 227 }, 228 { 229 .name = "Initialize L2P", 230 .action = ftl_mngt_init_l2p, 231 .cleanup = ftl_mngt_deinit_l2p 232 }, 233 { 234 .name = "Restore L2P", 235 .action = ftl_mngt_restore_l2p, 236 }, 237 { 238 .name = "Finalize band initialization", 239 .action = ftl_mngt_finalize_init_bands, 240 }, 241 { 242 .name = "Free P2L region bufs", 243 .action = ftl_mngt_p2l_free_bufs, 244 }, 245 { 246 .name = "Start core poller", 247 .action = ftl_mngt_start_core_poller, 248 .cleanup = ftl_mngt_stop_core_poller 249 }, 250 { 251 .name = "Self test on startup", 252 .action = ftl_mngt_self_test, 253 }, 254 { 255 .name = "Set FTL dirty state", 256 .action = ftl_mngt_set_dirty, 257 }, 258 { 259 .name = "Finalize initialization", 260 .action = ftl_mngt_finalize_startup, 261 }, 262 {} 263 } 264 }; 265 266 int 267 ftl_mngt_call_dev_startup(struct spdk_ftl_dev *dev, ftl_mngt_completion cb, void *cb_cntx) 268 { 269 return ftl_mngt_process_execute(dev, &desc_startup, cb, cb_cntx); 270 } 271 272 void 273 ftl_mngt_rollback_device(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 274 { 275 ftl_mngt_call_process_rollback(mngt, &desc_startup); 276 } 277