xref: /spdk/lib/ftl/mngt/ftl_mngt_startup.c (revision 4061ed111c296d0f508ddfd75d09052b9acd6d72)
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