xref: /spdk/lib/ftl/utils/ftl_md.h (revision b02581a89058ebaebe03bd0e16e3b58adfe406c1)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2022 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #ifndef FTL_MD_H
7 #define FTL_MD_H
8 
9 #include "spdk/stdinc.h"
10 
11 #include "ftl_layout.h"
12 
13 struct ftl_md;
14 struct spdk_ftl_dev;
15 
16 typedef void (*ftl_md_cb)(struct spdk_ftl_dev *dev, struct ftl_md *md, int status);
17 
18 enum ftl_md_ops {
19 	FTL_MD_OP_RESTORE,
20 	FTL_MD_OP_PERSIST,
21 	FTL_MD_OP_CLEAR,
22 };
23 
24 typedef int (*shm_open_t)(const char *, int, mode_t);
25 typedef int (*shm_unlink_t)(const char *);
26 
27 /* FTL metadata container which allows to store/restore/recover */
28 struct ftl_md {
29 	/* Context of owner (Caller of restore/persist/clear operation) */
30 	struct {
31 		/* Private context of the metadata's owner */
32 		void *private;
33 
34 		/* Additional context of the owner */
35 		void *cb_ctx;
36 	} owner;
37 
38 	/* Callback for signaling end of procedures like restore, persist, or clear */
39 	ftl_md_cb cb;
40 
41 	/* Pointer to the FTL device */
42 	struct spdk_ftl_dev *dev;
43 
44 	/* Region of device on which store/restore the metadata */
45 	const struct ftl_layout_region  *region;
46 
47 	/* Pointer to data */
48 	void *data;
49 
50 	/* Size of buffer in FTL block size unit */
51 	uint64_t data_blocks;
52 
53 	/* Pointer to VSS metadata data */
54 	void *vss_data;
55 
56 	/* Default DMA buffer for VSS of a single entry. Used by ftl_md_persist_entry(). */
57 	void *entry_vss_dma_buf;
58 
59 	/* Fields for doing IO */
60 	struct {
61 		void *data;
62 		void *md;
63 		uint64_t address;
64 		uint64_t remaining;
65 		uint64_t data_offset;
66 		int status;
67 		enum ftl_md_ops op;
68 		struct spdk_bdev_io_wait_entry bdev_io_wait;
69 	} io;
70 
71 	/* SHM object file descriptor or -1 if heap alloc */
72 	int shm_fd;
73 
74 	/* Object name */
75 	char name[NAME_MAX + 1];
76 
77 	/* mmap flags for the SHM object */
78 	int shm_mmap_flags;
79 
80 	/* Total size of SHM object (data + md) */
81 	size_t shm_sz;
82 
83 	/* open() for the SHM object */
84 	shm_open_t shm_open;
85 
86 	/* unlink() for the SHM object */
87 	shm_unlink_t shm_unlink;
88 
89 	/* Memory was registered to SPDK */
90 	bool mem_reg;
91 
92 	/* This flag is used by the primary to disable mirror temporarily */
93 	bool mirror_enabled;
94 
95 	/* This MD descriptor is used for a mirror region */
96 	bool is_mirror;
97 };
98 
99 typedef void (*ftl_md_io_entry_cb)(int status, void *cb_arg);
100 
101 struct ftl_md_io_entry_ctx {
102 	uint32_t remaining;
103 	int status;
104 	ftl_md_io_entry_cb cb;
105 	void *cb_arg;
106 	struct ftl_md *md;
107 	uint64_t start_entry;
108 	void *buffer;
109 	void *vss_buffer;
110 	struct spdk_bdev_io_wait_entry bdev_io_wait;
111 };
112 
113 #define FTL_MD_VSS_SZ	64
114 union ftl_md_vss {
115 	struct {
116 		uint8_t		unused[FTL_MD_VSS_SZ - sizeof(uint64_t)];
117 		uint64_t	md_version;
118 	} version;
119 
120 	struct {
121 		uint64_t	start_lba;
122 		uint64_t	num_blocks;
123 		uint64_t	seq_id;
124 	} unmap;
125 
126 	struct {
127 		uint64_t	seq_id;
128 		uint32_t	p2l_checksum;
129 	} p2l_ckpt;
130 
131 	struct {
132 		uint64_t	lba;
133 		uint64_t	seq_id;
134 	} nv_cache;
135 };
136 
137 SPDK_STATIC_ASSERT(sizeof(union ftl_md_vss) == FTL_MD_VSS_SZ, "Invalid md vss size");
138 
139 /**
140  *  FTL metadata creation flags
141  */
142 enum ftl_md_create_flags {
143 	/** FTL metadata will be created without memory allocation */
144 	FTL_MD_CREATE_NO_MEM =		0x0,
145 
146 	/** FTL metadata data buf will be allocated in SHM */
147 	FTL_MD_CREATE_SHM =		0x1,
148 
149 	/** Always create a new SHM obj, i.e. issue shm_unlink() before shm_open(), only valid with FTL_MD_CREATE_SHM */
150 	FTL_MD_CREATE_SHM_NEW =		0x2,
151 
152 	/** FTL metadata will be created on heap */
153 	FTL_MD_CREATE_HEAP =		0x4,
154 };
155 
156 /**
157  * @brief Creates FTL metadata
158  *
159  * @param dev The FTL device
160  * @param blocks Size of buffer in FTL block size unit
161  * @param vss_blksz Size of VSS MD
162  * @param name Name of the object being created
163  * @param flags Bit flags of ftl_md_create_flags type
164  * @param region Region associated with FTL metadata
165  *
166  * @note if buffer is NULL, the buffer will be allocated internally by the object
167  *
168  * @return FTL metadata
169  */
170 struct ftl_md *ftl_md_create(struct spdk_ftl_dev *dev, uint64_t blocks,
171 			     uint64_t vss_blksz, const char *name, int flags,
172 			     const struct ftl_layout_region *region);
173 
174 /**
175  * @brief Unlinks metadata object from FS
176  * @param dev The FTL device
177  * @param name Name of the object being unlinked
178  * @param flags Bit flag describing the MD object
179  *
180  * @note Unlink is possible only for objects created with FTL_MD_CREATE_SHM flag
181  *
182  * @return Operation result
183  */
184 int ftl_md_unlink(struct spdk_ftl_dev *dev, const char *name, int flags);
185 
186 /**
187  *  FTL metadata destroy flags
188  */
189 enum ftl_md_destroy_flags {
190 	/** FTL metadata data buf will be kept in SHM */
191 	FTL_MD_DESTROY_SHM_KEEP = 0x1,
192 };
193 
194 /**
195  * @brief Destroys metadata
196  *
197  * @param md Metadata to be destroyed
198  * @param flags Bit flags of type ftl_md_destroy_flags
199  */
200 void ftl_md_destroy(struct ftl_md *md, int flags);
201 
202 /**
203  * @brief Free the data buf associated with the metadata
204  *
205  * @param md Metadata object
206  * @param flags Bit flags of type ftl_md_destroy_flags
207  */
208 void ftl_md_free_buf(struct ftl_md *md, int flags);
209 
210 /**
211  * @brief Sets the region of a device on which to perform IO when persisting,
212  * restoring, or clearing.
213  *
214  * @param md The FTL metadata
215  * @param region The device region to be set
216  */
217 void ftl_md_set_region(struct ftl_md *md,
218 		       const struct ftl_layout_region *region);
219 
220 /**
221  * @brief Gets layout region on which ongoing an IO procedure is executed
222  *
223  * @param md Metadata object
224  *
225  * @return Layout region
226  */
227 const struct ftl_layout_region *ftl_md_get_region(struct ftl_md *md);
228 
229 /**
230  * @brief Gets metadata's data buffer
231  *
232  * @param md The FTL metadata
233  *
234  * @result FTL metadata data buffer
235  */
236 void *ftl_md_get_buffer(struct ftl_md *md);
237 
238 /**
239  * @brief Gets metadata object corresponding buffer size
240  *
241  * @param md The FTL metadata
242  *
243  * @return Buffer size
244  */
245 uint64_t ftl_md_get_buffer_size(struct ftl_md *md);
246 
247 /**
248  * @brief Heap allocate and initialize a vss buffer for MD region.
249  *
250  * The buffer is aligned to FTL_BLOCK_SIZE.
251  * The buffer is zeroed.
252  * The VSS version is inherited from the MD region.
253  *
254  * @param region The MD region
255  * @param count Number of VSS items to allocate
256  *
257  * @return VSS buffer
258  */
259 union ftl_md_vss *ftl_md_vss_buf_alloc(struct ftl_layout_region *region, uint32_t count);
260 
261 /**
262  * @brief Get the VSS metadata data buffer
263  *
264  * @param md The FTL metadata
265  *
266  * @return VSS metadata data buffer
267  */
268 union ftl_md_vss *ftl_md_get_vss_buffer(struct ftl_md *md);
269 
270 /**
271  * Restores metadata from the region which is set
272  *
273  * @param md Metadata to be restored
274  */
275 void ftl_md_restore(struct ftl_md *md);
276 
277 /**
278  * Persists all metadata to the region which is set
279  *
280  * @param md Metadata to be persisted
281  */
282 void ftl_md_persist(struct ftl_md *md);
283 
284 /**
285  * Persists given entries in metadata to the region which is set
286  *
287  * @param md Metadata to be persisted
288  * @param start_entry Starting index of entry to be persisted
289  * @param buffer DMA buffer for writing the entry to the device
290  * @param vss_buffer DMA buffer for writing the entry VSS to the device
291  * @param cb Completion called on persist entry end
292  * @param cb_arg Context returned on completion
293  * @param ctx Operation context structure
294  */
295 void ftl_md_persist_entry(struct ftl_md *md, uint64_t start_entry, void *buffer, void *vss_buffer,
296 			  ftl_md_io_entry_cb cb, void *cb_arg,
297 			  struct ftl_md_io_entry_ctx *ctx);
298 
299 /**
300  * Retries a persist operation performed by ftl_md_persist_entry.
301  *
302  * @param ctx Operation context structure.
303  */
304 void ftl_md_persist_entry_retry(struct ftl_md_io_entry_ctx *ctx);
305 
306 /**
307  * Reads given entries from metadata region
308  *
309  * @param md Metadata to be read
310  * @param start_entry Starting index of entry to be read
311  * @param buffer DMA buffer for reading the entry from the device
312  * @param vss_buffer DMA buffer for reading the entry VSS from the device
313  * @param cb Completion called on read entry end
314  * @param cb_arg Context returned on completion
315  * @param ctx Operation context structure
316  */
317 void ftl_md_read_entry(struct ftl_md *md, uint64_t start_entry, void *buffer, void *vss_buffer,
318 		       ftl_md_io_entry_cb cb, void *cb_arg, struct ftl_md_io_entry_ctx *ctx);
319 
320 /**
321  * @brief Clears metadata on the region which is set
322  *
323  * @param md Metadata to be cleared
324  * @param pattern Pattern used to initialize metadata
325  * @param vss_pattern Pattern used to initialize metadata VSS
326  *
327  * @note size of pattern needs to be aligned to FTL device transfer size
328  */
329 void ftl_md_clear(struct ftl_md *md, int pattern, union ftl_md_vss *vss_pattern);
330 
331 /**
332  * @brief Gets the number of blocks that are transferred in a single IO operation
333  *
334  * @param dev The FTL device
335  *
336  * @return Number of blocks
337  */
338 uint64_t ftl_md_xfer_blocks(struct spdk_ftl_dev *dev);
339 
340 /**
341  * @brief Return the md creation flags for a given md region type
342  *
343  * Controls MD regions backed up on SHM via FTL_MD_CREATE_SHM.
344  * FTL_MD_CREATE_SHM_NEW is added for:
345  * 1. superblock upon SPDK_FTL_MODE_CREATE flag set,
346  * 2. other regions if not in a fast startup mode.
347  *
348  * @param dev		The FTL device
349  * @param region_type	MD region type
350  *
351  * @return MD creation flags
352  */
353 int ftl_md_create_region_flags(struct spdk_ftl_dev *dev, int region_type);
354 
355 /**
356  * @brief Return the md destroy flags for a given md region type
357  *
358  * In a fast shutdown mode, returns FTL_MD_DESTROY_SHM_KEEP.
359  * Otherwise the SHM is unlinked.
360  *
361  * @param dev		The FTL device
362  * @param region_type	MD region type
363  *
364  * #return MD destroy flags
365  */
366 int ftl_md_destroy_region_flags(struct spdk_ftl_dev *dev, int region_type);
367 
368 /**
369  * @brief Return the SHM-backed md creation flags
370  *
371  * FTL_MD_CREATE_SHM is always set.
372  * FTL_MD_CREATE_SHM_NEW is added if not in a fast startup mode.
373  *
374  * @param dev	The FTL device
375  *
376  * @return MD creation flags
377  */
378 int ftl_md_create_shm_flags(struct spdk_ftl_dev *dev);
379 
380 /**
381  * @brief Return the md destroy flags
382  *
383  * In a fast shutdown mode, returns FTL_MD_DESTROY_SHM_KEEP.
384  * Otherwise the SHM is unlinked.
385  *
386  * @param dev			The FTL device
387  *
388  * @return MD destroy flags
389  */
390 int ftl_md_destroy_shm_flags(struct spdk_ftl_dev *dev);
391 #endif /* FTL_MD_H */
392