xref: /spdk/lib/ftl/ftl_layout.c (revision 6d6179ff420a322c5161a49a5af5bfd30e78674e)
12b5bba56SArtur Paszkiewicz /*   SPDX-License-Identifier: BSD-3-Clause
217cf101bSMateusz Kozlowski  *   Copyright 2023 Solidigm All Rights Reserved
3a6dbe372Spaul luse  *   Copyright (C) 2022 Intel Corporation.
42b5bba56SArtur Paszkiewicz  *   All rights reserved.
52b5bba56SArtur Paszkiewicz  */
62b5bba56SArtur Paszkiewicz 
72b5bba56SArtur Paszkiewicz #include "spdk/bdev.h"
82b5bba56SArtur Paszkiewicz 
92b5bba56SArtur Paszkiewicz #include "ftl_core.h"
102b5bba56SArtur Paszkiewicz #include "ftl_utils.h"
116448f336SArtur Paszkiewicz #include "ftl_band.h"
122b5bba56SArtur Paszkiewicz #include "ftl_layout.h"
13a68a12a4SKozlowski Mateusz #include "ftl_nv_cache.h"
14c6880a39SArtur Paszkiewicz #include "ftl_sb.h"
15b0556d4aSLukasz Lasek #include "nvc/ftl_nvc_dev.h"
1693036282SLukasz Lasek #include "utils/ftl_layout_tracker_bdev.h"
17a5c04e6dSMateusz Kozlowski #include "upgrade/ftl_layout_upgrade.h"
182b5bba56SArtur Paszkiewicz 
199f42898aSLukasz Lasek enum ftl_layout_setup_mode {
209f42898aSLukasz Lasek 	FTL_LAYOUT_SETUP_MODE_LOAD_CURRENT = 0,
219f42898aSLukasz Lasek 	FTL_LAYOUT_SETUP_MODE_NO_RESTRICT,
22845c9ae2SMateusz Kozlowski 	FTL_LAYOUT_SETUP_MODE_LEGACY_DEFAULT,
239f42898aSLukasz Lasek };
24a68a12a4SKozlowski Mateusz 
252b5bba56SArtur Paszkiewicz static inline float
262b5bba56SArtur Paszkiewicz blocks2mib(uint64_t blocks)
272b5bba56SArtur Paszkiewicz {
282b5bba56SArtur Paszkiewicz 	float result;
292b5bba56SArtur Paszkiewicz 
302b5bba56SArtur Paszkiewicz 	result = blocks;
312b5bba56SArtur Paszkiewicz 	result *= FTL_BLOCK_SIZE;
322b5bba56SArtur Paszkiewicz 	result /= 1024UL;
332b5bba56SArtur Paszkiewicz 	result /= 1024UL;
342b5bba56SArtur Paszkiewicz 
352b5bba56SArtur Paszkiewicz 	return result;
362b5bba56SArtur Paszkiewicz }
37102d266dSKozlowski Mateusz 
38102d266dSKozlowski Mateusz static uint64_t
39102d266dSKozlowski Mateusz superblock_region_size(struct spdk_ftl_dev *dev)
40102d266dSKozlowski Mateusz {
41102d266dSKozlowski Mateusz 	const struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(dev->base_bdev_desc);
42102d266dSKozlowski Mateusz 	uint64_t wus = spdk_bdev_get_write_unit_size(bdev) * FTL_BLOCK_SIZE;
43102d266dSKozlowski Mateusz 
44102d266dSKozlowski Mateusz 	if (wus > FTL_SUPERBLOCK_SIZE) {
45102d266dSKozlowski Mateusz 		return wus;
46102d266dSKozlowski Mateusz 	} else {
47102d266dSKozlowski Mateusz 		return wus * spdk_divide_round_up(FTL_SUPERBLOCK_SIZE, wus);
48102d266dSKozlowski Mateusz 	}
49102d266dSKozlowski Mateusz }
50102d266dSKozlowski Mateusz 
51102d266dSKozlowski Mateusz static uint64_t
52102d266dSKozlowski Mateusz superblock_region_blocks(struct spdk_ftl_dev *dev)
53102d266dSKozlowski Mateusz {
54102d266dSKozlowski Mateusz 	return superblock_region_size(dev) / FTL_BLOCK_SIZE;
55102d266dSKozlowski Mateusz }
562b5bba56SArtur Paszkiewicz 
57b0556d4aSLukasz Lasek uint64_t
58b0556d4aSLukasz Lasek ftl_md_region_blocks(struct spdk_ftl_dev *dev, uint64_t bytes)
59f725ca81SArtur Paszkiewicz {
60102d266dSKozlowski Mateusz 	const uint64_t alignment = superblock_region_size(dev);
61f725ca81SArtur Paszkiewicz 	uint64_t result;
62f725ca81SArtur Paszkiewicz 
63f725ca81SArtur Paszkiewicz 	result = spdk_divide_round_up(bytes, alignment);
64f725ca81SArtur Paszkiewicz 	result *= alignment;
65f725ca81SArtur Paszkiewicz 	result /= FTL_BLOCK_SIZE;
66f725ca81SArtur Paszkiewicz 
67f725ca81SArtur Paszkiewicz 	return result;
68f725ca81SArtur Paszkiewicz }
69f725ca81SArtur Paszkiewicz 
708fcffebaSMateusz Kozlowski uint64_t
718fcffebaSMateusz Kozlowski ftl_md_region_align_blocks(struct spdk_ftl_dev *dev, uint64_t blocks)
728fcffebaSMateusz Kozlowski {
738fcffebaSMateusz Kozlowski 	const uint64_t alignment = superblock_region_blocks(dev);
748fcffebaSMateusz Kozlowski 	uint64_t result;
758fcffebaSMateusz Kozlowski 
768fcffebaSMateusz Kozlowski 	result = spdk_divide_round_up(blocks, alignment);
778fcffebaSMateusz Kozlowski 	result *= alignment;
788fcffebaSMateusz Kozlowski 
798fcffebaSMateusz Kozlowski 	return result;
808fcffebaSMateusz Kozlowski }
818fcffebaSMateusz Kozlowski 
82b0556d4aSLukasz Lasek const char *
83b0556d4aSLukasz Lasek ftl_md_region_name(enum ftl_layout_region_type reg_type)
84b0556d4aSLukasz Lasek {
85b0556d4aSLukasz Lasek 	static const char *md_region_name[FTL_LAYOUT_REGION_TYPE_MAX] = {
86b0556d4aSLukasz Lasek 		[FTL_LAYOUT_REGION_TYPE_SB] = "sb",
87b0556d4aSLukasz Lasek 		[FTL_LAYOUT_REGION_TYPE_SB_BASE] = "sb_mirror",
88b0556d4aSLukasz Lasek 		[FTL_LAYOUT_REGION_TYPE_L2P] = "l2p",
89b0556d4aSLukasz Lasek 		[FTL_LAYOUT_REGION_TYPE_BAND_MD] = "band_md",
90b0556d4aSLukasz Lasek 		[FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR] = "band_md_mirror",
91b0556d4aSLukasz Lasek 		[FTL_LAYOUT_REGION_TYPE_VALID_MAP] = "vmap",
92b0556d4aSLukasz Lasek 		[FTL_LAYOUT_REGION_TYPE_NVC_MD] = "nvc_md",
93b0556d4aSLukasz Lasek 		[FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR] = "nvc_md_mirror",
94b0556d4aSLukasz Lasek 		[FTL_LAYOUT_REGION_TYPE_DATA_NVC] = "data_nvc",
95b0556d4aSLukasz Lasek 		[FTL_LAYOUT_REGION_TYPE_DATA_BASE] = "data_btm",
96b0556d4aSLukasz Lasek 		[FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC] = "p2l0",
97b0556d4aSLukasz Lasek 		[FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC_NEXT] = "p2l1",
98b0556d4aSLukasz Lasek 		[FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP] = "p2l2",
99b0556d4aSLukasz Lasek 		[FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP_NEXT] = "p2l3",
100b0556d4aSLukasz Lasek 		[FTL_LAYOUT_REGION_TYPE_TRIM_MD] = "trim_md",
101b0556d4aSLukasz Lasek 		[FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR] = "trim_md_mirror",
1022d613454SMateusz Kozlowski 		[FTL_LAYOUT_REGION_TYPE_TRIM_LOG] = "trim_log",
103*6d6179ffSMateusz Kozlowski 		[FTL_LAYOUT_REGION_TYPE_TRIM_LOG_MIRROR] = "trim_log_mirror",
104*6d6179ffSMateusz Kozlowski 		[FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MIN] = "p2l_log_io1",
105*6d6179ffSMateusz Kozlowski 		[FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MAX] = "p2l_log_io2",
106b0556d4aSLukasz Lasek 	};
107b0556d4aSLukasz Lasek 	const char *reg_name = md_region_name[reg_type];
108b0556d4aSLukasz Lasek 
109b0556d4aSLukasz Lasek 	assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX);
110b0556d4aSLukasz Lasek 	assert(reg_name != NULL);
111b0556d4aSLukasz Lasek 	return reg_name;
112b0556d4aSLukasz Lasek }
113b0556d4aSLukasz Lasek 
114*6d6179ffSMateusz Kozlowski static bool
115*6d6179ffSMateusz Kozlowski is_region_disabled(struct ftl_layout_region *region)
116*6d6179ffSMateusz Kozlowski {
117*6d6179ffSMateusz Kozlowski 	return region->current.blocks == 0 && region->current.offset == FTL_ADDR_INVALID;
118*6d6179ffSMateusz Kozlowski }
119*6d6179ffSMateusz Kozlowski 
1202b5bba56SArtur Paszkiewicz static void
1212b5bba56SArtur Paszkiewicz dump_region(struct spdk_ftl_dev *dev, struct ftl_layout_region *region)
1222b5bba56SArtur Paszkiewicz {
123*6d6179ffSMateusz Kozlowski 	if (is_region_disabled(region)) {
124*6d6179ffSMateusz Kozlowski 		return;
125*6d6179ffSMateusz Kozlowski 	}
126*6d6179ffSMateusz Kozlowski 
127102d266dSKozlowski Mateusz 	assert(!(region->current.offset % superblock_region_blocks(dev)));
128102d266dSKozlowski Mateusz 	assert(!(region->current.blocks % superblock_region_blocks(dev)));
1292b5bba56SArtur Paszkiewicz 
1302b5bba56SArtur Paszkiewicz 	FTL_NOTICELOG(dev, "Region %s\n", region->name);
1312b5bba56SArtur Paszkiewicz 	FTL_NOTICELOG(dev, "	offset:                      %.2f MiB\n",
1322b5bba56SArtur Paszkiewicz 		      blocks2mib(region->current.offset));
1332b5bba56SArtur Paszkiewicz 	FTL_NOTICELOG(dev, "	blocks:                      %.2f MiB\n",
1342b5bba56SArtur Paszkiewicz 		      blocks2mib(region->current.blocks));
1352b5bba56SArtur Paszkiewicz }
1362b5bba56SArtur Paszkiewicz 
1372b5bba56SArtur Paszkiewicz int
1382b5bba56SArtur Paszkiewicz ftl_validate_regions(struct spdk_ftl_dev *dev, struct ftl_layout *layout)
1392b5bba56SArtur Paszkiewicz {
14030ef80cdSMateusz Kozlowski 	enum ftl_layout_region_type i, j;
1412b5bba56SArtur Paszkiewicz 
1422b5bba56SArtur Paszkiewicz 	/* Validate if regions doesn't overlap each other  */
1432b5bba56SArtur Paszkiewicz 	for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++) {
14430ef80cdSMateusz Kozlowski 		struct ftl_layout_region *r1 = ftl_layout_region_get(dev, i);
1452b5bba56SArtur Paszkiewicz 
1462d613454SMateusz Kozlowski 		if (!r1 || is_region_disabled(r1)) {
1478fc78fd8SMateusz Kozlowski 			continue;
1488fc78fd8SMateusz Kozlowski 		}
1498fc78fd8SMateusz Kozlowski 
1502b5bba56SArtur Paszkiewicz 		for (j = 0; j < FTL_LAYOUT_REGION_TYPE_MAX; j++) {
15130ef80cdSMateusz Kozlowski 			struct ftl_layout_region *r2 = ftl_layout_region_get(dev, j);
1522b5bba56SArtur Paszkiewicz 
1532d613454SMateusz Kozlowski 			if (!r2 || is_region_disabled(r2)) {
1548fc78fd8SMateusz Kozlowski 				continue;
1558fc78fd8SMateusz Kozlowski 			}
1568fc78fd8SMateusz Kozlowski 
1572b5bba56SArtur Paszkiewicz 			if (r1->bdev_desc != r2->bdev_desc) {
1582b5bba56SArtur Paszkiewicz 				continue;
1592b5bba56SArtur Paszkiewicz 			}
1602b5bba56SArtur Paszkiewicz 
1612b5bba56SArtur Paszkiewicz 			if (i == j) {
1622b5bba56SArtur Paszkiewicz 				continue;
1632b5bba56SArtur Paszkiewicz 			}
1642b5bba56SArtur Paszkiewicz 
1652b5bba56SArtur Paszkiewicz 			uint64_t r1_begin = r1->current.offset;
1662b5bba56SArtur Paszkiewicz 			uint64_t r1_end = r1->current.offset + r1->current.blocks - 1;
1672b5bba56SArtur Paszkiewicz 			uint64_t r2_begin = r2->current.offset;
1682b5bba56SArtur Paszkiewicz 			uint64_t r2_end = r2->current.offset + r2->current.blocks - 1;
1692b5bba56SArtur Paszkiewicz 
1702b5bba56SArtur Paszkiewicz 			if (spdk_max(r1_begin, r2_begin) <= spdk_min(r1_end, r2_end)) {
1712b5bba56SArtur Paszkiewicz 				FTL_ERRLOG(dev, "Layout initialization ERROR, two regions overlap, "
1722b5bba56SArtur Paszkiewicz 					   "%s and %s\n", r1->name, r2->name);
1732b5bba56SArtur Paszkiewicz 				return -1;
1742b5bba56SArtur Paszkiewicz 			}
1752b5bba56SArtur Paszkiewicz 		}
1762b5bba56SArtur Paszkiewicz 	}
1772b5bba56SArtur Paszkiewicz 
1782b5bba56SArtur Paszkiewicz 	return 0;
1792b5bba56SArtur Paszkiewicz }
1802b5bba56SArtur Paszkiewicz 
1812b5bba56SArtur Paszkiewicz static uint64_t
1822b5bba56SArtur Paszkiewicz get_num_user_lbas(struct spdk_ftl_dev *dev)
1832b5bba56SArtur Paszkiewicz {
18481dfe157SKozlowski Mateusz 	uint64_t blocks;
1852b5bba56SArtur Paszkiewicz 
18681dfe157SKozlowski Mateusz 	blocks = dev->num_bands * ftl_get_num_blocks_in_band(dev);
1872b5bba56SArtur Paszkiewicz 	blocks = (blocks * (100 - dev->conf.overprovisioning)) / 100;
1882b5bba56SArtur Paszkiewicz 
1892b5bba56SArtur Paszkiewicz 	return blocks;
1902b5bba56SArtur Paszkiewicz }
1912b5bba56SArtur Paszkiewicz 
19230ef80cdSMateusz Kozlowski struct ftl_layout_region *
19330ef80cdSMateusz Kozlowski ftl_layout_region_get(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type)
19430ef80cdSMateusz Kozlowski {
19530ef80cdSMateusz Kozlowski 	struct ftl_layout_region *reg = &dev->layout.region[reg_type];
19630ef80cdSMateusz Kozlowski 
19730ef80cdSMateusz Kozlowski 	assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX);
19830ef80cdSMateusz Kozlowski 	return reg->type == reg_type ? reg : NULL;
19930ef80cdSMateusz Kozlowski }
20030ef80cdSMateusz Kozlowski 
2018fcffebaSMateusz Kozlowski uint64_t
2028fcffebaSMateusz Kozlowski ftl_layout_base_offset(struct spdk_ftl_dev *dev)
2038fcffebaSMateusz Kozlowski {
2048fcffebaSMateusz Kozlowski 	return dev->num_bands * ftl_get_num_blocks_in_band(dev);
2058fcffebaSMateusz Kozlowski }
2068fcffebaSMateusz Kozlowski 
2072b5bba56SArtur Paszkiewicz static int
208d55b9f29SMateusz Kozlowski layout_region_create_nvc(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type,
209d55b9f29SMateusz Kozlowski 			 uint32_t reg_version, size_t entry_size, size_t entry_count)
210d55b9f29SMateusz Kozlowski {
21126f3b551SMateusz Kozlowski 	const struct ftl_md_layout_ops *md_ops = &dev->nv_cache.nvc_type->ops.md_layout_ops;
2129f42898aSLukasz Lasek 	size_t reg_blks = ftl_md_region_blocks(dev, entry_count * entry_size);
213d55b9f29SMateusz Kozlowski 
2149f42898aSLukasz Lasek 	if (md_ops->region_create(dev, reg_type, reg_version, reg_blks)) {
2159f42898aSLukasz Lasek 		return -1;
2169f42898aSLukasz Lasek 	}
2179f42898aSLukasz Lasek 	if (md_ops->region_open(dev, reg_type, reg_version, entry_size, entry_count,
2189f42898aSLukasz Lasek 				&dev->layout.region[reg_type])) {
219d55b9f29SMateusz Kozlowski 		return -1;
220d55b9f29SMateusz Kozlowski 	}
221d55b9f29SMateusz Kozlowski 	return 0;
222d55b9f29SMateusz Kozlowski }
223d55b9f29SMateusz Kozlowski 
224d55b9f29SMateusz Kozlowski static int
225d55b9f29SMateusz Kozlowski layout_region_create_base(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type,
226d55b9f29SMateusz Kozlowski 			  uint32_t reg_version, size_t entry_size, size_t entry_count)
227d55b9f29SMateusz Kozlowski {
228d55b9f29SMateusz Kozlowski 	const struct ftl_md_layout_ops *md_ops = &dev->base_type->ops.md_layout_ops;
2299f42898aSLukasz Lasek 	size_t reg_blks = ftl_md_region_blocks(dev, entry_count * entry_size);
230d55b9f29SMateusz Kozlowski 
2319f42898aSLukasz Lasek 	if (md_ops->region_create(dev, reg_type, reg_version, reg_blks)) {
2329f42898aSLukasz Lasek 		return -1;
2339f42898aSLukasz Lasek 	}
2349f42898aSLukasz Lasek 	if (md_ops->region_open(dev, reg_type, reg_version, entry_size, entry_count,
2359f42898aSLukasz Lasek 				&dev->layout.region[reg_type])) {
236d55b9f29SMateusz Kozlowski 		return -1;
237d55b9f29SMateusz Kozlowski 	}
238d55b9f29SMateusz Kozlowski 	return 0;
239d55b9f29SMateusz Kozlowski }
240d55b9f29SMateusz Kozlowski 
241845c9ae2SMateusz Kozlowski static void
242845c9ae2SMateusz Kozlowski legacy_layout_verify_region(struct ftl_layout_tracker_bdev *layout_tracker,
243845c9ae2SMateusz Kozlowski 			    enum ftl_layout_region_type reg_type, uint32_t reg_version)
244845c9ae2SMateusz Kozlowski {
245845c9ae2SMateusz Kozlowski 	const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
246845c9ae2SMateusz Kozlowski 	const struct ftl_layout_tracker_bdev_region_props *reg_found = NULL;
247845c9ae2SMateusz Kozlowski 
248845c9ae2SMateusz Kozlowski 	while (true) {
249845c9ae2SMateusz Kozlowski 		ftl_layout_tracker_bdev_find_next_region(layout_tracker, reg_type, &reg_search_ctx);
250845c9ae2SMateusz Kozlowski 		if (!reg_search_ctx) {
251845c9ae2SMateusz Kozlowski 			break;
252845c9ae2SMateusz Kozlowski 		}
253845c9ae2SMateusz Kozlowski 
254845c9ae2SMateusz Kozlowski 		/* Only a single region version is present in upgrade from the legacy layout */
255845c9ae2SMateusz Kozlowski 		ftl_bug(reg_search_ctx->ver != reg_version);
256845c9ae2SMateusz Kozlowski 		ftl_bug(reg_found != NULL);
257845c9ae2SMateusz Kozlowski 
258845c9ae2SMateusz Kozlowski 		reg_found = reg_search_ctx;
259845c9ae2SMateusz Kozlowski 	}
260845c9ae2SMateusz Kozlowski }
261845c9ae2SMateusz Kozlowski 
262845c9ae2SMateusz Kozlowski static int
263845c9ae2SMateusz Kozlowski legacy_layout_region_open_nvc(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type,
264845c9ae2SMateusz Kozlowski 			      uint32_t reg_version, size_t entry_size, size_t entry_count)
265845c9ae2SMateusz Kozlowski {
266845c9ae2SMateusz Kozlowski 	struct ftl_layout_region *reg = &dev->layout.region[reg_type];
26726f3b551SMateusz Kozlowski 	const struct ftl_md_layout_ops *md_ops = &dev->nv_cache.nvc_type->ops.md_layout_ops;
268845c9ae2SMateusz Kozlowski 
269845c9ae2SMateusz Kozlowski 	legacy_layout_verify_region(dev->nvc_layout_tracker, reg_type, reg_version);
270845c9ae2SMateusz Kozlowski 	return md_ops->region_open(dev, reg_type, reg_version, entry_size, entry_count, reg);
271845c9ae2SMateusz Kozlowski }
272845c9ae2SMateusz Kozlowski 
273845c9ae2SMateusz Kozlowski static int
274845c9ae2SMateusz Kozlowski legacy_layout_region_open_base(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type,
275845c9ae2SMateusz Kozlowski 			       uint32_t reg_version, size_t entry_size, size_t entry_count)
276845c9ae2SMateusz Kozlowski {
277845c9ae2SMateusz Kozlowski 	struct ftl_layout_region *reg = &dev->layout.region[reg_type];
278845c9ae2SMateusz Kozlowski 	const struct ftl_md_layout_ops *md_ops = &dev->base_type->ops.md_layout_ops;
279845c9ae2SMateusz Kozlowski 
280845c9ae2SMateusz Kozlowski 	legacy_layout_verify_region(dev->nvc_layout_tracker, reg_type, reg_version);
281845c9ae2SMateusz Kozlowski 	return md_ops->region_open(dev, reg_type, reg_version, entry_size, entry_count, reg);
282845c9ae2SMateusz Kozlowski }
283845c9ae2SMateusz Kozlowski 
284845c9ae2SMateusz Kozlowski static int
285845c9ae2SMateusz Kozlowski layout_setup_legacy_default_nvc(struct spdk_ftl_dev *dev)
286845c9ae2SMateusz Kozlowski {
287845c9ae2SMateusz Kozlowski 	int region_type;
288845c9ae2SMateusz Kozlowski 	uint64_t blocks, chunk_count;
289845c9ae2SMateusz Kozlowski 	struct ftl_layout *layout = &dev->layout;
290845c9ae2SMateusz Kozlowski 	const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
291845c9ae2SMateusz Kozlowski 
292845c9ae2SMateusz Kozlowski 	/* Initialize L2P region */
293845c9ae2SMateusz Kozlowski 	blocks = ftl_md_region_blocks(dev, layout->l2p.addr_size * dev->num_lbas);
294845c9ae2SMateusz Kozlowski 	if (legacy_layout_region_open_nvc(dev, FTL_LAYOUT_REGION_TYPE_L2P, 0, FTL_BLOCK_SIZE,
295845c9ae2SMateusz Kozlowski 					  blocks)) {
296845c9ae2SMateusz Kozlowski 		goto error;
297845c9ae2SMateusz Kozlowski 	}
298845c9ae2SMateusz Kozlowski 
299845c9ae2SMateusz Kozlowski 	/* Initialize band info metadata */
300845c9ae2SMateusz Kozlowski 	if (legacy_layout_region_open_nvc(dev, FTL_LAYOUT_REGION_TYPE_BAND_MD, FTL_BAND_VERSION_1,
301845c9ae2SMateusz Kozlowski 					  sizeof(struct ftl_band_md), ftl_get_num_bands(dev))) {
302845c9ae2SMateusz Kozlowski 		goto error;
303845c9ae2SMateusz Kozlowski 	}
304845c9ae2SMateusz Kozlowski 
305845c9ae2SMateusz Kozlowski 	/* Initialize band info metadata mirror */
306845c9ae2SMateusz Kozlowski 	if (legacy_layout_region_open_nvc(dev, FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR, FTL_BAND_VERSION_1,
307845c9ae2SMateusz Kozlowski 					  sizeof(struct ftl_band_md), ftl_get_num_bands(dev))) {
308845c9ae2SMateusz Kozlowski 		goto error;
309845c9ae2SMateusz Kozlowski 	}
310845c9ae2SMateusz Kozlowski 	layout->region[FTL_LAYOUT_REGION_TYPE_BAND_MD].mirror_type = FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR;
311845c9ae2SMateusz Kozlowski 
312845c9ae2SMateusz Kozlowski 	/*
313845c9ae2SMateusz Kozlowski 	 * Initialize P2L checkpointing regions
314845c9ae2SMateusz Kozlowski 	 */
315845c9ae2SMateusz Kozlowski 	for (region_type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN;
316845c9ae2SMateusz Kozlowski 	     region_type <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX;
317845c9ae2SMateusz Kozlowski 	     region_type++) {
318845c9ae2SMateusz Kozlowski 		const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
319845c9ae2SMateusz Kozlowski 
320845c9ae2SMateusz Kozlowski 		/* Get legacy number of blocks */
321845c9ae2SMateusz Kozlowski 		ftl_layout_tracker_bdev_find_next_region(dev->nvc_layout_tracker, region_type, &reg_search_ctx);
322845c9ae2SMateusz Kozlowski 		if (!reg_search_ctx || reg_search_ctx->ver != FTL_P2L_VERSION_1) {
323845c9ae2SMateusz Kozlowski 			goto error;
324845c9ae2SMateusz Kozlowski 		}
325845c9ae2SMateusz Kozlowski 		blocks = reg_search_ctx->blk_sz;
326845c9ae2SMateusz Kozlowski 
327845c9ae2SMateusz Kozlowski 		if (legacy_layout_region_open_nvc(dev, region_type, FTL_P2L_VERSION_1, FTL_BLOCK_SIZE, blocks)) {
328845c9ae2SMateusz Kozlowski 			goto error;
329845c9ae2SMateusz Kozlowski 		}
330845c9ae2SMateusz Kozlowski 	}
331845c9ae2SMateusz Kozlowski 
332845c9ae2SMateusz Kozlowski 	/*
333845c9ae2SMateusz Kozlowski 	 * Initialize trim metadata region
334845c9ae2SMateusz Kozlowski 	 */
335845c9ae2SMateusz Kozlowski 	blocks = layout->region[FTL_LAYOUT_REGION_TYPE_L2P].current.blocks;
336845c9ae2SMateusz Kozlowski 	if (legacy_layout_region_open_nvc(dev, FTL_LAYOUT_REGION_TYPE_TRIM_MD, 0, sizeof(uint64_t),
337845c9ae2SMateusz Kozlowski 					  blocks)) {
338845c9ae2SMateusz Kozlowski 		goto error;
339845c9ae2SMateusz Kozlowski 	}
340845c9ae2SMateusz Kozlowski 
341845c9ae2SMateusz Kozlowski 	/* Initialize trim metadata mirror region */
342845c9ae2SMateusz Kozlowski 	if (legacy_layout_region_open_nvc(dev, FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR, 0, sizeof(uint64_t),
343845c9ae2SMateusz Kozlowski 					  blocks)) {
344845c9ae2SMateusz Kozlowski 		goto error;
345845c9ae2SMateusz Kozlowski 	}
346845c9ae2SMateusz Kozlowski 	layout->region[FTL_LAYOUT_REGION_TYPE_TRIM_MD].mirror_type = FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR;
347845c9ae2SMateusz Kozlowski 
348845c9ae2SMateusz Kozlowski 	/* Restore chunk count */
349845c9ae2SMateusz Kozlowski 	ftl_layout_tracker_bdev_find_next_region(dev->nvc_layout_tracker, FTL_LAYOUT_REGION_TYPE_DATA_NVC,
350845c9ae2SMateusz Kozlowski 			&reg_search_ctx);
351845c9ae2SMateusz Kozlowski 	if (!reg_search_ctx || reg_search_ctx->ver != 0) {
352845c9ae2SMateusz Kozlowski 		goto error;
353845c9ae2SMateusz Kozlowski 	}
354845c9ae2SMateusz Kozlowski 	blocks = reg_search_ctx->blk_sz;
355845c9ae2SMateusz Kozlowski 	chunk_count = blocks / ftl_get_num_blocks_in_band(dev);
356845c9ae2SMateusz Kozlowski 	if (0 == chunk_count) {
357845c9ae2SMateusz Kozlowski 		goto error;
358845c9ae2SMateusz Kozlowski 	}
359845c9ae2SMateusz Kozlowski 
360845c9ae2SMateusz Kozlowski 	/*
361845c9ae2SMateusz Kozlowski 	 * Initialize NV Cache metadata
362845c9ae2SMateusz Kozlowski 	 */
363845c9ae2SMateusz Kozlowski 	if (legacy_layout_region_open_nvc(dev, FTL_LAYOUT_REGION_TYPE_NVC_MD, FTL_NVC_VERSION_1,
364845c9ae2SMateusz Kozlowski 					  sizeof(struct ftl_nv_cache_chunk_md), chunk_count)) {
365845c9ae2SMateusz Kozlowski 		goto error;
366845c9ae2SMateusz Kozlowski 	}
367845c9ae2SMateusz Kozlowski 
368845c9ae2SMateusz Kozlowski 	/*
369845c9ae2SMateusz Kozlowski 	 * Initialize NV Cache metadata mirror
370845c9ae2SMateusz Kozlowski 	 */
371845c9ae2SMateusz Kozlowski 	if (legacy_layout_region_open_nvc(dev, FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR, FTL_NVC_VERSION_1,
372845c9ae2SMateusz Kozlowski 					  sizeof(struct ftl_nv_cache_chunk_md), chunk_count)) {
373845c9ae2SMateusz Kozlowski 		goto error;
374845c9ae2SMateusz Kozlowski 	}
375845c9ae2SMateusz Kozlowski 	layout->region[FTL_LAYOUT_REGION_TYPE_NVC_MD].mirror_type = FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR;
376845c9ae2SMateusz Kozlowski 
377845c9ae2SMateusz Kozlowski 	/*
378845c9ae2SMateusz Kozlowski 	 * Initialize data region on NV cache
379845c9ae2SMateusz Kozlowski 	 */
380845c9ae2SMateusz Kozlowski 	if (legacy_layout_region_open_nvc(dev, FTL_LAYOUT_REGION_TYPE_DATA_NVC, 0,
381845c9ae2SMateusz Kozlowski 					  layout->nvc.chunk_data_blocks * FTL_BLOCK_SIZE, chunk_count)) {
382845c9ae2SMateusz Kozlowski 		goto error;
383845c9ae2SMateusz Kozlowski 	}
384845c9ae2SMateusz Kozlowski 
3855555d51cSLukasz Lasek 	/* Here is the place to add necessary region placeholders for the creation of new regions */
3862d613454SMateusz Kozlowski 	ftl_layout_upgrade_add_region_placeholder(dev, dev->nvc_layout_tracker,
3872d613454SMateusz Kozlowski 			FTL_LAYOUT_REGION_TYPE_TRIM_LOG);
3882d613454SMateusz Kozlowski 	ftl_layout_upgrade_add_region_placeholder(dev, dev->nvc_layout_tracker,
3892d613454SMateusz Kozlowski 			FTL_LAYOUT_REGION_TYPE_TRIM_LOG_MIRROR);
3905555d51cSLukasz Lasek 
391845c9ae2SMateusz Kozlowski 	return 0;
392845c9ae2SMateusz Kozlowski 
393845c9ae2SMateusz Kozlowski error:
394845c9ae2SMateusz Kozlowski 	FTL_ERRLOG(dev, "Invalid legacy NV Cache metadata layout\n");
395845c9ae2SMateusz Kozlowski 	return -1;
396845c9ae2SMateusz Kozlowski }
397845c9ae2SMateusz Kozlowski 
398845c9ae2SMateusz Kozlowski static int
399845c9ae2SMateusz Kozlowski layout_setup_legacy_default_base(struct spdk_ftl_dev *dev)
400845c9ae2SMateusz Kozlowski {
401845c9ae2SMateusz Kozlowski 	struct ftl_layout *layout = &dev->layout;
402845c9ae2SMateusz Kozlowski 
403845c9ae2SMateusz Kozlowski 	/* Base device layout is as follows:
404845c9ae2SMateusz Kozlowski 	 * - superblock
405845c9ae2SMateusz Kozlowski 	 * - data
406845c9ae2SMateusz Kozlowski 	 * - valid map
407845c9ae2SMateusz Kozlowski 	 */
408845c9ae2SMateusz Kozlowski 	if (layout_region_create_base(dev, FTL_LAYOUT_REGION_TYPE_DATA_BASE, 0, FTL_BLOCK_SIZE,
409845c9ae2SMateusz Kozlowski 				      ftl_layout_base_offset(dev))) {
410845c9ae2SMateusz Kozlowski 		return -1;
411845c9ae2SMateusz Kozlowski 	}
412845c9ae2SMateusz Kozlowski 
413845c9ae2SMateusz Kozlowski 	if (legacy_layout_region_open_base(dev, FTL_LAYOUT_REGION_TYPE_VALID_MAP, 0, FTL_BLOCK_SIZE,
414845c9ae2SMateusz Kozlowski 					   ftl_md_region_blocks(dev, spdk_divide_round_up(layout->base.total_blocks + layout->nvc.total_blocks,
415845c9ae2SMateusz Kozlowski 							   8)))) {
416845c9ae2SMateusz Kozlowski 		return -1;
417845c9ae2SMateusz Kozlowski 	}
418845c9ae2SMateusz Kozlowski 
419845c9ae2SMateusz Kozlowski 	return 0;
420845c9ae2SMateusz Kozlowski }
421845c9ae2SMateusz Kozlowski 
422845c9ae2SMateusz Kozlowski static int
423845c9ae2SMateusz Kozlowski layout_setup_legacy_default(struct spdk_ftl_dev *dev)
424845c9ae2SMateusz Kozlowski {
425845c9ae2SMateusz Kozlowski 	if (layout_setup_legacy_default_nvc(dev) || layout_setup_legacy_default_base(dev)) {
426845c9ae2SMateusz Kozlowski 		return -1;
427845c9ae2SMateusz Kozlowski 	}
428845c9ae2SMateusz Kozlowski 	return 0;
429845c9ae2SMateusz Kozlowski }
430845c9ae2SMateusz Kozlowski 
431d55b9f29SMateusz Kozlowski static int
4329f42898aSLukasz Lasek layout_setup_default_nvc(struct spdk_ftl_dev *dev)
4332b5bba56SArtur Paszkiewicz {
4341738488eSArtur Paszkiewicz 	int region_type;
4352d613454SMateusz Kozlowski 	uint64_t blocks;
4362b5bba56SArtur Paszkiewicz 	struct ftl_layout *layout = &dev->layout;
437c6880a39SArtur Paszkiewicz 
438b16bdc6dSArtur Paszkiewicz 	/* Initialize L2P region */
4392d613454SMateusz Kozlowski 	blocks = ftl_md_region_blocks(dev, layout->l2p.addr_size * dev->num_lbas);
4402d613454SMateusz Kozlowski 	if (layout_region_create_nvc(dev, FTL_LAYOUT_REGION_TYPE_L2P, 0, FTL_BLOCK_SIZE, blocks)) {
441b16bdc6dSArtur Paszkiewicz 		goto error;
442b16bdc6dSArtur Paszkiewicz 	}
443b16bdc6dSArtur Paszkiewicz 
4446448f336SArtur Paszkiewicz 	/* Initialize band info metadata */
445d55b9f29SMateusz Kozlowski 	if (layout_region_create_nvc(dev, FTL_LAYOUT_REGION_TYPE_BAND_MD, FTL_BAND_VERSION_CURRENT,
446b0556d4aSLukasz Lasek 				     sizeof(struct ftl_band_md), ftl_get_num_bands(dev))) {
4476448f336SArtur Paszkiewicz 		goto error;
4486448f336SArtur Paszkiewicz 	}
4496448f336SArtur Paszkiewicz 
4506448f336SArtur Paszkiewicz 	/* Initialize band info metadata mirror */
451d55b9f29SMateusz Kozlowski 	if (layout_region_create_nvc(dev, FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR, FTL_BAND_VERSION_CURRENT,
452b0556d4aSLukasz Lasek 				     sizeof(struct ftl_band_md), ftl_get_num_bands(dev))) {
4536448f336SArtur Paszkiewicz 		goto error;
4546448f336SArtur Paszkiewicz 	}
455b0556d4aSLukasz Lasek 	layout->region[FTL_LAYOUT_REGION_TYPE_BAND_MD].mirror_type = FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR;
456c6880a39SArtur Paszkiewicz 
457a68a12a4SKozlowski Mateusz 	/*
4581738488eSArtur Paszkiewicz 	 * Initialize P2L checkpointing regions
4591738488eSArtur Paszkiewicz 	 */
4601738488eSArtur Paszkiewicz 	for (region_type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN;
4611738488eSArtur Paszkiewicz 	     region_type <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX;
4621738488eSArtur Paszkiewicz 	     region_type++) {
463d55b9f29SMateusz Kozlowski 		if (layout_region_create_nvc(dev, region_type, FTL_P2L_VERSION_CURRENT, FTL_BLOCK_SIZE,
464b0556d4aSLukasz Lasek 					     layout->p2l.ckpt_pages)) {
4651738488eSArtur Paszkiewicz 			goto error;
4661738488eSArtur Paszkiewicz 		}
4671738488eSArtur Paszkiewicz 	}
4681738488eSArtur Paszkiewicz 
4691738488eSArtur Paszkiewicz 	/*
47078c3cbf4SArtur Paszkiewicz 	 * Initialize trim metadata region
47178c3cbf4SArtur Paszkiewicz 	 */
4722d613454SMateusz Kozlowski 	blocks = layout->region[FTL_LAYOUT_REGION_TYPE_L2P].current.blocks;
4732d613454SMateusz Kozlowski 	blocks = spdk_divide_round_up(blocks * sizeof(uint64_t), FTL_BLOCK_SIZE);
4742d613454SMateusz Kozlowski 	if (layout_region_create_nvc(dev, FTL_LAYOUT_REGION_TYPE_TRIM_MD, 0, FTL_BLOCK_SIZE, blocks)) {
47578c3cbf4SArtur Paszkiewicz 		goto error;
47678c3cbf4SArtur Paszkiewicz 	}
47778c3cbf4SArtur Paszkiewicz 
47878c3cbf4SArtur Paszkiewicz 	/* Initialize trim metadata mirror region */
4792d613454SMateusz Kozlowski 	if (layout_region_create_nvc(dev, FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR, 0, FTL_BLOCK_SIZE,
4802d613454SMateusz Kozlowski 				     blocks)) {
48178c3cbf4SArtur Paszkiewicz 		goto error;
48278c3cbf4SArtur Paszkiewicz 	}
483b0556d4aSLukasz Lasek 	layout->region[FTL_LAYOUT_REGION_TYPE_TRIM_MD].mirror_type = FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR;
48478c3cbf4SArtur Paszkiewicz 
48578c3cbf4SArtur Paszkiewicz 	/*
4862d613454SMateusz Kozlowski 	 * Initialize trim log region
4872d613454SMateusz Kozlowski 	 */
4882d613454SMateusz Kozlowski 	if (layout_region_create_nvc(dev, FTL_LAYOUT_REGION_TYPE_TRIM_LOG, FTL_TRIM_LOG_VERSION_CURRENT,
4892d613454SMateusz Kozlowski 				     sizeof(struct ftl_trim_log), 1)) {
4902d613454SMateusz Kozlowski 		goto error;
4912d613454SMateusz Kozlowski 	}
4922d613454SMateusz Kozlowski 
4932d613454SMateusz Kozlowski 	/* Initialize trim log mirror region */
4942d613454SMateusz Kozlowski 	if (layout_region_create_nvc(dev, FTL_LAYOUT_REGION_TYPE_TRIM_LOG_MIRROR,
4952d613454SMateusz Kozlowski 				     FTL_TRIM_LOG_VERSION_CURRENT,
4962d613454SMateusz Kozlowski 				     sizeof(struct ftl_trim_log), 1)) {
4972d613454SMateusz Kozlowski 		goto error;
4982d613454SMateusz Kozlowski 	}
4992d613454SMateusz Kozlowski 	layout->region[FTL_LAYOUT_REGION_TYPE_TRIM_LOG].mirror_type =
5002d613454SMateusz Kozlowski 		FTL_LAYOUT_REGION_TYPE_TRIM_LOG_MIRROR;
5012d613454SMateusz Kozlowski 
5022d613454SMateusz Kozlowski 	/*
503a68a12a4SKozlowski Mateusz 	 * Initialize NV Cache metadata
504a68a12a4SKozlowski Mateusz 	 */
505a68a12a4SKozlowski Mateusz 	if (0 == layout->nvc.chunk_count) {
506a68a12a4SKozlowski Mateusz 		goto error;
507a68a12a4SKozlowski Mateusz 	}
508d55b9f29SMateusz Kozlowski 	if (layout_region_create_nvc(dev, FTL_LAYOUT_REGION_TYPE_NVC_MD, FTL_NVC_VERSION_CURRENT,
509b0556d4aSLukasz Lasek 				     sizeof(struct ftl_nv_cache_chunk_md), layout->nvc.chunk_count)) {
510b0556d4aSLukasz Lasek 		goto error;
511b0556d4aSLukasz Lasek 	}
512a68a12a4SKozlowski Mateusz 
513a68a12a4SKozlowski Mateusz 	/*
514a68a12a4SKozlowski Mateusz 	 * Initialize NV Cache metadata mirror
515a68a12a4SKozlowski Mateusz 	 */
516d55b9f29SMateusz Kozlowski 	if (layout_region_create_nvc(dev, FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR, FTL_NVC_VERSION_CURRENT,
517b0556d4aSLukasz Lasek 				     sizeof(struct ftl_nv_cache_chunk_md), layout->nvc.chunk_count)) {
518b0556d4aSLukasz Lasek 		goto error;
519b0556d4aSLukasz Lasek 	}
520b0556d4aSLukasz Lasek 	layout->region[FTL_LAYOUT_REGION_TYPE_NVC_MD].mirror_type = FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR;
521a68a12a4SKozlowski Mateusz 
522*6d6179ffSMateusz Kozlowski 	if (dev->nv_cache.nvc_type->ops.setup_layout) {
523*6d6179ffSMateusz Kozlowski 		return dev->nv_cache.nvc_type->ops.setup_layout(dev);
524*6d6179ffSMateusz Kozlowski 	}
525*6d6179ffSMateusz Kozlowski 
5262b5bba56SArtur Paszkiewicz 	return 0;
5272b5bba56SArtur Paszkiewicz 
5282b5bba56SArtur Paszkiewicz error:
5292b5bba56SArtur Paszkiewicz 	FTL_ERRLOG(dev, "Insufficient NV Cache capacity to preserve metadata\n");
5302b5bba56SArtur Paszkiewicz 	return -1;
5312b5bba56SArtur Paszkiewicz }
5322b5bba56SArtur Paszkiewicz 
5332b5bba56SArtur Paszkiewicz static int
5349f42898aSLukasz Lasek layout_setup_default_base(struct spdk_ftl_dev *dev)
5352b5bba56SArtur Paszkiewicz {
5362b5bba56SArtur Paszkiewicz 	struct ftl_layout *layout = &dev->layout;
537498c39beSLukasz Lasek 	uint64_t valid_map_size;
5382b5bba56SArtur Paszkiewicz 
539498c39beSLukasz Lasek 	/* Base device layout is as follows:
540c6880a39SArtur Paszkiewicz 	 * - superblock
541c3321813SKozlowski Mateusz 	 * - data
542c6880a39SArtur Paszkiewicz 	 * - valid map
543c6880a39SArtur Paszkiewicz 	 */
544d55b9f29SMateusz Kozlowski 	if (layout_region_create_base(dev, FTL_LAYOUT_REGION_TYPE_DATA_BASE, 0, FTL_BLOCK_SIZE,
545d55b9f29SMateusz Kozlowski 				      ftl_layout_base_offset(dev))) {
546c6880a39SArtur Paszkiewicz 		return -1;
547c6880a39SArtur Paszkiewicz 	}
548c6880a39SArtur Paszkiewicz 
549498c39beSLukasz Lasek 	valid_map_size = spdk_divide_round_up(layout->base.total_blocks + layout->nvc.total_blocks, 8);
550d55b9f29SMateusz Kozlowski 	if (layout_region_create_base(dev, FTL_LAYOUT_REGION_TYPE_VALID_MAP, 0, FTL_BLOCK_SIZE,
551498c39beSLukasz Lasek 				      ftl_md_region_blocks(dev, valid_map_size))) {
552c6880a39SArtur Paszkiewicz 		return -1;
553c6880a39SArtur Paszkiewicz 	}
554c6880a39SArtur Paszkiewicz 
5552b5bba56SArtur Paszkiewicz 	return 0;
5562b5bba56SArtur Paszkiewicz }
5572b5bba56SArtur Paszkiewicz 
5589f42898aSLukasz Lasek static int
5599f42898aSLukasz Lasek layout_setup_default(struct spdk_ftl_dev *dev)
5609f42898aSLukasz Lasek {
5619f42898aSLukasz Lasek 	if (layout_setup_default_nvc(dev) || layout_setup_default_base(dev)) {
5629f42898aSLukasz Lasek 		return -1;
5639f42898aSLukasz Lasek 	}
5649f42898aSLukasz Lasek 	return 0;
5659f42898aSLukasz Lasek }
5669f42898aSLukasz Lasek 
5679f42898aSLukasz Lasek static int
5689f42898aSLukasz Lasek layout_load(struct spdk_ftl_dev *dev)
5699f42898aSLukasz Lasek {
5709f42898aSLukasz Lasek 	if (ftl_superblock_load_blob_area(dev)) {
5719f42898aSLukasz Lasek 		return -1;
5729f42898aSLukasz Lasek 	}
5739f42898aSLukasz Lasek 	if (ftl_superblock_md_layout_apply(dev)) {
5749f42898aSLukasz Lasek 		return -1;
5759f42898aSLukasz Lasek 	}
5769f42898aSLukasz Lasek 	return 0;
5779f42898aSLukasz Lasek }
5789f42898aSLukasz Lasek 
5792b5bba56SArtur Paszkiewicz int
5802b5bba56SArtur Paszkiewicz ftl_layout_setup(struct spdk_ftl_dev *dev)
5812b5bba56SArtur Paszkiewicz {
5822b5bba56SArtur Paszkiewicz 	struct ftl_layout *layout = &dev->layout;
5832b5bba56SArtur Paszkiewicz 	uint64_t i;
5842b5bba56SArtur Paszkiewicz 	uint64_t num_lbas;
5859f42898aSLukasz Lasek 	enum ftl_layout_setup_mode setup_mode;
5869f42898aSLukasz Lasek 	int rc;
5872b5bba56SArtur Paszkiewicz 
5889f42898aSLukasz Lasek 	/*
5899f42898aSLukasz Lasek 	 * SB v5 adds the ability to create MD regions dynamically, i.e. depending on the underlying device type.
5909f42898aSLukasz Lasek 	 * For compatibility reasons:
5919f42898aSLukasz Lasek 	 * 1. When upgrading from pre-v5 SB, only the legacy default layout is created.
5929f42898aSLukasz Lasek 	 *    Pre-v5: some regions were static and not stored in the SB layout. These must be created to match
5939f42898aSLukasz Lasek 	 *            the legacy default layout.
5949f42898aSLukasz Lasek 	 *    v5: all regions are stored in the SB layout. Upon the SB upgrade, the legacy default layout
5959f42898aSLukasz Lasek 	 *        is updated with pre-v5 layout stored in the SB. The whole layout is then stored in v5 SB.
5969f42898aSLukasz Lasek 	 *
5979f42898aSLukasz Lasek 	 * 2. When SB v5 or later was loaded, the layout is instantiated from the nvc and base layout blobs.
5989f42898aSLukasz Lasek 	 *    No default layout is created.
5999f42898aSLukasz Lasek 	 *
6009f42898aSLukasz Lasek 	 * 3. When the FTL layout is being created for the first time, there are no restrictions.
6019f42898aSLukasz Lasek 	 *
6029f42898aSLukasz Lasek 	 * Any new regions to be created in cases (1) and (2) can only be placed in the unallocated area
6039f42898aSLukasz Lasek 	 * of the underlying device.
6049f42898aSLukasz Lasek 	 */
6059f42898aSLukasz Lasek 
6069f42898aSLukasz Lasek 	if (dev->conf.mode & SPDK_FTL_MODE_CREATE) {
6079f42898aSLukasz Lasek 		setup_mode = FTL_LAYOUT_SETUP_MODE_NO_RESTRICT;
608845c9ae2SMateusz Kozlowski 	} else if (ftl_superblock_is_blob_area_empty(dev->sb)) {
609845c9ae2SMateusz Kozlowski 		setup_mode = FTL_LAYOUT_SETUP_MODE_LEGACY_DEFAULT;
6109f42898aSLukasz Lasek 	} else {
6119f42898aSLukasz Lasek 		setup_mode = FTL_LAYOUT_SETUP_MODE_LOAD_CURRENT;
6129f42898aSLukasz Lasek 	}
6139f42898aSLukasz Lasek 	FTL_NOTICELOG(dev, "FTL layout setup mode %d\n", (int)setup_mode);
6149f42898aSLukasz Lasek 
6159f42898aSLukasz Lasek 	/* Invalidate all regions */
6162b5bba56SArtur Paszkiewicz 	for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; ++i) {
6179f42898aSLukasz Lasek 		if (i == FTL_LAYOUT_REGION_TYPE_SB || i == FTL_LAYOUT_REGION_TYPE_SB_BASE) {
618c6880a39SArtur Paszkiewicz 			/* Super block has been already initialized */
619c6880a39SArtur Paszkiewicz 			continue;
620c6880a39SArtur Paszkiewicz 		}
621c6880a39SArtur Paszkiewicz 
6222b5bba56SArtur Paszkiewicz 		layout->region[i].mirror_type = FTL_LAYOUT_REGION_TYPE_INVALID;
6239f42898aSLukasz Lasek 		/* Mark the region inactive */
6249f42898aSLukasz Lasek 		layout->region[i].type = FTL_LAYOUT_REGION_TYPE_INVALID;
6252b5bba56SArtur Paszkiewicz 	}
6262b5bba56SArtur Paszkiewicz 
6272b5bba56SArtur Paszkiewicz 	/*
6282b5bba56SArtur Paszkiewicz 	 * Initialize L2P information
6292b5bba56SArtur Paszkiewicz 	 */
6302b5bba56SArtur Paszkiewicz 	num_lbas = get_num_user_lbas(dev);
6312b5bba56SArtur Paszkiewicz 	if (dev->num_lbas == 0) {
6322b5bba56SArtur Paszkiewicz 		assert(dev->conf.mode & SPDK_FTL_MODE_CREATE);
6332b5bba56SArtur Paszkiewicz 		dev->num_lbas = num_lbas;
634c6880a39SArtur Paszkiewicz 		dev->sb->lba_cnt = num_lbas;
6352b5bba56SArtur Paszkiewicz 	} else if (dev->num_lbas != num_lbas) {
6362b5bba56SArtur Paszkiewicz 		FTL_ERRLOG(dev, "Mismatched FTL num_lbas\n");
6372b5bba56SArtur Paszkiewicz 		return -EINVAL;
6382b5bba56SArtur Paszkiewicz 	}
6392b5bba56SArtur Paszkiewicz 	layout->l2p.addr_length = spdk_u64log2(layout->base.total_blocks + layout->nvc.total_blocks) + 1;
6402b5bba56SArtur Paszkiewicz 	layout->l2p.addr_size = layout->l2p.addr_length > 32 ? 8 : 4;
6412b5bba56SArtur Paszkiewicz 	layout->l2p.lbas_in_page = FTL_BLOCK_SIZE / layout->l2p.addr_size;
6422b5bba56SArtur Paszkiewicz 
6431738488eSArtur Paszkiewicz 	/* Setup P2L ckpt */
6444061ed11SMateusz Kozlowski 	layout->p2l.pages_per_xfer = spdk_divide_round_up(dev->xfer_size, FTL_NUM_P2L_ENTRIES_NO_VSS);
6454061ed11SMateusz Kozlowski 	layout->p2l.ckpt_pages = spdk_divide_round_up(ftl_get_num_blocks_in_band(dev),
6464061ed11SMateusz Kozlowski 				 dev->xfer_size) * layout->p2l.pages_per_xfer;
6471738488eSArtur Paszkiewicz 
648a5c04e6dSMateusz Kozlowski 	layout->nvc.chunk_data_blocks = ftl_get_num_blocks_in_band(dev);
649a5c04e6dSMateusz Kozlowski 	layout->nvc.chunk_count = layout->nvc.total_blocks / ftl_get_num_blocks_in_band(dev);
6509f42898aSLukasz Lasek 	layout->nvc.chunk_tail_md_num_blocks = ftl_nv_cache_chunk_tail_md_num_blocks(&dev->nv_cache);
6519f42898aSLukasz Lasek 
6529f42898aSLukasz Lasek 	layout->base.num_usable_blocks = ftl_get_num_blocks_in_band(dev);
6539f42898aSLukasz Lasek 	layout->base.user_blocks = ftl_band_user_blocks(dev->bands);
6549f42898aSLukasz Lasek 
6559f42898aSLukasz Lasek 	switch (setup_mode) {
656845c9ae2SMateusz Kozlowski 	case FTL_LAYOUT_SETUP_MODE_LEGACY_DEFAULT:
657845c9ae2SMateusz Kozlowski 		if (layout_setup_legacy_default(dev)) {
658845c9ae2SMateusz Kozlowski 			return -EINVAL;
659845c9ae2SMateusz Kozlowski 		}
660845c9ae2SMateusz Kozlowski 		break;
661845c9ae2SMateusz Kozlowski 
6629f42898aSLukasz Lasek 	case FTL_LAYOUT_SETUP_MODE_LOAD_CURRENT:
6639f42898aSLukasz Lasek 		if (layout_load(dev)) {
6642b5bba56SArtur Paszkiewicz 			return -EINVAL;
6652b5bba56SArtur Paszkiewicz 		}
6669f42898aSLukasz Lasek 		break;
6672b5bba56SArtur Paszkiewicz 
6689f42898aSLukasz Lasek 	case FTL_LAYOUT_SETUP_MODE_NO_RESTRICT:
6699f42898aSLukasz Lasek 		if (layout_setup_default(dev)) {
6702b5bba56SArtur Paszkiewicz 			return -EINVAL;
6712b5bba56SArtur Paszkiewicz 		}
6729f42898aSLukasz Lasek 		break;
6739f42898aSLukasz Lasek 
6749f42898aSLukasz Lasek 	default:
6759f42898aSLukasz Lasek 		ftl_abort();
6769f42898aSLukasz Lasek 		break;
6779f42898aSLukasz Lasek 	}
6782b5bba56SArtur Paszkiewicz 
6792b5bba56SArtur Paszkiewicz 	if (ftl_validate_regions(dev, layout)) {
6802b5bba56SArtur Paszkiewicz 		return -EINVAL;
6812b5bba56SArtur Paszkiewicz 	}
6822b5bba56SArtur Paszkiewicz 
6839f42898aSLukasz Lasek 	rc = ftl_superblock_store_blob_area(dev);
6849f42898aSLukasz Lasek 
6852b5bba56SArtur Paszkiewicz 	FTL_NOTICELOG(dev, "Base device capacity:         %.2f MiB\n",
6862b5bba56SArtur Paszkiewicz 		      blocks2mib(layout->base.total_blocks));
6872b5bba56SArtur Paszkiewicz 	FTL_NOTICELOG(dev, "NV cache device capacity:       %.2f MiB\n",
6882b5bba56SArtur Paszkiewicz 		      blocks2mib(layout->nvc.total_blocks));
6891738488eSArtur Paszkiewicz 	FTL_NOTICELOG(dev, "L2P entries:                    %"PRIu64"\n", dev->num_lbas);
6901738488eSArtur Paszkiewicz 	FTL_NOTICELOG(dev, "L2P address size:               %"PRIu64"\n", layout->l2p.addr_size);
6911738488eSArtur Paszkiewicz 	FTL_NOTICELOG(dev, "P2L checkpoint pages:           %"PRIu64"\n", layout->p2l.ckpt_pages);
6929f42898aSLukasz Lasek 	FTL_NOTICELOG(dev, "NV cache chunk count            %"PRIu64"\n", dev->layout.nvc.chunk_count);
6932b5bba56SArtur Paszkiewicz 
6949f42898aSLukasz Lasek 	return rc;
6952b5bba56SArtur Paszkiewicz }
6962b5bba56SArtur Paszkiewicz 
697c6880a39SArtur Paszkiewicz int
698c6880a39SArtur Paszkiewicz ftl_layout_setup_superblock(struct spdk_ftl_dev *dev)
699c6880a39SArtur Paszkiewicz {
700b0556d4aSLukasz Lasek 	const struct spdk_bdev *bdev;
701c6880a39SArtur Paszkiewicz 	struct ftl_layout *layout = &dev->layout;
702c6880a39SArtur Paszkiewicz 	struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB];
703c6880a39SArtur Paszkiewicz 	uint64_t total_blocks, offset, left;
704c6880a39SArtur Paszkiewicz 
705c6880a39SArtur Paszkiewicz 	assert(layout->md[FTL_LAYOUT_REGION_TYPE_SB] == NULL);
706c6880a39SArtur Paszkiewicz 
707b0556d4aSLukasz Lasek 	bdev = spdk_bdev_desc_get_bdev(dev->base_bdev_desc);
708b0556d4aSLukasz Lasek 	layout->base.total_blocks = spdk_bdev_get_num_blocks(bdev);
709c6880a39SArtur Paszkiewicz 
710b0556d4aSLukasz Lasek 	bdev = spdk_bdev_desc_get_bdev(dev->nv_cache.bdev_desc);
711b0556d4aSLukasz Lasek 	layout->nvc.total_blocks = spdk_bdev_get_num_blocks(bdev);
712b0556d4aSLukasz Lasek 
713b0556d4aSLukasz Lasek 	/* Initialize superblock region */
7149f42898aSLukasz Lasek 	if (layout_region_create_nvc(dev, FTL_LAYOUT_REGION_TYPE_SB, FTL_SB_VERSION_CURRENT,
715b0556d4aSLukasz Lasek 				     superblock_region_size(dev), 1)) {
716b0556d4aSLukasz Lasek 		FTL_ERRLOG(dev, "Error when setting up primary super block\n");
717b0556d4aSLukasz Lasek 		return -1;
718b0556d4aSLukasz Lasek 	}
719c6880a39SArtur Paszkiewicz 
720c6880a39SArtur Paszkiewicz 	assert(region->bdev_desc != NULL);
721c6880a39SArtur Paszkiewicz 	assert(region->ioch != NULL);
722498c39beSLukasz Lasek 	assert(region->current.offset == 0);
723c6880a39SArtur Paszkiewicz 
7249f42898aSLukasz Lasek 	if (layout_region_create_base(dev, FTL_LAYOUT_REGION_TYPE_SB_BASE, FTL_SB_VERSION_CURRENT,
725498c39beSLukasz Lasek 				      superblock_region_size(dev), 1)) {
726498c39beSLukasz Lasek 		FTL_ERRLOG(dev, "Error when setting up secondary super block\n");
727498c39beSLukasz Lasek 		return -1;
728498c39beSLukasz Lasek 	}
7296394849aSMateusz Kozlowski 	layout->region[FTL_LAYOUT_REGION_TYPE_SB].mirror_type = FTL_LAYOUT_REGION_TYPE_SB_BASE;
7306394849aSMateusz Kozlowski 
731c6880a39SArtur Paszkiewicz 	region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB_BASE];
732498c39beSLukasz Lasek 	assert(region->current.offset == 0);
733c6880a39SArtur Paszkiewicz 
734c6880a39SArtur Paszkiewicz 	/* Check if SB can be stored at the end of base device */
735c6880a39SArtur Paszkiewicz 	total_blocks = spdk_bdev_get_num_blocks(
736c6880a39SArtur Paszkiewicz 			       spdk_bdev_desc_get_bdev(dev->base_bdev_desc));
737c6880a39SArtur Paszkiewicz 	offset = region->current.offset + region->current.blocks;
738c6880a39SArtur Paszkiewicz 	left = total_blocks - offset;
739c6880a39SArtur Paszkiewicz 	if ((left > total_blocks) || (offset > total_blocks)) {
740c6880a39SArtur Paszkiewicz 		FTL_ERRLOG(dev, "Error when setup base device super block\n");
741c6880a39SArtur Paszkiewicz 		return -1;
742c6880a39SArtur Paszkiewicz 	}
743c6880a39SArtur Paszkiewicz 
744c6880a39SArtur Paszkiewicz 	return 0;
745c6880a39SArtur Paszkiewicz }
746f725ca81SArtur Paszkiewicz 
7479f42898aSLukasz Lasek int
7489f42898aSLukasz Lasek ftl_layout_clear_superblock(struct spdk_ftl_dev *dev)
7499f42898aSLukasz Lasek {
7509f42898aSLukasz Lasek 	int rc;
7519f42898aSLukasz Lasek 
7529f42898aSLukasz Lasek 	rc = ftl_layout_tracker_bdev_rm_region(dev->nvc_layout_tracker, FTL_LAYOUT_REGION_TYPE_SB,
7539f42898aSLukasz Lasek 					       FTL_SB_VERSION_CURRENT);
7549f42898aSLukasz Lasek 	if (rc) {
7559f42898aSLukasz Lasek 		return rc;
7569f42898aSLukasz Lasek 	}
7579f42898aSLukasz Lasek 
7589f42898aSLukasz Lasek 	return ftl_layout_tracker_bdev_rm_region(dev->base_layout_tracker, FTL_LAYOUT_REGION_TYPE_SB_BASE,
7599f42898aSLukasz Lasek 			FTL_SB_VERSION_CURRENT);
7609f42898aSLukasz Lasek }
7619f42898aSLukasz Lasek 
7622b5bba56SArtur Paszkiewicz void
7632b5bba56SArtur Paszkiewicz ftl_layout_dump(struct spdk_ftl_dev *dev)
7642b5bba56SArtur Paszkiewicz {
76530ef80cdSMateusz Kozlowski 	struct ftl_layout_region *reg;
76630ef80cdSMateusz Kozlowski 	enum ftl_layout_region_type i;
767102d266dSKozlowski Mateusz 
7682b5bba56SArtur Paszkiewicz 	FTL_NOTICELOG(dev, "NV cache layout:\n");
7692b5bba56SArtur Paszkiewicz 	for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; ++i) {
77030ef80cdSMateusz Kozlowski 		reg = ftl_layout_region_get(dev, i);
77130ef80cdSMateusz Kozlowski 		if (reg && reg->bdev_desc == dev->nv_cache.bdev_desc) {
77230ef80cdSMateusz Kozlowski 			dump_region(dev, reg);
7732b5bba56SArtur Paszkiewicz 		}
7742b5bba56SArtur Paszkiewicz 	}
775102d266dSKozlowski Mateusz 	FTL_NOTICELOG(dev, "Base device layout:\n");
7762b5bba56SArtur Paszkiewicz 	for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; ++i) {
77730ef80cdSMateusz Kozlowski 		reg = ftl_layout_region_get(dev, i);
77830ef80cdSMateusz Kozlowski 		if (reg && reg->bdev_desc == dev->base_bdev_desc) {
77930ef80cdSMateusz Kozlowski 			dump_region(dev, reg);
7802b5bba56SArtur Paszkiewicz 		}
7812b5bba56SArtur Paszkiewicz 	}
7822b5bba56SArtur Paszkiewicz }
783102d266dSKozlowski Mateusz 
784102d266dSKozlowski Mateusz uint64_t
785102d266dSKozlowski Mateusz ftl_layout_base_md_blocks(struct spdk_ftl_dev *dev)
786102d266dSKozlowski Mateusz {
787102d266dSKozlowski Mateusz 	const struct spdk_bdev *bdev;
788102d266dSKozlowski Mateusz 	uint64_t md_blocks = 0, total_blocks = 0;
789102d266dSKozlowski Mateusz 
790102d266dSKozlowski Mateusz 	bdev = spdk_bdev_desc_get_bdev(dev->base_bdev_desc);
791102d266dSKozlowski Mateusz 	total_blocks += spdk_bdev_get_num_blocks(bdev);
792102d266dSKozlowski Mateusz 
793102d266dSKozlowski Mateusz 	bdev = spdk_bdev_desc_get_bdev(dev->nv_cache.bdev_desc);
794102d266dSKozlowski Mateusz 	total_blocks += spdk_bdev_get_num_blocks(bdev);
795102d266dSKozlowski Mateusz 
796102d266dSKozlowski Mateusz 	/* Count space needed for validity map */
797b0556d4aSLukasz Lasek 	md_blocks += ftl_md_region_blocks(dev, spdk_divide_round_up(total_blocks, 8));
798102d266dSKozlowski Mateusz 
799102d266dSKozlowski Mateusz 	/* Count space needed for superblock */
800102d266dSKozlowski Mateusz 	md_blocks += superblock_region_blocks(dev);
801102d266dSKozlowski Mateusz 	return md_blocks;
802102d266dSKozlowski Mateusz }
803e8cbab9eSMateusz Kozlowski 
804e8cbab9eSMateusz Kozlowski struct layout_blob_entry {
805e8cbab9eSMateusz Kozlowski 	uint32_t type;
806e8cbab9eSMateusz Kozlowski 	uint64_t entry_size;
807e8cbab9eSMateusz Kozlowski 	uint64_t num_entries;
808e8cbab9eSMateusz Kozlowski } __attribute__((packed));
809e8cbab9eSMateusz Kozlowski 
810e8cbab9eSMateusz Kozlowski size_t
811e8cbab9eSMateusz Kozlowski ftl_layout_blob_store(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_buf_sz)
812e8cbab9eSMateusz Kozlowski {
813e8cbab9eSMateusz Kozlowski 	struct layout_blob_entry *blob_entry = blob_buf;
814e8cbab9eSMateusz Kozlowski 	struct ftl_layout_region *reg;
815e8cbab9eSMateusz Kozlowski 	enum ftl_layout_region_type reg_type;
816e8cbab9eSMateusz Kozlowski 	size_t blob_sz = 0;
817e8cbab9eSMateusz Kozlowski 
818e8cbab9eSMateusz Kozlowski 	for (reg_type = 0; reg_type < FTL_LAYOUT_REGION_TYPE_MAX; reg_type++) {
819e8cbab9eSMateusz Kozlowski 		if (blob_sz + sizeof(*blob_entry) > blob_buf_sz) {
820e8cbab9eSMateusz Kozlowski 			return 0;
821e8cbab9eSMateusz Kozlowski 		}
822e8cbab9eSMateusz Kozlowski 
823e8cbab9eSMateusz Kozlowski 		reg = &dev->layout.region[reg_type];
824e8cbab9eSMateusz Kozlowski 		blob_entry->type = reg_type;
825e8cbab9eSMateusz Kozlowski 		blob_entry->entry_size = reg->entry_size;
826e8cbab9eSMateusz Kozlowski 		blob_entry->num_entries = reg->num_entries;
827e8cbab9eSMateusz Kozlowski 
828e8cbab9eSMateusz Kozlowski 		blob_entry++;
829e8cbab9eSMateusz Kozlowski 		blob_sz += sizeof(*blob_entry);
830e8cbab9eSMateusz Kozlowski 	}
831e8cbab9eSMateusz Kozlowski 
832e8cbab9eSMateusz Kozlowski 	return blob_sz;
833e8cbab9eSMateusz Kozlowski }
834e8cbab9eSMateusz Kozlowski 
835e8cbab9eSMateusz Kozlowski int
836e8cbab9eSMateusz Kozlowski ftl_layout_blob_load(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_sz)
837e8cbab9eSMateusz Kozlowski {
838e8cbab9eSMateusz Kozlowski 	struct layout_blob_entry *blob_entry = blob_buf;
839e8cbab9eSMateusz Kozlowski 	size_t blob_entry_num = blob_sz / sizeof(*blob_entry);
840e8cbab9eSMateusz Kozlowski 	struct layout_blob_entry *blob_entry_end = blob_entry + blob_entry_num;
841e8cbab9eSMateusz Kozlowski 	struct ftl_layout_region *reg;
842e8cbab9eSMateusz Kozlowski 
843e8cbab9eSMateusz Kozlowski 	if (blob_sz % sizeof(*blob_entry) != 0) {
844e8cbab9eSMateusz Kozlowski 		/* Invalid blob size */
845e8cbab9eSMateusz Kozlowski 		return -1;
846e8cbab9eSMateusz Kozlowski 	}
847e8cbab9eSMateusz Kozlowski 
848e8cbab9eSMateusz Kozlowski 	for (; blob_entry < blob_entry_end; blob_entry++) {
849e8cbab9eSMateusz Kozlowski 		/* Verify the type */
850e8cbab9eSMateusz Kozlowski 		if (blob_entry->type >= FTL_LAYOUT_REGION_TYPE_MAX) {
851e8cbab9eSMateusz Kozlowski 			return -1;
852e8cbab9eSMateusz Kozlowski 		}
853e8cbab9eSMateusz Kozlowski 
854e8cbab9eSMateusz Kozlowski 		/* Load the entry */
855e8cbab9eSMateusz Kozlowski 		reg = &dev->layout.region[blob_entry->type];
856e8cbab9eSMateusz Kozlowski 		reg->entry_size = blob_entry->entry_size;
857e8cbab9eSMateusz Kozlowski 		reg->num_entries = blob_entry->num_entries;
858e8cbab9eSMateusz Kozlowski 	}
859e8cbab9eSMateusz Kozlowski 
860e8cbab9eSMateusz Kozlowski 	return 0;
861e8cbab9eSMateusz Kozlowski }
8625555d51cSLukasz Lasek 
8635555d51cSLukasz Lasek void
8645555d51cSLukasz Lasek ftl_layout_upgrade_add_region_placeholder(struct spdk_ftl_dev *dev,
8655555d51cSLukasz Lasek 		struct ftl_layout_tracker_bdev *layout_tracker, enum ftl_layout_region_type reg_type)
8665555d51cSLukasz Lasek {
8675555d51cSLukasz Lasek 	const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
8685555d51cSLukasz Lasek 
8695555d51cSLukasz Lasek 	ftl_layout_tracker_bdev_find_next_region(layout_tracker, reg_type, &reg_search_ctx);
8705555d51cSLukasz Lasek 	if (reg_search_ctx) {
8715555d51cSLukasz Lasek 		return;
8725555d51cSLukasz Lasek 	}
8735555d51cSLukasz Lasek 
8745555d51cSLukasz Lasek 	dev->layout.region[reg_type].type = reg_type;
8755555d51cSLukasz Lasek 	dev->layout.region[reg_type].current.version = 0;
8765555d51cSLukasz Lasek 	dev->layout.region[reg_type].current.offset = UINT64_MAX;
8775555d51cSLukasz Lasek 	dev->layout.region[reg_type].current.blocks = 0;
8785555d51cSLukasz Lasek }
879