xref: /spdk/lib/ftl/ftl_internal.h (revision d4d015a572e1af7b2818e44218c1e661a61545ec)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2022 Intel Corporation.
3  *   Copyright 2023 Solidigm All Rights Reserved
4  *   All rights reserved.
5  */
6 
7 #ifndef FTL_INTERNAL_H
8 #define FTL_INTERNAL_H
9 
10 #include "spdk/stdinc.h"
11 #include "spdk/crc32.h"
12 #include "spdk/util.h"
13 #include "spdk/uuid.h"
14 #include "spdk/ftl.h"
15 
16 #include "utils/ftl_bitmap.h"
17 #include "utils/ftl_md.h"
18 
19 /* Marks address as invalid */
20 #define FTL_ADDR_INVALID	((ftl_addr)-1)
21 /* Marks LBA as invalid */
22 #define FTL_LBA_INVALID		((uint64_t)-1)
23 /* Smallest data unit size */
24 #define FTL_BLOCK_SIZE		4096ULL
25 
26 #define FTL_P2L_VERSION_0	0
27 #define FTL_P2L_VERSION_1	1
28 #define FTL_P2L_VERSION_2	2
29 
30 #define FTL_P2L_VERSION_CURRENT FTL_P2L_VERSION_2
31 
32 #define FTL_P2L_LOG_VERSION_0	0
33 
34 #define FTL_P2L_LOG_VERSION_CURRENT FTL_P2L_LOG_VERSION_0
35 
36 /*
37  * This type represents address in the ftl address space. Values from 0 to based bdev size are
38  * mapped directly to base device lbas. Values above that represent nv cache lbas.
39  */
40 typedef uint64_t ftl_addr;
41 
42 struct spdk_ftl_dev;
43 
44 enum ftl_md_type {
45 	FTL_MD_TYPE_BAND,
46 	FTL_MD_TYPE_CHUNK
47 };
48 
49 enum ftl_band_type {
50 	FTL_BAND_TYPE_GC = 1,
51 	FTL_BAND_TYPE_COMPACTION
52 };
53 
54 enum ftl_md_status {
55 	FTL_MD_SUCCESS,
56 	/* Metadata read failure */
57 	FTL_MD_IO_FAILURE,
58 	/* Invalid version */
59 	FTL_MD_INVALID_VER,
60 	/* UUID doesn't match */
61 	FTL_MD_NO_MD,
62 	/* UUID and version matches but CRC doesn't */
63 	FTL_MD_INVALID_CRC,
64 	/* Vld or p2l map size doesn't match */
65 	FTL_MD_INVALID_SIZE
66 };
67 
68 struct ftl_p2l_map_entry {
69 	uint64_t lba;
70 	uint64_t seq_id;
71 };
72 
73 /* Number of p2l entries that could be stored in a single block for bands */
74 #define FTL_NUM_LBA_IN_BLOCK	(FTL_BLOCK_SIZE / sizeof(struct ftl_p2l_map_entry))
75 
76 /*
77  * Mapping of physical (actual location on disk) to logical (user's POV) addresses. Used in two main scenarios:
78  * - during relocation FTL needs to pin L2P pages (this allows to check which pages to pin) and move still valid blocks
79  * (valid map allows for preliminary elimination of invalid physical blocks, but user data could invalidate a location
80  * during read/write operation, so actual comparison against L2P needs to be done)
81  * - After dirty shutdown the state of the L2P is unknown and needs to be rebuilt - it is done by applying all P2L, taking
82  * into account ordering of user writes
83  */
84 struct ftl_p2l_map {
85 	/* Number of valid LBAs */
86 	size_t					num_valid;
87 
88 	/* P2L map's reference count, prevents premature release of resources during dirty shutdown recovery for open bands */
89 	size_t					ref_cnt;
90 
91 	/* Bitmap of valid LBAs */
92 	struct ftl_bitmap			*valid;
93 
94 	/* P2L map (only valid for open/relocating bands) */
95 	union {
96 		struct ftl_p2l_map_entry	*band_map;
97 		void				*chunk_map;
98 	};
99 
100 	/* DMA buffer for region's metadata entry */
101 	union {
102 		struct ftl_band_md		*band_dma_md;
103 
104 		struct ftl_nv_cache_chunk_md	*chunk_dma_md;
105 	};
106 
107 	/* P2L checkpointing region */
108 	struct ftl_p2l_ckpt			*p2l_ckpt;
109 };
110 
111 struct ftl_p2l_sync_ctx {
112 	struct ftl_band *band;
113 	uint64_t	xfer_start;
114 	uint64_t	xfer_end;
115 	int		md_region;
116 };
117 
118 struct ftl_p2l_ckpt_page {
119 	struct ftl_p2l_map_entry map[FTL_NUM_LBA_IN_BLOCK];
120 };
121 
122 struct ftl_p2l_ckpt_page_no_vss {
123 	union ftl_md_vss metadata;
124 	struct ftl_p2l_map_entry map[FTL_NUM_LBA_IN_BLOCK - sizeof(union ftl_md_vss) / sizeof(
125 								  struct ftl_p2l_map_entry)];
126 } __attribute__((packed));
127 SPDK_STATIC_ASSERT(sizeof(struct ftl_p2l_ckpt_page_no_vss) == FTL_BLOCK_SIZE,
128 		   "ftl_p2l_ckpt_page_no_vss incorrect size");
129 
130 #define FTL_NUM_P2L_ENTRIES_NO_VSS (SPDK_COUNTOF_MEMBER(struct ftl_p2l_ckpt_page_no_vss, map))
131 
132 #define FTL_TRIM_LOG_VERSION_0		0
133 #define FTL_TRIM_LOG_VERSION_1		1
134 #define FTL_TRIM_LOG_VERSION_CURRENT	FTL_TRIM_LOG_VERSION_1
135 
136 struct ftl_trim_log {
137 	union ftl_md_vss hdr;
138 	char reserved[FTL_BLOCK_SIZE - sizeof(union ftl_md_vss)];
139 };
140 SPDK_STATIC_ASSERT(sizeof(struct ftl_trim_log) == FTL_BLOCK_SIZE, "Invalid trim log page size");
141 
142 struct ftl_p2l_ckpt;
143 struct ftl_p2l_log;
144 struct ftl_band;
145 struct spdk_ftl_dev;
146 struct ftl_mngt_process;
147 struct ftl_io;
148 struct ftl_rq;
149 
150 int ftl_p2l_ckpt_init(struct spdk_ftl_dev *dev);
151 
152 void ftl_p2l_ckpt_deinit(struct spdk_ftl_dev *dev);
153 
154 void ftl_p2l_ckpt_issue(struct ftl_rq *rq);
155 
156 struct ftl_p2l_ckpt *ftl_p2l_ckpt_acquire(struct spdk_ftl_dev *dev);
157 
158 struct ftl_p2l_ckpt *ftl_p2l_ckpt_acquire_region_type(struct spdk_ftl_dev *dev,
159 		uint32_t region_type);
160 
161 void ftl_p2l_ckpt_release(struct spdk_ftl_dev *dev, struct ftl_p2l_ckpt *ckpt);
162 
163 enum ftl_layout_region_type ftl_p2l_ckpt_region_type(const struct ftl_p2l_ckpt *ckpt);
164 
165 #if defined(DEBUG)
166 void ftl_p2l_validate_ckpt(struct ftl_band *band);
167 #else
168 static inline void
169 ftl_p2l_validate_ckpt(struct ftl_band *band)
170 {
171 }
172 #endif
173 
174 uint64_t ftl_mngt_p2l_ckpt_get_seq_id(struct spdk_ftl_dev *dev, int md_region);
175 
176 int ftl_mngt_p2l_ckpt_restore(struct ftl_band *band, uint32_t md_region, uint64_t seq_id);
177 
178 int ftl_mngt_p2l_ckpt_restore_clean(struct ftl_band *band);
179 
180 void ftl_mngt_p2l_ckpt_restore_shm_clean(struct ftl_band *band);
181 
182 void ftl_mngt_persist_bands_p2l(struct ftl_mngt_process *mngt);
183 
184 struct ftl_reloc *ftl_reloc_init(struct spdk_ftl_dev *dev);
185 
186 void ftl_reloc_free(struct ftl_reloc *reloc);
187 
188 void ftl_reloc(struct ftl_reloc *reloc);
189 
190 void ftl_reloc_halt(struct ftl_reloc *reloc);
191 
192 void ftl_reloc_resume(struct ftl_reloc *reloc);
193 
194 bool ftl_reloc_is_halted(const struct ftl_reloc *reloc);
195 
196 /**
197  * P2L IO log
198  */
199 /*
200  * @brief Initialize P2L IO log
201  *
202  * @param dev FTL device
203  *
204  * @return Initialization result
205  */
206 int ftl_p2l_log_init(struct spdk_ftl_dev *dev);
207 
208 /**
209  * @brief Deinitialize P2L IO log
210  *
211  * @param dev FTL device
212  */
213 void ftl_p2l_log_deinit(struct spdk_ftl_dev *dev);
214 
215 /**
216  * @brief Get number of blocks required in FTL MD object to store P2L IO log
217  *
218  * @param dev FTL device
219  * @param write_unit_blocks number of blocks in a write unit
220  * @param max_user_data_blocks maximum number of user data blocks within a chunk/band
221  *
222  * @return Number of blocks required
223  */
224 uint64_t ftl_p2l_log_get_md_blocks_required(struct spdk_ftl_dev *dev,
225 		uint64_t write_unit_blocks,
226 		uint64_t max_user_data_blocks);
227 
228 /**
229  * @brief Add an IO to the P2L IO log
230  *
231  * @param p2l P2L IO log
232  * @param io The IO to be logged
233  */
234 void ftl_p2l_log_io(struct ftl_p2l_log *p2l, struct ftl_io *io);
235 
236 /**
237  * @brief Flush the P2L IO logs
238  *
239  * @param dev FTL device
240  */
241 void ftl_p2l_log_flush(struct spdk_ftl_dev *dev);
242 
243 /**
244  * @brief Callback function invoked when IO is logged
245  *
246  * @param io IO that P2L logging was finished
247  */
248 typedef void (*ftl_p2l_log_cb)(struct ftl_io *io);
249 
250 /**
251  * @brief Get layout region type corresponding to the specific P2L log
252  *
253  * @param p2l P2L log
254  *
255  * @return Layout region type
256  */
257 enum ftl_layout_region_type ftl_p2l_log_type(struct ftl_p2l_log *p2l);
258 
259 /**
260  * @brief Acquire P2L IO log
261  *
262  * @param dev FTL device
263  * @param seq_id Sequence ID of the P2L IO log
264  * @param cb Callback function invoked when IO logging is finished
265  *
266  * @return The P2L IO log
267  */
268 struct ftl_p2l_log *ftl_p2l_log_acquire(struct spdk_ftl_dev *dev,
269 					uint64_t seq_id,
270 					ftl_p2l_log_cb cb);
271 
272 /**
273  * @brief Release P2L IO log
274  *
275  * @param dev FTL device
276  * @param p2l P2L IO log to be released
277  */
278 void ftl_p2l_log_release(struct spdk_ftl_dev *dev, struct ftl_p2l_log *p2l);
279 
280 /**
281  * @brief P2L Log read callback
282  *
283  * @param dev FTL device
284  * @param cb_arg The callback argument
285  * @param lba LBA value of P2L log entry
286  * @param addr Physical address of P2L log entry
287  * @param seq_id Sequence ID of P2L log entry
288  *
289  * @retval 0 Continue reading
290  * @retval Non-zero Stop reading
291  */
292 typedef int (*ftl_p2l_log_rd_cb)(struct spdk_ftl_dev *dev, void *cb_arg,
293 				 uint64_t lba, ftl_addr addr, uint64_t seq_id);
294 
295 /**
296  * @brief Read P2L IO log
297  *
298  * @param dev FTL device
299  * @param type The P2L IO log layout region type
300  * @param seq_id The sequence number of the log
301  * @param cb_fn The callback function which will be invoked when reading process finished
302  * @param cb_arg The callback argument
303  * @param cb_rd The callback function to report items found in the P2L log
304  *
305  * @return Operation result
306  * @retval 0 - The reading procedure started successfully
307  * @retval non-zero - An error occurred and the reading did not started
308  */
309 int ftl_p2l_log_read(struct spdk_ftl_dev *dev, enum ftl_layout_region_type type, uint64_t seq_id,
310 		     spdk_ftl_fn cb_fn, void *cb_arg, ftl_p2l_log_rd_cb cb_rd);
311 
312 
313 #endif /* FTL_INTERNAL_H */
314