xref: /spdk/lib/ftl/utils/ftl_md.h (revision 2e283fcb67a8ee1d9b4f470f17bec57bbe3adad5)
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 	} unmap;
123 
124 	struct {
125 		uint64_t	lba;
126 	} nv_cache;
127 };
128 
129 SPDK_STATIC_ASSERT(sizeof(union ftl_md_vss) == FTL_MD_VSS_SZ, "Invalid md vss size");
130 
131 /**
132  *  FTL metadata creation flags
133  */
134 enum ftl_md_create_flags {
135 	/** FTL metadata will be created without memory allocation */
136 	FTL_MD_CREATE_NO_MEM =		0x0,
137 
138 	/** FTL metadata data buf will be allocated in SHM */
139 	FTL_MD_CREATE_SHM =		0x1,
140 
141 	/** Always create a new SHM obj, i.e. issue shm_unlink() before shm_open(), only valid with FTL_MD_CREATE_SHM */
142 	FTL_MD_CREATE_SHM_NEW =		0x2,
143 
144 	/** FTL metadata will be created on heap */
145 	FTL_MD_CREATE_HEAP =		0x4,
146 };
147 
148 /**
149  * @brief Creates FTL metadata
150  *
151  * @param dev The FTL device
152  * @param blocks Size of buffer in FTL block size unit
153  * @param vss_blksz Size of VSS MD
154  * @param name Name of the object being created
155  * @param flags Bit flags of ftl_md_create_flags type
156  * @param region Region associated with FTL metadata
157  *
158  * @note if buffer is NULL, the buffer will be allocated internally by the object
159  *
160  * @return FTL metadata
161  */
162 struct ftl_md *ftl_md_create(struct spdk_ftl_dev *dev, uint64_t blocks,
163 			     uint64_t vss_blksz, const char *name, int flags,
164 			     const struct ftl_layout_region *region);
165 
166 /**
167  * @brief Unlinks metadata object from FS
168  * @param dev The FTL device
169  * @param name Name of the object being unlinked
170  * @param flags Bit flag describing the MD object
171  *
172  * @note Unlink is possible only for objects created with FTL_MD_CREATE_SHM flag
173  *
174  * @return Operation result
175  */
176 int ftl_md_unlink(struct spdk_ftl_dev *dev, const char *name, int flags);
177 
178 /**
179  * @brief Destroys metadata
180  *
181  * @param md Metadata to be destroyed
182  */
183 void ftl_md_destroy(struct ftl_md *md);
184 
185 /**
186  * @brief Free the data buf associated with the metadata
187  *
188  * @param md Metadata object
189  */
190 void ftl_md_free_buf(struct ftl_md *md);
191 
192 /**
193  * @brief Sets the region of a device on which to perform IO when persisting,
194  * restoring, or clearing.
195  *
196  * @param md The FTL metadata
197  * @param region The device region to be set
198  *
199  * @return Operation status
200  */
201 int ftl_md_set_region(struct ftl_md *md,
202 		      const struct ftl_layout_region *region);
203 
204 /**
205  * @brief Gets layout region on which ongoing an IO procedure is executed
206  *
207  * @param md Metadata object
208  *
209  * @return Layout region
210  */
211 const struct ftl_layout_region *ftl_md_get_region(struct ftl_md *md);
212 
213 /**
214  * @brief Gets metadata's data buffer
215  *
216  * @param md The FTL metadata
217  *
218  * @result FTL metadata data buffer
219  */
220 void *ftl_md_get_buffer(struct ftl_md *md);
221 
222 /**
223  * @brief Gets metadata object corresponding buffer size
224  *
225  * @param md The FTL metadata
226  *
227  * @return Buffer size
228  */
229 uint64_t ftl_md_get_buffer_size(struct ftl_md *md);
230 
231 /**
232  * @brief Heap allocate and initialize a vss buffer for MD region.
233  *
234  * The buffer is aligned to FTL_BLOCK_SIZE.
235  * The buffer is zeroed.
236  * The VSS version is inherited from the MD region.
237  *
238  * @param region The MD region
239  * @param count Number of VSS items to allocate
240  *
241  * @return VSS buffer
242  */
243 union ftl_md_vss *ftl_md_vss_buf_alloc(struct ftl_layout_region *region, uint32_t count);
244 
245 /**
246  * @brief Get the VSS metadata data buffer
247  *
248  * @param md The FTL metadata
249  *
250  * @return VSS metadata data buffer
251  */
252 union ftl_md_vss *ftl_md_get_vss_buffer(struct ftl_md *md);
253 
254 /**
255  * Restores metadata from the region which is set
256  *
257  * @param md Metadata to be restored
258  */
259 void ftl_md_restore(struct ftl_md *md);
260 
261 /**
262  * Persists all metadata to the region which is set
263  *
264  * @param md Metadata to be persisted
265  */
266 void ftl_md_persist(struct ftl_md *md);
267 
268 /**
269  * Persists given entries in metadata to the region which is set
270  *
271  * @param md Metadata to be persisted
272  * @param start_entry Starting index of entry to be persisted
273  * @param buffer DMA buffer for writing the entry to the device
274  * @param vss_buffer DMA buffer for writing the entry VSS to the device
275  * @param cb Completion called on persist entry end
276  * @param cb_arg Context returned on completion
277  * @param ctx Operation context structure
278  */
279 void ftl_md_persist_entry(struct ftl_md *md, uint64_t start_entry, void *buffer, void *vss_buffer,
280 			  ftl_md_io_entry_cb cb, void *cb_arg,
281 			  struct ftl_md_io_entry_ctx *ctx);
282 
283 /**
284  * Retries a persist operation performed by ftl_md_persist_entry.
285  *
286  * @param ctx Operation context structure.
287  */
288 void ftl_md_persist_entry_retry(struct ftl_md_io_entry_ctx *ctx);
289 
290 /**
291  * Reads given entries from metadata region
292  *
293  * @param md Metadata to be read
294  * @param start_entry Starting index of entry to be read
295  * @param buffer DMA buffer for reading the entry from the device
296  * @param vss_buffer DMA buffer for reading the entry VSS from the device
297  * @param cb Completion called on read entry end
298  * @param cb_arg Context returned on completion
299  * @param ctx Operation context structure
300  */
301 void ftl_md_read_entry(struct ftl_md *md, uint64_t start_entry, void *buffer, void *vss_buffer,
302 		       ftl_md_io_entry_cb cb, void *cb_arg, struct ftl_md_io_entry_ctx *ctx);
303 
304 /**
305  * @brief Clears metadata on the region which is set
306  *
307  * @param md Metadata to be cleared
308  * @param pattern Pattern used to initialize metadata
309  * @param vss_pattern Pattern used to initialize metadata VSS
310  *
311  * @note size of pattern needs to be aligned to FTL device transfer size
312  */
313 void ftl_md_clear(struct ftl_md *md, int pattern, union ftl_md_vss *vss_pattern);
314 
315 /**
316  * @brief Gets the number of blocks that are transfered in a single IO operation
317  *
318  * @param dev The FTL device
319  *
320  * @return Number of blocks
321  */
322 uint64_t ftl_md_xfer_blocks(struct spdk_ftl_dev *dev);
323 
324 #endif /* FTL_MD_H */
325