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_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 : 0 : ftl_mngt_select_startup_mode(struct spdk_ftl_dev *dev,
18 : : struct ftl_mngt_process *mngt)
19 : : {
20 [ # # ]: 0 : if (dev->conf.mode & SPDK_FTL_MODE_CREATE) {
21 : 0 : ftl_mngt_call_process(mngt, &desc_first_start, NULL);
22 : : } else {
23 : 0 : ftl_mngt_call_process(mngt, &desc_restore, NULL);
24 : : }
25 : 0 : }
26 : :
27 : : static void
28 : 0 : ftl_mngt_select_restore_mode(struct spdk_ftl_dev *dev,
29 : : struct ftl_mngt_process *mngt)
30 : : {
31 [ # # ]: 0 : if (dev->sb->clean) {
32 : 0 : ftl_mngt_call_process(mngt, &desc_clean_start, NULL);
33 : : } else {
34 : 0 : ftl_mngt_recover(dev, mngt);
35 : : }
36 : 0 : }
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_trim_map,
126 : : .cleanup = ftl_mngt_deinit_trim_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_trim_metadata_clear,
187 : : },
188 : : {
189 : : .name = "Clear trim log",
190 : : .action = ftl_mngt_trim_log_clear,
191 : : },
192 : : {
193 : : .name = "Set FTL dirty state",
194 : : .action = ftl_mngt_set_dirty,
195 : : },
196 : : {
197 : : .name = "Start core poller",
198 : : .action = ftl_mngt_start_core_poller,
199 : : .cleanup = ftl_mngt_stop_core_poller
200 : : },
201 : : {
202 : : .name = "Finalize initialization",
203 : : .action = ftl_mngt_finalize_startup,
204 : : },
205 : : {}
206 : : }
207 : : };
208 : :
209 : : /*
210 : : * Step utilized on loading of an FTL instance - decides on dirty/clean shutdown path.
211 : : */
212 : : static const struct ftl_mngt_process_desc desc_restore = {
213 : : .name = "FTL restore",
214 : : .steps = {
215 : : {
216 : : .name = "Select recovery mode",
217 : : .action = ftl_mngt_select_restore_mode,
218 : : },
219 : : {}
220 : : }
221 : : };
222 : :
223 : : /*
224 : : * Loading of FTL after clean shutdown.
225 : : */
226 : : static const struct ftl_mngt_process_desc desc_clean_start = {
227 : : .name = "Clean startup",
228 : : .steps = {
229 : : {
230 : : .name = "Restore metadata",
231 : : .action = ftl_mngt_restore_md
232 : : },
233 : : {
234 : : .name = "Initialize P2L checkpointing",
235 : : .action = ftl_mngt_p2l_init_ckpt,
236 : : .cleanup = ftl_mngt_p2l_deinit_ckpt
237 : : },
238 : : {
239 : : .name = "Restore P2L checkpoints",
240 : : .action = ftl_mngt_p2l_restore_ckpt
241 : : },
242 : : {
243 : : .name = "Initialize L2P",
244 : : .action = ftl_mngt_init_l2p,
245 : : .cleanup = ftl_mngt_deinit_l2p
246 : : },
247 : : {
248 : : .name = "Restore L2P",
249 : : .action = ftl_mngt_restore_l2p,
250 : : },
251 : : {
252 : : .name = "Finalize band initialization",
253 : : .action = ftl_mngt_finalize_init_bands,
254 : : },
255 : : {
256 : : .name = "Start core poller",
257 : : .action = ftl_mngt_start_core_poller,
258 : : .cleanup = ftl_mngt_stop_core_poller
259 : : },
260 : : {
261 : : .name = "Self test on startup",
262 : : .action = ftl_mngt_self_test,
263 : : },
264 : : {
265 : : .name = "Set FTL dirty state",
266 : : .action = ftl_mngt_set_dirty,
267 : : },
268 : : {
269 : : .name = "Finalize initialization",
270 : : .action = ftl_mngt_finalize_startup,
271 : : },
272 : : {}
273 : : }
274 : : };
275 : :
276 : : int
277 : 0 : ftl_mngt_call_dev_startup(struct spdk_ftl_dev *dev, ftl_mngt_completion cb, void *cb_cntx)
278 : : {
279 : 0 : return ftl_mngt_process_execute(dev, &desc_startup, cb, cb_cntx);
280 : : }
281 : :
282 : : struct ftl_trim_ctx {
283 : : uint64_t lba;
284 : : uint64_t num_blocks;
285 : : spdk_ftl_fn cb_fn;
286 : : void *cb_arg;
287 : : struct spdk_thread *thread;
288 : : int status;
289 : : };
290 : :
291 : : static void
292 : 0 : ftl_mngt_process_trim_cb(void *ctx, int status)
293 : : {
294 : 0 : struct ftl_mngt_process *mngt = ctx;
295 : :
296 [ # # ]: 0 : if (status) {
297 : 0 : ftl_mngt_fail_step(ctx);
298 : : } else {
299 : 0 : ftl_mngt_next_step(mngt);
300 : : }
301 : 0 : }
302 : :
303 : : static void
304 : 0 : ftl_mngt_process_trim(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
305 : : {
306 : 0 : struct ftl_io *io = ftl_mngt_get_process_ctx(mngt);
307 : 0 : struct ftl_trim_ctx *ctx = ftl_mngt_get_caller_ctx(mngt);
308 : : int rc;
309 : :
310 [ # # ]: 0 : if (!dev->ioch) {
311 : 0 : ftl_mngt_fail_step(mngt);
312 : 0 : return;
313 : : }
314 : :
315 : 0 : rc = spdk_ftl_unmap(dev, io, dev->ioch, ctx->lba, ctx->num_blocks, ftl_mngt_process_trim_cb, mngt);
316 [ # # ]: 0 : if (rc == -EAGAIN) {
317 : 0 : ftl_mngt_continue_step(mngt);
318 : : }
319 : : }
320 : :
321 : : /*
322 : : * RPC trim path.
323 : : */
324 : : static const struct ftl_mngt_process_desc g_desc_trim = {
325 : : .name = "FTL trim",
326 : : .ctx_size = sizeof(struct ftl_io),
327 : : .steps = {
328 : : {
329 : : .name = "Process trim",
330 : : .action = ftl_mngt_process_trim,
331 : : },
332 : : {}
333 : : }
334 : : };
335 : :
336 : : static void
337 : 0 : trim_user_cb(void *_ctx)
338 : : {
339 : 0 : struct ftl_trim_ctx *ctx = _ctx;
340 : :
341 : 0 : ctx->cb_fn(ctx->cb_arg, ctx->status);
342 : 0 : free(ctx);
343 : 0 : }
344 : :
345 : : static void
346 : 0 : ftl_mngt_trim_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
347 : : {
348 : 0 : struct ftl_trim_ctx *ctx = _ctx;
349 : 0 : ctx->status = status;
350 : :
351 [ # # ]: 0 : if (spdk_thread_send_msg(ctx->thread, trim_user_cb, ctx)) {
352 : 0 : ftl_abort();
353 : : }
354 : 0 : }
355 : :
356 : : int
357 : 0 : ftl_mngt_trim(struct spdk_ftl_dev *dev, uint64_t lba, uint64_t num_blocks, spdk_ftl_fn cb,
358 : : void *cb_cntx)
359 : : {
360 : : struct ftl_trim_ctx *ctx;
361 : :
362 : 0 : ctx = calloc(1, sizeof(*ctx));
363 [ # # ]: 0 : if (ctx == NULL) {
364 : 0 : return -EAGAIN;
365 : : }
366 : :
367 : 0 : ctx->lba = lba;
368 : 0 : ctx->num_blocks = num_blocks;
369 : 0 : ctx->cb_fn = cb;
370 : 0 : ctx->cb_arg = cb_cntx;
371 : 0 : ctx->thread = spdk_get_thread();
372 : :
373 : 0 : return ftl_mngt_process_execute(dev, &g_desc_trim, ftl_mngt_trim_cb, ctx);
374 : : }
375 : :
376 : : void
377 : 0 : ftl_mngt_rollback_device(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
378 : : {
379 : 0 : ftl_mngt_call_process_rollback(mngt, &desc_startup);
380 : 0 : }
|