xref: /spdk/lib/ftl/mngt/ftl_mngt_startup.c (revision 95d6c9fac17572b107042103439aafd696d60b0e)
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, NULL);
22 	} else {
23 		ftl_mngt_call_process(mngt, &desc_restore, NULL);
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, NULL);
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_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 = "Wipe P2L Log IO region",
186 			.action = ftl_mngt_p2l_log_io_wipe,
187 		},
188 		{
189 			.name = "Clear trim map",
190 			.action = ftl_mngt_trim_metadata_clear,
191 		},
192 		{
193 			.name = "Clear trim log",
194 			.action = ftl_mngt_trim_log_clear,
195 		},
196 		{
197 			.name = "Set FTL dirty state",
198 			.action = ftl_mngt_set_dirty,
199 		},
200 		{
201 			.name = "Start core poller",
202 			.action = ftl_mngt_start_core_poller,
203 			.cleanup = ftl_mngt_stop_core_poller
204 		},
205 		{
206 			.name = "Finalize initialization",
207 			.action = ftl_mngt_finalize_startup,
208 		},
209 		{}
210 	}
211 };
212 
213 /*
214  * Step utilized on loading of an FTL instance - decides on dirty/clean shutdown path.
215  */
216 static const struct ftl_mngt_process_desc desc_restore = {
217 	.name = "FTL restore",
218 	.steps = {
219 		{
220 			.name = "Select recovery mode",
221 			.action = ftl_mngt_select_restore_mode,
222 		},
223 		{}
224 	}
225 };
226 
227 /*
228  * Loading of FTL after clean shutdown.
229  */
230 static const struct ftl_mngt_process_desc desc_clean_start = {
231 	.name = "Clean startup",
232 	.steps = {
233 		{
234 			.name = "Restore metadata",
235 			.action = ftl_mngt_restore_md
236 		},
237 		{
238 			.name = "Initialize P2L checkpointing",
239 			.action = ftl_mngt_p2l_init_ckpt,
240 			.cleanup = ftl_mngt_p2l_deinit_ckpt
241 		},
242 		{
243 			.name = "Restore P2L checkpoints",
244 			.action = ftl_mngt_p2l_restore_ckpt
245 		},
246 		{
247 			.name = "Initialize L2P",
248 			.action = ftl_mngt_init_l2p,
249 			.cleanup = ftl_mngt_deinit_l2p
250 		},
251 		{
252 			.name = "Restore L2P",
253 			.action = ftl_mngt_restore_l2p,
254 		},
255 		{
256 			.name = "Finalize band initialization",
257 			.action = ftl_mngt_finalize_init_bands,
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_trim_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_trim_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_trim(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_trim_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_trim_cb, mngt);
320 	if (rc == -EAGAIN) {
321 		ftl_mngt_continue_step(mngt);
322 	}
323 }
324 
325 /*
326  * RPC trim path.
327  */
328 static const struct ftl_mngt_process_desc g_desc_trim = {
329 	.name = "FTL trim",
330 	.ctx_size = sizeof(struct ftl_io),
331 	.steps = {
332 		{
333 			.name = "Process trim",
334 			.action = ftl_mngt_process_trim,
335 		},
336 		{}
337 	}
338 };
339 
340 static void
341 trim_user_cb(void *_ctx)
342 {
343 	struct ftl_trim_ctx *ctx = _ctx;
344 
345 	ctx->cb_fn(ctx->cb_arg, ctx->status);
346 	free(ctx);
347 }
348 
349 static void
350 ftl_mngt_trim_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
351 {
352 	struct ftl_trim_ctx *ctx = _ctx;
353 	ctx->status = status;
354 
355 	if (spdk_thread_send_msg(ctx->thread, trim_user_cb, ctx)) {
356 		ftl_abort();
357 	}
358 }
359 
360 int
361 ftl_mngt_trim(struct spdk_ftl_dev *dev, uint64_t lba, uint64_t num_blocks, spdk_ftl_fn cb,
362 	      void *cb_cntx)
363 {
364 	struct ftl_trim_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_trim, ftl_mngt_trim_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