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);
22 : } else {
23 0 : ftl_mngt_call_process(mngt, &desc_restore);
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);
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 = "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 0 : ftl_mngt_call_dev_startup(struct spdk_ftl_dev *dev, ftl_mngt_completion cb, void *cb_cntx)
282 : {
283 0 : 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 0 : ftl_mngt_process_unmap_cb(void *ctx, int status)
297 : {
298 0 : struct ftl_mngt_process *mngt = ctx;
299 :
300 0 : if (status) {
301 0 : ftl_mngt_fail_step(ctx);
302 : } else {
303 0 : ftl_mngt_next_step(mngt);
304 : }
305 0 : }
306 :
307 : static void
308 0 : ftl_mngt_process_unmap(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
309 : {
310 0 : struct ftl_io *io = ftl_mngt_get_process_ctx(mngt);
311 0 : struct ftl_unmap_ctx *ctx = ftl_mngt_get_caller_ctx(mngt);
312 : int rc;
313 :
314 0 : if (!dev->ioch) {
315 0 : ftl_mngt_fail_step(mngt);
316 0 : return;
317 : }
318 :
319 0 : rc = spdk_ftl_unmap(dev, io, dev->ioch, ctx->lba, ctx->num_blocks, ftl_mngt_process_unmap_cb, mngt);
320 0 : 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 0 : unmap_user_cb(void *_ctx)
342 : {
343 0 : struct ftl_unmap_ctx *ctx = _ctx;
344 :
345 0 : ctx->cb_fn(ctx->cb_arg, ctx->status);
346 0 : free(ctx);
347 0 : }
348 :
349 : static void
350 0 : ftl_mngt_unmap_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
351 : {
352 0 : struct ftl_unmap_ctx *ctx = _ctx;
353 0 : ctx->status = status;
354 :
355 0 : if (spdk_thread_send_msg(ctx->thread, unmap_user_cb, ctx)) {
356 0 : ftl_abort();
357 : }
358 0 : }
359 :
360 : int
361 0 : 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 0 : ctx = calloc(1, sizeof(*ctx));
367 0 : if (ctx == NULL) {
368 0 : return -EAGAIN;
369 : }
370 :
371 0 : ctx->lba = lba;
372 0 : ctx->num_blocks = num_blocks;
373 0 : ctx->cb_fn = cb;
374 0 : ctx->cb_arg = cb_cntx;
375 0 : ctx->thread = spdk_get_thread();
376 :
377 0 : return ftl_mngt_process_execute(dev, &g_desc_unmap, ftl_mngt_unmap_cb, ctx);
378 : }
379 :
380 : void
381 0 : ftl_mngt_rollback_device(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
382 : {
383 0 : ftl_mngt_call_process_rollback(mngt, &desc_startup);
384 0 : }
|