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