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