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