xref: /spdk/lib/ftl/ftl_layout.h (revision 95d6c9fac17572b107042103439aafd696d60b0e)
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 #ifndef FTL_LAYOUT_H
8 #define FTL_LAYOUT_H
9 
10 #include "spdk/stdinc.h"
11 
12 struct spdk_ftl_dev;
13 struct ftl_md;
14 struct ftl_layout_tracker_bdev;
15 
16 #define FTL_LAYOUT_REGION_TYPE_P2L_COUNT \
17 	(FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX - FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN + 1)
18 
19 #define FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_COUNT \
20 	(FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MAX - FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MIN + 1)
21 
22 enum ftl_layout_region_type {
23 	/* Superblock describing the basic FTL information */
24 	FTL_LAYOUT_REGION_TYPE_SB = 0,
25 	/* Mirrored instance of the superblock on the base device */
26 	FTL_LAYOUT_REGION_TYPE_SB_BASE = 1,
27 	/* If using cached L2P, this region stores the serialized instance of it */
28 	FTL_LAYOUT_REGION_TYPE_L2P = 2,
29 
30 	/* State of bands */
31 	FTL_LAYOUT_REGION_TYPE_BAND_MD = 3,
32 	/* Mirrored instance of bands state */
33 	FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR = 4,
34 
35 	/* Map of valid physical addresses, used for more efficient garbage collection */
36 	FTL_LAYOUT_REGION_TYPE_VALID_MAP = 5,
37 
38 	/* State of chunks */
39 	FTL_LAYOUT_REGION_TYPE_NVC_MD = 6,
40 	/* Mirrored instance of the state of chunks */
41 	FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR = 7,
42 
43 	/* User data region on the nv cache device */
44 	FTL_LAYOUT_REGION_TYPE_DATA_NVC = 8,
45 
46 	/* User data region on the base device */
47 	FTL_LAYOUT_REGION_TYPE_DATA_BASE = 9,
48 
49 	/* P2L checkpointing allows for emulation of VSS on base device.
50 	 * 4 entries are needed - 2 for each writer */
51 	FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC = 10,
52 	FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC,
53 	FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC_NEXT = 11,
54 	FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP = 12,
55 	FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP_NEXT = 13,
56 	FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP_NEXT,
57 
58 	/* Information about trimmed space in FTL */
59 	FTL_LAYOUT_REGION_TYPE_TRIM_MD = 14,
60 	/* Mirrored information about trim */
61 	FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR = 15,
62 
63 	/* Max layout region for metadata prior to the major upgrade improvements */
64 	FTL_LAYOUT_REGION_TYPE_MAX_V3 = 16,
65 
66 	/* Log for the transaction of trim */
67 	FTL_LAYOUT_REGION_TYPE_TRIM_LOG = 16,
68 	/* Mirror log for the transaction of trim */
69 	FTL_LAYOUT_REGION_TYPE_TRIM_LOG_MIRROR = 17,
70 	/* P2L IO logs for non-VSS cache */
71 	FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MIN = 18,
72 	FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MAX = 19,
73 
74 	FTL_LAYOUT_REGION_TYPE_MAX = 20
75 };
76 
77 /* last nvc/base region in terms of lba address space */
78 #define FTL_LAYOUT_REGION_LAST_NVC FTL_LAYOUT_REGION_TYPE_DATA_NVC
79 #define FTL_LAYOUT_REGION_LAST_BASE FTL_LAYOUT_REGION_TYPE_VALID_MAP
80 #define FTL_LAYOUT_REGION_TYPE_FREE_BASE (UINT32_MAX - 2)
81 #define FTL_LAYOUT_REGION_TYPE_FREE_NVC (UINT32_MAX - 1)
82 #define FTL_LAYOUT_REGION_TYPE_FREE (UINT32_MAX - 1)
83 #define FTL_LAYOUT_REGION_TYPE_INVALID (UINT32_MAX)
84 
85 struct ftl_layout_region_descriptor {
86 	/* Current version of the region */
87 	uint64_t version;
88 
89 	/* Offset in FTL_BLOCK_SIZE unit where the region exists on the device */
90 	uint64_t offset;
91 
92 	/* Number of blocks in FTL_BLOCK_SIZE unit */
93 	uint64_t blocks;
94 };
95 
96 /* Data or metadata region on devices */
97 struct ftl_layout_region {
98 	/* Name of the region */
99 	const char *name;
100 
101 	/* Region type */
102 	enum ftl_layout_region_type type;
103 
104 	/* Mirror region type - a region may be mirrored for higher durability */
105 	enum ftl_layout_region_type mirror_type;
106 
107 	/* Current region version */
108 	struct ftl_layout_region_descriptor current;
109 
110 	/* Number of blocks in FTL_BLOCK_SIZE unit of a single entry.
111 	 * A metadata region may be subdivided into multiple smaller entries.
112 	 * Eg. there's one region describing all bands, but you may be able to access
113 	 * metadata of a single one.
114 	 */
115 	uint64_t entry_size;
116 
117 	/* Number of entries */
118 	uint64_t num_entries;
119 
120 	/* VSS MD size or 0:disable VSS MD */
121 	uint64_t vss_blksz;
122 
123 	/* Device of region */
124 	struct spdk_bdev_desc *bdev_desc;
125 
126 	/* IO channel of region */
127 	struct spdk_io_channel *ioch;
128 };
129 
130 /*
131  * This structure describes the geometry (space organization) of FTL
132  */
133 struct ftl_layout {
134 	/* Organization for base device */
135 	struct {
136 		uint64_t total_blocks;
137 		uint64_t num_usable_blocks;
138 		uint64_t user_blocks;
139 	} base;
140 
141 	/* Organization for NV cache */
142 	struct {
143 		uint64_t total_blocks;
144 		uint64_t chunk_data_blocks;
145 		uint64_t chunk_count;
146 		uint64_t chunk_tail_md_num_blocks;
147 	} nvc;
148 
149 	/* Information corresponding to L2P */
150 	struct {
151 		/* Address length in bits */
152 		uint64_t addr_length;
153 		/* Address size in bytes */
154 		uint64_t addr_size;
155 		/* Number of LBAS in memory page */
156 		uint64_t lbas_in_page;
157 	} l2p;
158 
159 	/* Organization of P2L checkpoints */
160 	struct {
161 		/* Number of P2L checkpoint pages */
162 		uint64_t ckpt_pages;
163 		/* Number of P2L checkpoint pages to be written per write unit size */
164 		uint64_t pages_per_xfer;
165 	} p2l;
166 
167 	struct ftl_layout_region region[FTL_LAYOUT_REGION_TYPE_MAX];
168 
169 	/* Metadata object corresponding to the regions */
170 	struct ftl_md *md[FTL_LAYOUT_REGION_TYPE_MAX];
171 };
172 
173 /**
174  * @brief FTL MD layout operations interface
175  */
176 struct ftl_md_layout_ops {
177 	/**
178 	 * @brief Create a new MD region
179 	 *
180 	 * @param dev ftl device
181 	 * @param reg_type region type
182 	 * @param reg_version region version
183 	 * @param entry_size MD entry size in bytes
184 	 * @param entry_count number of MD entries
185 	 *
186 	 * @retval 0 on success
187 	 * @retval -1 on fault
188 	 */
189 	int (*region_create)(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type,
190 			     uint32_t reg_version, size_t reg_blks);
191 
192 	int (*region_open)(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type,
193 			   uint32_t reg_version, size_t entry_size, size_t entry_count, struct ftl_layout_region *region);
194 };
195 
196 uint64_t ftl_layout_upgrade_get_latest_version(enum ftl_layout_region_type reg_type);
197 
198 /**
199  * @brief Get number of blocks required to store an MD region
200  *
201  * @param dev ftl device
202  * @param bytes size of the MD region in bytes
203  *
204  * @retval Number of blocks required to store an MD region
205  */
206 uint64_t ftl_md_region_blocks(struct spdk_ftl_dev *dev, uint64_t bytes);
207 
208 /**
209  * @brief Get number of blocks for md_region aligned to a common value
210  *
211  * @param dev ftl device
212  * @param blocks size of the MD region in blocks
213  *
214  * @retval Aligned number of blocks required to store an MD region
215  */
216 uint64_t ftl_md_region_align_blocks(struct spdk_ftl_dev *dev, uint64_t blocks);
217 
218 /**
219  * @brief Get name of an MD region
220  *
221  * @param reg_type MD region type
222  *
223  * @return Name of the MD region specified
224  */
225 const char *ftl_md_region_name(enum ftl_layout_region_type reg_type);
226 
227 /**
228  * @brief Setup FTL layout
229  */
230 int ftl_layout_setup(struct spdk_ftl_dev *dev);
231 
232 /**
233  * @brief Setup FTL layout of a superblock
234  */
235 int ftl_layout_setup_superblock(struct spdk_ftl_dev *dev);
236 
237 /**
238  * @brief Clear the superblock from the layout. Used after failure of shared memory files verification causes a retry.
239  */
240 int ftl_layout_clear_superblock(struct spdk_ftl_dev *dev);
241 
242 void ftl_layout_dump(struct spdk_ftl_dev *dev);
243 int ftl_validate_regions(struct spdk_ftl_dev *dev, struct ftl_layout *layout);
244 
245 /**
246  * @brief Get number of blocks required to store metadata on bottom device
247  */
248 uint64_t ftl_layout_base_md_blocks(struct spdk_ftl_dev *dev);
249 
250 /**
251  * @brief Get the FTL layout region
252  *
253  * @param dev FTL device
254  * @param reg_type type of the layout region
255  *
256  * @return pointer to the layout region if region was created or NULL, if not created
257  */
258 struct ftl_layout_region *ftl_layout_region_get(struct spdk_ftl_dev *dev,
259 		enum ftl_layout_region_type reg_type);
260 
261 /**
262  * @brief Store the layout data in the blob
263  *
264  * @param dev FTL device
265  * @param blob_buf Blob buffer where the layout will be stored
266  * @param blob_buf_sz Size of the blob buffer in bytes
267  *
268  * @return Number of bytes the stored blob entries take up. 0 if calculated value would exceed blob_buf_sz.
269  */
270 size_t ftl_layout_blob_store(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_buf_sz);
271 
272 /**
273  * @brief Load the layout data from the blob
274  *
275  * @param dev FTL device
276  * @param blob_buf Blob buffer from which the layout will be loaded
277  * @param blob_sz Size of the blob buffer in bytes
278  *
279  * @return 0 on success, -1 on failure
280  */
281 int ftl_layout_blob_load(struct spdk_ftl_dev *dev, void *blob_buf, size_t blob_sz);
282 
283 uint64_t ftl_layout_base_offset(struct spdk_ftl_dev *dev);
284 
285 /**
286  * @brief Adds a new region entry to the layout
287  *
288  * Any offset and length are not explicitly assigned yet, used to define any new metadata in the layout,
289  * before the exact sizes are calculated.
290  *
291  * @param dev FTL device
292  * @param layout_tracker Tracker of the base/nvc bdev
293  * @param reg_type type of the layout region
294  * @return int 0: add region successful, -1 otherwise
295  */
296 void ftl_layout_upgrade_add_region_placeholder(struct spdk_ftl_dev *dev,
297 		struct ftl_layout_tracker_bdev *layout_tracker, enum ftl_layout_region_type reg_type);
298 
299 /**
300  * @brief Removes the given metadata region from the layout
301  *
302  * Used to remove regions that are no longer utilized in FTL
303  *
304  * @param dev FTL device
305  * @param layout_tracker Tracker of the base/nvc bdev
306  * @param reg_type type of the layout region
307  * @param reg_ver region version to be dropped
308  * @return int 0: drop region successful, -1 otherwise
309  */
310 int ftl_layout_upgrade_drop_region(struct spdk_ftl_dev *dev,
311 				   struct ftl_layout_tracker_bdev *layout_tracker, enum ftl_layout_region_type reg_type,
312 				   uint32_t reg_ver);
313 
314 #endif /* FTL_LAYOUT_H */
315