xref: /spdk/lib/ftl/mngt/ftl_mngt_md.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 "spdk/thread.h"
8 #include "spdk/crc32.h"
9 #include "spdk/string.h"
10 
11 #include "ftl_core.h"
12 #include "ftl_mngt.h"
13 #include "ftl_mngt_steps.h"
14 #include "ftl_utils.h"
15 #include "ftl_band.h"
16 #include "ftl_internal.h"
17 #include "ftl_sb.h"
18 #include "base/ftl_base_dev.h"
19 #include "nvc/ftl_nvc_dev.h"
20 #include "upgrade/ftl_layout_upgrade.h"
21 #include "upgrade/ftl_sb_upgrade.h"
22 
23 void
24 ftl_mngt_init_layout(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
25 {
26 	if (ftl_layout_setup(dev)) {
27 		ftl_mngt_fail_step(mngt);
28 	} else {
29 		ftl_mngt_next_step(mngt);
30 	}
31 }
32 
33 static bool
34 is_buffer_needed(enum ftl_layout_region_type type)
35 {
36 	switch (type) {
37 	case FTL_LAYOUT_REGION_TYPE_SB:
38 	case FTL_LAYOUT_REGION_TYPE_SB_BASE:
39 	case FTL_LAYOUT_REGION_TYPE_DATA_NVC:
40 	case FTL_LAYOUT_REGION_TYPE_DATA_BASE:
41 	case FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR:
42 	case FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR:
43 #ifndef SPDK_FTL_L2P_FLAT
44 	case FTL_LAYOUT_REGION_TYPE_L2P:
45 #endif
46 	case FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR:
47 		return false;
48 
49 	default:
50 		return true;
51 	}
52 }
53 
54 void
55 ftl_mngt_init_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
56 {
57 	struct ftl_layout *layout = &dev->layout;
58 	struct ftl_layout_region *region;
59 	struct ftl_md *md, *md_mirror;
60 	enum ftl_layout_region_type i;
61 	int md_flags;
62 
63 	for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++) {
64 		region = ftl_layout_region_get(dev, i);
65 		if (!region) {
66 			continue;
67 		}
68 		assert(i == region->type);
69 		if (layout->md[i]) {
70 			/*
71 			 * Some metadata objects are initialized by other FTL
72 			 * components. At the moment it's only used by superblock (and its mirror) -
73 			 * during load time we need to read it earlier in order to get the layout for the
74 			 * other regions.
75 			 */
76 			continue;
77 		}
78 		md_flags = is_buffer_needed(i) ? ftl_md_create_region_flags(dev,
79 				region->type) : FTL_MD_CREATE_NO_MEM;
80 		layout->md[i] = ftl_md_create(dev, region->current.blocks, region->vss_blksz, region->name,
81 					      md_flags, region);
82 		if (NULL == layout->md[i]) {
83 			ftl_mngt_fail_step(mngt);
84 			return;
85 		}
86 	}
87 
88 	/* Initialize mirror regions */
89 	for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++) {
90 		region = ftl_layout_region_get(dev, i);
91 		if (!region) {
92 			continue;
93 		}
94 		assert(i == region->type);
95 		if (region->mirror_type != FTL_LAYOUT_REGION_TYPE_INVALID &&
96 		    !is_buffer_needed(region->mirror_type)) {
97 			md = layout->md[i];
98 			md_mirror = layout->md[region->mirror_type];
99 
100 			md_mirror->dev = md->dev;
101 			md_mirror->data_blocks = md->data_blocks;
102 			md_mirror->data = md->data;
103 			if (md_mirror->region->vss_blksz == md->region->vss_blksz) {
104 				md_mirror->vss_data = md->vss_data;
105 			}
106 			md_mirror->region = ftl_layout_region_get(dev, region->mirror_type);
107 			ftl_bug(md_mirror->region == NULL);
108 			md_mirror->is_mirror = true;
109 		}
110 	}
111 
112 	ftl_mngt_next_step(mngt);
113 }
114 
115 void
116 ftl_mngt_deinit_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
117 {
118 	struct ftl_layout *layout = &dev->layout;
119 	struct ftl_layout_region *region;
120 	enum ftl_layout_region_type i;
121 
122 	for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++) {
123 		region = ftl_layout_region_get(dev, i);
124 		if (!region) {
125 			continue;
126 		}
127 		if (layout->md[i]) {
128 			ftl_md_destroy(layout->md[i], ftl_md_destroy_region_flags(dev, region->type));
129 			layout->md[i] = NULL;
130 		}
131 	}
132 
133 	ftl_mngt_next_step(mngt);
134 }
135 
136 static void
137 persist_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status)
138 {
139 	struct ftl_mngt_process *mngt = md->owner.cb_ctx;
140 
141 	if (status) {
142 		ftl_mngt_fail_step(mngt);
143 	} else {
144 		ftl_mngt_next_step(mngt);
145 	}
146 }
147 
148 static void
149 persist(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt,
150 	enum ftl_layout_region_type type)
151 {
152 	struct ftl_layout *layout = &dev->layout;
153 	struct ftl_md *md;
154 
155 	assert(type < FTL_LAYOUT_REGION_TYPE_MAX);
156 
157 	md = layout->md[type];
158 	if (!md) {
159 		ftl_mngt_fail_step(mngt);
160 		return;
161 	}
162 
163 	md->owner.cb_ctx = mngt;
164 	md->cb = persist_cb;
165 	ftl_md_persist(md);
166 }
167 
168 static int
169 ftl_md_restore_region(struct spdk_ftl_dev *dev, int region_type)
170 {
171 	int status = 0;
172 	switch (region_type) {
173 	case FTL_LAYOUT_REGION_TYPE_NVC_MD:
174 		status = ftl_nv_cache_load_state(&dev->nv_cache);
175 		break;
176 	case FTL_LAYOUT_REGION_TYPE_VALID_MAP:
177 		ftl_valid_map_load_state(dev);
178 		break;
179 	case FTL_LAYOUT_REGION_TYPE_BAND_MD:
180 		ftl_bands_load_state(dev);
181 		break;
182 	default:
183 		break;
184 	}
185 	return status;
186 }
187 
188 static void
189 restore_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status)
190 {
191 	struct ftl_mngt_process *mngt = md->owner.cb_ctx;
192 	const struct ftl_layout_region *region = ftl_md_get_region(md);
193 
194 	if (status) {
195 		/* Restore error, end step */
196 		ftl_mngt_fail_step(mngt);
197 		return;
198 	}
199 
200 	assert(region);
201 	status = ftl_md_restore_region(dev, region->type);
202 
203 	if (status) {
204 		ftl_mngt_fail_step(mngt);
205 	} else {
206 		ftl_mngt_next_step(mngt);
207 	}
208 }
209 
210 static void
211 restore(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt, enum ftl_layout_region_type type)
212 {
213 	struct ftl_layout *layout = &dev->layout;
214 	assert(type < FTL_LAYOUT_REGION_TYPE_MAX);
215 	struct ftl_md *md = layout->md[type];
216 
217 	if (!md) {
218 		ftl_mngt_fail_step(mngt);
219 		return;
220 	}
221 
222 	md->owner.cb_ctx = mngt;
223 	md->cb = restore_cb;
224 	ftl_md_restore(md);
225 }
226 
227 void
228 ftl_mngt_persist_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
229 {
230 	if (ftl_nv_cache_save_state(&dev->nv_cache)) {
231 		ftl_mngt_fail_step(mngt);
232 		return;
233 	}
234 
235 	persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_NVC_MD);
236 }
237 
238 static void
239 ftl_mngt_fast_persist_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
240 {
241 	if (ftl_nv_cache_save_state(&dev->nv_cache)) {
242 		ftl_mngt_fail_step(mngt);
243 		return;
244 	}
245 	ftl_mngt_next_step(mngt);
246 }
247 
248 static void
249 ftl_mngt_persist_vld_map_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
250 {
251 	persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_VALID_MAP);
252 }
253 
254 static void
255 ftl_mngt_persist_p2l_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
256 {
257 	/* Sync runtime P2L to persist any invalidation that may have happened */
258 
259 	struct ftl_p2l_sync_ctx *ctx = ftl_mngt_get_step_ctx(mngt);
260 
261 	/*
262 	 * ftl_mngt_persist_bands_p2l will increment the md_region before the step_continue for next regions
263 	 */
264 	if (ctx->md_region <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN) {
265 		ctx->md_region = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN;
266 	}
267 	ftl_mngt_persist_bands_p2l(mngt);
268 }
269 
270 void
271 ftl_mngt_persist_band_info_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
272 {
273 	persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_BAND_MD);
274 }
275 
276 static void
277 ftl_mngt_persist_trim_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
278 {
279 	persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_TRIM_MD);
280 }
281 
282 static uint32_t
283 get_sb_crc(struct ftl_superblock *sb)
284 {
285 	uint32_t crc = 0;
286 
287 	/* Calculate CRC excluding CRC field in superblock */
288 	void *buffer = sb;
289 	size_t offset = offsetof(struct ftl_superblock, header.crc);
290 	size_t size = offset;
291 	crc = spdk_crc32c_update(buffer, size, crc);
292 
293 	buffer += offset + sizeof(sb->header.crc);
294 	if (sb->header.version > FTL_SB_VERSION_2) {
295 		/* whole buf for v3 and on: */
296 		size = FTL_SUPERBLOCK_SIZE - offset - sizeof(sb->header.crc);
297 		crc = spdk_crc32c_update(buffer, size, crc);
298 	} else {
299 		/* special for sb v2 only: */
300 		size = sizeof(struct ftl_superblock_v2) - offset - sizeof(sb->header.crc);
301 		sb->header.crc = spdk_crc32c_update(buffer, size, crc);
302 	}
303 
304 	return crc;
305 }
306 
307 static void
308 ftl_mngt_persist_super_block(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
309 {
310 	dev->sb->overprovisioning = dev->conf.overprovisioning;
311 	dev->sb->gc_info = dev->sb_shm->gc_info;
312 	dev->sb->header.crc = get_sb_crc(dev->sb);
313 	persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB);
314 }
315 
316 /*
317  * Persists all necessary metadata (band state, P2L, etc) during FTL's clean shutdown.
318  */
319 static const struct ftl_mngt_process_desc desc_persist = {
320 	.name = "Persist metadata",
321 	.steps = {
322 		{
323 			.name = "Persist NV cache metadata",
324 			.action = ftl_mngt_persist_nv_cache_metadata,
325 		},
326 		{
327 			.name = "Persist valid map metadata",
328 			.action = ftl_mngt_persist_vld_map_metadata,
329 		},
330 		{
331 			.name = "Persist P2L metadata",
332 			.action = ftl_mngt_persist_p2l_metadata,
333 			.ctx_size = sizeof(struct ftl_p2l_sync_ctx),
334 		},
335 		{
336 			.name = "persist band info metadata",
337 			.action = ftl_mngt_persist_band_info_metadata,
338 		},
339 		{
340 			.name = "persist trim metadata",
341 			.action = ftl_mngt_persist_trim_metadata,
342 		},
343 		{
344 			.name = "Persist superblock",
345 			.action = ftl_mngt_persist_super_block,
346 		},
347 		{}
348 	}
349 };
350 
351 void
352 ftl_mngt_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
353 {
354 	ftl_mngt_call_process(mngt, &desc_persist);
355 }
356 
357 /*
358  * Fast clean shutdown path - skips the persistence of most metadata regions and
359  * relies on their shared memory state instead.
360  */
361 static const struct ftl_mngt_process_desc desc_fast_persist = {
362 	.name = "Fast persist metadata",
363 	.steps = {
364 		{
365 			.name = "Fast persist NV cache metadata",
366 			.action = ftl_mngt_fast_persist_nv_cache_metadata,
367 		},
368 		{}
369 	}
370 };
371 
372 void
373 ftl_mngt_fast_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
374 {
375 	ftl_mngt_call_process(mngt, &desc_fast_persist);
376 }
377 
378 void
379 ftl_mngt_init_default_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
380 {
381 	struct ftl_superblock *sb = dev->sb;
382 
383 	sb->header.magic = FTL_SUPERBLOCK_MAGIC;
384 	sb->header.version = FTL_SB_VERSION_CURRENT;
385 	sb->uuid = dev->conf.uuid;
386 	sb->clean = 0;
387 	dev->sb_shm->shm_clean = false;
388 	sb->ckpt_seq_id = 0;
389 
390 	/* Max 16 IO depth per band relocate */
391 	sb->max_reloc_qdepth = 16;
392 
393 	sb->overprovisioning = dev->conf.overprovisioning;
394 
395 	ftl_band_init_gc_iter(dev);
396 
397 	/* md layout isn't initialized yet.
398 	 * empty region list => all regions in the default location */
399 	spdk_strcpy_pad(sb->base_dev_name, dev->base_type->name,
400 			SPDK_COUNTOF(sb->base_dev_name), '\0');
401 	sb->md_layout_base.df_id = FTL_DF_OBJ_ID_INVALID;
402 
403 	spdk_strcpy_pad(sb->nvc_dev_name, dev->nv_cache.nvc_desc->name,
404 			SPDK_COUNTOF(sb->nvc_dev_name), '\0');
405 	sb->md_layout_nvc.df_id = FTL_DF_OBJ_ID_INVALID;
406 
407 	sb->header.crc = get_sb_crc(sb);
408 
409 	ftl_mngt_next_step(mngt);
410 }
411 
412 void
413 ftl_mngt_set_dirty(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
414 {
415 	struct ftl_superblock *sb = dev->sb;
416 
417 	sb->clean = 0;
418 	sb->upgrade_ready = false;
419 	dev->sb_shm->shm_clean = false;
420 	sb->header.crc = get_sb_crc(sb);
421 	persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB);
422 }
423 
424 void
425 ftl_mngt_set_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
426 {
427 	struct ftl_superblock *sb = dev->sb;
428 
429 	sb->clean = 1;
430 	sb->upgrade_ready = dev->conf.prep_upgrade_on_shutdown;
431 	dev->sb_shm->shm_clean = false;
432 	sb->header.crc = get_sb_crc(sb);
433 	persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB);
434 
435 	dev->sb_shm->shm_ready = false;
436 }
437 
438 void
439 ftl_mngt_set_shm_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
440 {
441 	struct ftl_superblock *sb = dev->sb;
442 
443 	sb->clean = 1;
444 	dev->sb_shm->shm_clean = true;
445 	sb->header.crc = get_sb_crc(sb);
446 	ftl_mngt_next_step(mngt);
447 }
448 
449 void
450 ftl_mngt_load_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
451 {
452 	FTL_NOTICELOG(dev, "SHM: clean %"PRIu64", shm_clean %d\n", dev->sb->clean, dev->sb_shm->shm_clean);
453 
454 	if (!ftl_fast_startup(dev)) {
455 		restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB);
456 		return;
457 	}
458 
459 	FTL_DEBUGLOG(dev, "SHM: found SB\n");
460 	if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_SB)) {
461 		ftl_mngt_fail_step(mngt);
462 		return;
463 	}
464 	ftl_mngt_next_step(mngt);
465 }
466 
467 void
468 ftl_mngt_validate_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
469 {
470 	struct ftl_superblock *sb = dev->sb;
471 
472 	if (!ftl_superblock_check_magic(sb)) {
473 		FTL_ERRLOG(dev, "Invalid FTL superblock magic\n");
474 		ftl_mngt_fail_step(mngt);
475 		return;
476 	}
477 
478 	if (sb->header.crc != get_sb_crc(sb)) {
479 		FTL_ERRLOG(dev, "Invalid FTL superblock CRC\n");
480 		ftl_mngt_fail_step(mngt);
481 		return;
482 	}
483 
484 	if (ftl_superblock_upgrade(dev)) {
485 		FTL_ERRLOG(dev, "FTL superblock dirty or invalid version\n");
486 		ftl_mngt_fail_step(mngt);
487 		return;
488 	}
489 
490 	if (spdk_uuid_compare(&sb->uuid, &dev->conf.uuid) != 0) {
491 		FTL_ERRLOG(dev, "Invalid FTL superblock UUID\n");
492 		ftl_mngt_fail_step(mngt);
493 		return;
494 	}
495 
496 	if (sb->lba_cnt == 0) {
497 		FTL_ERRLOG(dev, "Invalid FTL superblock lba_cnt\n");
498 		ftl_mngt_fail_step(mngt);
499 		return;
500 	}
501 	dev->num_lbas = sb->lba_cnt;
502 
503 	/* The sb has just been read. Validate and update the conf */
504 	if (sb->overprovisioning == 0 || sb->overprovisioning >= 100) {
505 		FTL_ERRLOG(dev, "Invalid FTL superblock lba_rsvd\n");
506 		ftl_mngt_fail_step(mngt);
507 		return;
508 	}
509 	dev->conf.overprovisioning = sb->overprovisioning;
510 
511 	if (!ftl_superblock_validate_blob_area(dev)) {
512 		FTL_ERRLOG(dev, "Corrupted FTL superblock blob area\n");
513 		ftl_mngt_fail_step(mngt);
514 		return;
515 	}
516 
517 	ftl_mngt_next_step(mngt);
518 }
519 
520 /*
521  * Loads and verifies superblock contents - utilized during the load of an FTL
522  * instance (both from a clean and dirty shutdown).
523  */
524 static const struct ftl_mngt_process_desc desc_restore_sb = {
525 	.name = "SB restore",
526 	.steps = {
527 		{
528 			.name = "Load super block",
529 			.action = ftl_mngt_load_sb
530 		},
531 		{
532 			.name = "Validate super block",
533 			.action = ftl_mngt_validate_sb
534 		},
535 		{}
536 	}
537 };
538 
539 /*
540  * Initializes the superblock fields during first startup of FTL
541  */
542 static const struct ftl_mngt_process_desc desc_init_sb = {
543 	.name = "SB initialize",
544 	.steps = {
545 		{
546 			.name = "Default-initialize superblock",
547 			.action = ftl_mngt_init_default_sb,
548 		},
549 		{}
550 	}
551 };
552 
553 void
554 ftl_mngt_superblock_init(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
555 {
556 	struct ftl_md *md;
557 	struct ftl_md *md_mirror;
558 	struct ftl_layout *layout = &dev->layout;
559 	struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB];
560 	char uuid[SPDK_UUID_STRING_LEN];
561 	int md_create_flags = ftl_md_create_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB);
562 
563 	/* Must generate UUID before MD create on SHM for the SB */
564 	if (dev->conf.mode & SPDK_FTL_MODE_CREATE) {
565 		spdk_uuid_generate(&dev->conf.uuid);
566 		spdk_uuid_fmt_lower(uuid, sizeof(uuid), &dev->conf.uuid);
567 		FTL_NOTICELOG(dev, "Create new FTL, UUID %s\n", uuid);
568 	}
569 
570 shm_retry:
571 	/* Allocate md buf */
572 	dev->sb_shm = NULL;
573 	dev->sb_shm_md = ftl_md_create(dev, spdk_divide_round_up(sizeof(*dev->sb_shm), FTL_BLOCK_SIZE),
574 				       0, "sb_shm",
575 				       md_create_flags, NULL);
576 	if (dev->sb_shm_md == NULL) {
577 		/* The first attempt may fail when trying to open SHM - try to create new */
578 		if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) {
579 			md_create_flags |= FTL_MD_CREATE_SHM_NEW;
580 			goto shm_retry;
581 		}
582 		if (dev->sb_shm_md == NULL) {
583 			ftl_mngt_fail_step(mngt);
584 			return;
585 		}
586 	}
587 
588 	dev->sb_shm = ftl_md_get_buffer(dev->sb_shm_md);
589 
590 	/* Setup the layout of a superblock */
591 	if (ftl_layout_setup_superblock(dev)) {
592 		ftl_mngt_fail_step(mngt);
593 		return;
594 	}
595 
596 	/* Allocate md buf */
597 	layout->md[FTL_LAYOUT_REGION_TYPE_SB] = ftl_md_create(dev, region->current.blocks,
598 						region->vss_blksz, region->name,
599 						md_create_flags, region);
600 	if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB]) {
601 		/* The first attempt may fail when trying to open SHM - try to create new */
602 		if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) {
603 			md_create_flags |= FTL_MD_CREATE_SHM_NEW;
604 			ftl_md_destroy(dev->sb_shm_md, 0);
605 			dev->sb_shm_md = NULL;
606 			if (ftl_layout_clear_superblock(dev)) {
607 				ftl_mngt_fail_step(mngt);
608 				return;
609 			}
610 			goto shm_retry;
611 		}
612 		ftl_mngt_fail_step(mngt);
613 		return;
614 	}
615 
616 	/* Link the md buf to the device */
617 	dev->sb = ftl_md_get_buffer(layout->md[FTL_LAYOUT_REGION_TYPE_SB]);
618 
619 	/* Setup superblock mirror to QLC */
620 	region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB_BASE];
621 	layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = ftl_md_create(dev, region->current.blocks,
622 			region->vss_blksz, NULL, FTL_MD_CREATE_NO_MEM, region);
623 	if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) {
624 		ftl_mngt_fail_step(mngt);
625 		return;
626 	}
627 
628 	/* Initialize mirror region buffer */
629 	md = layout->md[FTL_LAYOUT_REGION_TYPE_SB];
630 	md_mirror = layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE];
631 
632 	md_mirror->dev = md->dev;
633 	md_mirror->data_blocks = md->data_blocks;
634 	md_mirror->data = md->data;
635 	md_mirror->is_mirror = true;
636 
637 	/* Initialize the superblock */
638 	if (dev->conf.mode & SPDK_FTL_MODE_CREATE) {
639 		ftl_mngt_call_process(mngt, &desc_init_sb);
640 	} else {
641 		ftl_mngt_call_process(mngt, &desc_restore_sb);
642 	}
643 }
644 
645 void
646 ftl_mngt_superblock_deinit(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
647 {
648 	struct ftl_layout *layout = &dev->layout;
649 
650 	if (layout->md[FTL_LAYOUT_REGION_TYPE_SB]) {
651 		ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB],
652 			       ftl_md_destroy_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB));
653 		layout->md[FTL_LAYOUT_REGION_TYPE_SB] = NULL;
654 	}
655 
656 	if (layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) {
657 		ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE], 0);
658 		layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = NULL;
659 	}
660 
661 	ftl_md_destroy(dev->sb_shm_md, ftl_md_destroy_shm_flags(dev));
662 	dev->sb_shm_md = NULL;
663 	dev->sb_shm = NULL;
664 
665 	ftl_mngt_next_step(mngt);
666 }
667 
668 static void
669 ftl_mngt_restore_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
670 {
671 	if (ftl_fast_startup(dev)) {
672 		FTL_DEBUGLOG(dev, "SHM: found nv cache md\n");
673 		if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_NVC_MD)) {
674 			ftl_mngt_fail_step(mngt);
675 			return;
676 		}
677 		ftl_mngt_next_step(mngt);
678 		return;
679 	}
680 	restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_NVC_MD);
681 }
682 
683 static void
684 ftl_mngt_restore_vld_map_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
685 {
686 	if (ftl_fast_startup(dev)) {
687 		FTL_DEBUGLOG(dev, "SHM: found vldmap\n");
688 		if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_VALID_MAP)) {
689 			ftl_mngt_fail_step(mngt);
690 			return;
691 		}
692 		ftl_mngt_next_step(mngt);
693 		return;
694 	}
695 	restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_VALID_MAP);
696 }
697 
698 static void
699 ftl_mngt_restore_band_info_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
700 {
701 	if (ftl_fast_startup(dev)) {
702 		FTL_DEBUGLOG(dev, "SHM: found band md\n");
703 		if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_BAND_MD)) {
704 			ftl_mngt_fail_step(mngt);
705 			return;
706 		}
707 		ftl_mngt_next_step(mngt);
708 		return;
709 	}
710 	restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_BAND_MD);
711 }
712 
713 static void
714 ftl_mngt_restore_trim_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
715 {
716 	if (ftl_fast_startup(dev)) {
717 		FTL_DEBUGLOG(dev, "SHM: found trim md\n");
718 		if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_TRIM_MD)) {
719 			ftl_mngt_fail_step(mngt);
720 			return;
721 		}
722 		ftl_mngt_next_step(mngt);
723 		return;
724 	}
725 	restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_TRIM_MD);
726 }
727 
728 /*
729  * Loads metadata after a clean shutdown.
730  */
731 static const struct ftl_mngt_process_desc desc_restore = {
732 	.name = "Restore metadata",
733 	.steps = {
734 		{
735 			.name = "Restore NV cache metadata",
736 			.action = ftl_mngt_restore_nv_cache_metadata,
737 		},
738 		{
739 			.name = "Restore valid map metadata",
740 			.action = ftl_mngt_restore_vld_map_metadata,
741 		},
742 		{
743 			.name = "Restore band info metadata",
744 			.action = ftl_mngt_restore_band_info_metadata,
745 		},
746 		{
747 			.name = "Restore trim metadata",
748 			.action = ftl_mngt_restore_trim_metadata,
749 		},
750 		{}
751 	}
752 };
753 
754 void
755 ftl_mngt_restore_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
756 {
757 	ftl_mngt_call_process(mngt, &desc_restore);
758 }
759 
760 void
761 ftl_mngt_persist_superblock(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
762 {
763 	dev->sb->header.crc = get_sb_crc(dev->sb);
764 	persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB);
765 }
766