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