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