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 : 22 : ftl_mngt_select_startup_mode(struct spdk_ftl_dev *dev,
18 : : struct ftl_mngt_process *mngt)
19 : : {
20 [ + + ]: 22 : if (dev->conf.mode & SPDK_FTL_MODE_CREATE) {
21 : 5 : ftl_mngt_call_process(mngt, &desc_first_start);
22 : : } else {
23 : 17 : ftl_mngt_call_process(mngt, &desc_restore);
24 : : }
25 : 22 : }
26 : :
27 : : static void
28 : 17 : ftl_mngt_select_restore_mode(struct spdk_ftl_dev *dev,
29 : : struct ftl_mngt_process *mngt)
30 : : {
31 [ + + ]: 17 : if (dev->sb->clean) {
32 : 16 : ftl_mngt_call_process(mngt, &desc_clean_start);
33 : : } else {
34 : 1 : ftl_mngt_recover(dev, mngt);
35 : : }
36 : 17 : }
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 = "Initialize metadata",
102 : : .action = ftl_mngt_init_md,
103 : : .cleanup = ftl_mngt_deinit_md
104 : : },
105 : : {
106 : : .name = "Initialize band addresses",
107 : : .action = ftl_mngt_initialize_band_address
108 : : },
109 : : {
110 : : .name = "Initialize NV cache",
111 : : .action = ftl_mngt_init_nv_cache,
112 : : .cleanup = ftl_mngt_deinit_nv_cache
113 : : },
114 : : {
115 : : .name = "Initialize valid map",
116 : : .action = ftl_mngt_init_vld_map,
117 : : .cleanup = ftl_mngt_deinit_vld_map
118 : : },
119 : : {
120 : : .name = "Initialize trim map",
121 : : .action = ftl_mngt_init_unmap_map,
122 : : .cleanup = ftl_mngt_deinit_unmap_map
123 : : },
124 : : {
125 : : .name = "Initialize bands metadata",
126 : : .action = ftl_mngt_init_bands_md,
127 : : .cleanup = ftl_mngt_deinit_bands_md
128 : : },
129 : : {
130 : : .name = "Initialize reloc",
131 : : .action = ftl_mngt_init_reloc,
132 : : .cleanup = ftl_mngt_deinit_reloc
133 : : },
134 : : {
135 : : .name = "Select startup mode",
136 : : .action = ftl_mngt_select_startup_mode
137 : : },
138 : : {}
139 : : }
140 : : };
141 : :
142 : : /*
143 : : * Steps executed when creating FTL for the first time - most important being scrubbing
144 : : * old data/metadata (so it's not leaked during dirty shutdown recovery) and laying out
145 : : * regions for the new metadata (initializing band states, etc).
146 : : */
147 : : static const struct ftl_mngt_process_desc desc_first_start = {
148 : : .name = "FTL first start",
149 : : .steps = {
150 : : {
151 : : .name = "Initialize L2P",
152 : : .action = ftl_mngt_init_l2p,
153 : : .cleanup = ftl_mngt_deinit_l2p
154 : : },
155 : : {
156 : : .name = "Clear L2P",
157 : : .action = ftl_mngt_clear_l2p,
158 : : },
159 : : {
160 : : .name = "Scrub NV cache",
161 : : .action = ftl_mngt_scrub_nv_cache,
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 = "Free P2L region bufs",
190 : : .action = ftl_mngt_p2l_free_bufs,
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 = "Free P2L region bufs",
257 : : .action = ftl_mngt_p2l_free_bufs,
258 : : },
259 : : {
260 : : .name = "Start core poller",
261 : : .action = ftl_mngt_start_core_poller,
262 : : .cleanup = ftl_mngt_stop_core_poller
263 : : },
264 : : {
265 : : .name = "Self test on startup",
266 : : .action = ftl_mngt_self_test,
267 : : },
268 : : {
269 : : .name = "Set FTL dirty state",
270 : : .action = ftl_mngt_set_dirty,
271 : : },
272 : : {
273 : : .name = "Finalize initialization",
274 : : .action = ftl_mngt_finalize_startup,
275 : : },
276 : : {}
277 : : }
278 : : };
279 : :
280 : : int
281 : 22 : ftl_mngt_call_dev_startup(struct spdk_ftl_dev *dev, ftl_mngt_completion cb, void *cb_cntx)
282 : : {
283 : 22 : return ftl_mngt_process_execute(dev, &desc_startup, cb, cb_cntx);
284 : : }
285 : :
286 : : struct ftl_unmap_ctx {
287 : : uint64_t lba;
288 : : uint64_t num_blocks;
289 : : spdk_ftl_fn cb_fn;
290 : : void *cb_arg;
291 : : struct spdk_thread *thread;
292 : : int status;
293 : : };
294 : :
295 : : static void
296 : 4 : ftl_mngt_process_unmap_cb(void *ctx, int status)
297 : : {
298 : 4 : struct ftl_mngt_process *mngt = ctx;
299 : :
300 [ - + ]: 4 : if (status) {
301 : 0 : ftl_mngt_fail_step(ctx);
302 : : } else {
303 : 4 : ftl_mngt_next_step(mngt);
304 : : }
305 : 4 : }
306 : :
307 : : static void
308 : 4 : ftl_mngt_process_unmap(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
309 : : {
310 : 4 : struct ftl_io *io = ftl_mngt_get_process_ctx(mngt);
311 : 4 : struct ftl_unmap_ctx *ctx = ftl_mngt_get_caller_ctx(mngt);
312 : : int rc;
313 : :
314 [ - + ]: 4 : if (!dev->ioch) {
315 : 0 : ftl_mngt_fail_step(mngt);
316 : 0 : return;
317 : : }
318 : :
319 : 4 : rc = spdk_ftl_unmap(dev, io, dev->ioch, ctx->lba, ctx->num_blocks, ftl_mngt_process_unmap_cb, mngt);
320 [ - + ]: 4 : if (rc == -EAGAIN) {
321 : 0 : ftl_mngt_continue_step(mngt);
322 : : }
323 : : }
324 : :
325 : : /*
326 : : * RPC unmap path.
327 : : */
328 : : static const struct ftl_mngt_process_desc g_desc_unmap = {
329 : : .name = "FTL unmap",
330 : : .ctx_size = sizeof(struct ftl_io),
331 : : .steps = {
332 : : {
333 : : .name = "Process unmap",
334 : : .action = ftl_mngt_process_unmap,
335 : : },
336 : : {}
337 : : }
338 : : };
339 : :
340 : : static void
341 : 4 : unmap_user_cb(void *_ctx)
342 : : {
343 : 4 : struct ftl_unmap_ctx *ctx = _ctx;
344 : :
345 : 4 : ctx->cb_fn(ctx->cb_arg, ctx->status);
346 : 4 : free(ctx);
347 : 4 : }
348 : :
349 : : static void
350 : 4 : ftl_mngt_unmap_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
351 : : {
352 : 4 : struct ftl_unmap_ctx *ctx = _ctx;
353 : 4 : ctx->status = status;
354 : :
355 [ - + ]: 4 : if (spdk_thread_send_msg(ctx->thread, unmap_user_cb, ctx)) {
356 : 0 : ftl_abort();
357 : : }
358 : 4 : }
359 : :
360 : : int
361 : 4 : ftl_mngt_unmap(struct spdk_ftl_dev *dev, uint64_t lba, uint64_t num_blocks, spdk_ftl_fn cb,
362 : : void *cb_cntx)
363 : : {
364 : : struct ftl_unmap_ctx *ctx;
365 : :
366 : 4 : ctx = calloc(1, sizeof(*ctx));
367 [ - + ]: 4 : if (ctx == NULL) {
368 : 0 : return -EAGAIN;
369 : : }
370 : :
371 : 4 : ctx->lba = lba;
372 : 4 : ctx->num_blocks = num_blocks;
373 : 4 : ctx->cb_fn = cb;
374 : 4 : ctx->cb_arg = cb_cntx;
375 : 4 : ctx->thread = spdk_get_thread();
376 : :
377 : 4 : return ftl_mngt_process_execute(dev, &g_desc_unmap, ftl_mngt_unmap_cb, ctx);
378 : : }
379 : :
380 : : void
381 : 22 : ftl_mngt_rollback_device(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
382 : : {
383 : 22 : ftl_mngt_call_process_rollback(mngt, &desc_startup);
384 : 22 : }
|