xref: /spdk/lib/ftl/utils/ftl_md.h (revision 510f4c134a21b45ff3a5add9ebc6c6cf7e49aeab)
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  *  FTL metadata destroy flags
180  */
181 enum ftl_md_destroy_flags {
182 	/** FTL metadata data buf will be kept in SHM */
183 	FTL_MD_DESTROY_SHM_KEEP = 0x1,
184 };
185 
186 /**
187  * @brief Destroys metadata
188  *
189  * @param md Metadata to be destroyed
190  * @param flags Bit flags of type ftl_md_destroy_flags
191  */
192 void ftl_md_destroy(struct ftl_md *md, int flags);
193 
194 /**
195  * @brief Free the data buf associated with the metadata
196  *
197  * @param md Metadata object
198  * @param flags Bit flags of type ftl_md_destroy_flags
199  */
200 void ftl_md_free_buf(struct ftl_md *md, int flags);
201 
202 /**
203  * @brief Sets the region of a device on which to perform IO when persisting,
204  * restoring, or clearing.
205  *
206  * @param md The FTL metadata
207  * @param region The device region to be set
208  *
209  * @return Operation status
210  */
211 int ftl_md_set_region(struct ftl_md *md,
212 		      const struct ftl_layout_region *region);
213 
214 /**
215  * @brief Gets layout region on which ongoing an IO procedure is executed
216  *
217  * @param md Metadata object
218  *
219  * @return Layout region
220  */
221 const struct ftl_layout_region *ftl_md_get_region(struct ftl_md *md);
222 
223 /**
224  * @brief Gets metadata's data buffer
225  *
226  * @param md The FTL metadata
227  *
228  * @result FTL metadata data buffer
229  */
230 void *ftl_md_get_buffer(struct ftl_md *md);
231 
232 /**
233  * @brief Gets metadata object corresponding buffer size
234  *
235  * @param md The FTL metadata
236  *
237  * @return Buffer size
238  */
239 uint64_t ftl_md_get_buffer_size(struct ftl_md *md);
240 
241 /**
242  * @brief Heap allocate and initialize a vss buffer for MD region.
243  *
244  * The buffer is aligned to FTL_BLOCK_SIZE.
245  * The buffer is zeroed.
246  * The VSS version is inherited from the MD region.
247  *
248  * @param region The MD region
249  * @param count Number of VSS items to allocate
250  *
251  * @return VSS buffer
252  */
253 union ftl_md_vss *ftl_md_vss_buf_alloc(struct ftl_layout_region *region, uint32_t count);
254 
255 /**
256  * @brief Get the VSS metadata data buffer
257  *
258  * @param md The FTL metadata
259  *
260  * @return VSS metadata data buffer
261  */
262 union ftl_md_vss *ftl_md_get_vss_buffer(struct ftl_md *md);
263 
264 /**
265  * Restores metadata from the region which is set
266  *
267  * @param md Metadata to be restored
268  */
269 void ftl_md_restore(struct ftl_md *md);
270 
271 /**
272  * Persists all metadata to the region which is set
273  *
274  * @param md Metadata to be persisted
275  */
276 void ftl_md_persist(struct ftl_md *md);
277 
278 /**
279  * Persists given entries in metadata to the region which is set
280  *
281  * @param md Metadata to be persisted
282  * @param start_entry Starting index of entry to be persisted
283  * @param buffer DMA buffer for writing the entry to the device
284  * @param vss_buffer DMA buffer for writing the entry VSS to the device
285  * @param cb Completion called on persist entry end
286  * @param cb_arg Context returned on completion
287  * @param ctx Operation context structure
288  */
289 void ftl_md_persist_entry(struct ftl_md *md, uint64_t start_entry, void *buffer, void *vss_buffer,
290 			  ftl_md_io_entry_cb cb, void *cb_arg,
291 			  struct ftl_md_io_entry_ctx *ctx);
292 
293 /**
294  * Retries a persist operation performed by ftl_md_persist_entry.
295  *
296  * @param ctx Operation context structure.
297  */
298 void ftl_md_persist_entry_retry(struct ftl_md_io_entry_ctx *ctx);
299 
300 /**
301  * Reads given entries from metadata region
302  *
303  * @param md Metadata to be read
304  * @param start_entry Starting index of entry to be read
305  * @param buffer DMA buffer for reading the entry from the device
306  * @param vss_buffer DMA buffer for reading the entry VSS from the device
307  * @param cb Completion called on read entry end
308  * @param cb_arg Context returned on completion
309  * @param ctx Operation context structure
310  */
311 void ftl_md_read_entry(struct ftl_md *md, uint64_t start_entry, void *buffer, void *vss_buffer,
312 		       ftl_md_io_entry_cb cb, void *cb_arg, struct ftl_md_io_entry_ctx *ctx);
313 
314 /**
315  * @brief Clears metadata on the region which is set
316  *
317  * @param md Metadata to be cleared
318  * @param pattern Pattern used to initialize metadata
319  * @param vss_pattern Pattern used to initialize metadata VSS
320  *
321  * @note size of pattern needs to be aligned to FTL device transfer size
322  */
323 void ftl_md_clear(struct ftl_md *md, int pattern, union ftl_md_vss *vss_pattern);
324 
325 /**
326  * @brief Gets the number of blocks that are transfered in a single IO operation
327  *
328  * @param dev The FTL device
329  *
330  * @return Number of blocks
331  */
332 uint64_t ftl_md_xfer_blocks(struct spdk_ftl_dev *dev);
333 
334 /**
335  * @brief Return the md creation flags for a given md region type
336  *
337  * Controls MD regions backed up on SHM via FTL_MD_CREATE_SHM.
338  * FTL_MD_CREATE_SHM_NEW is added for:
339  * 1. superblock upon SPDK_FTL_MODE_CREATE flag set,
340  * 2. other regions if not in a fast startup mode.
341  *
342  * @param dev		The FTL device
343  * @param region_type	MD region type
344  *
345  * @return MD creation flags
346  */
347 int ftl_md_create_region_flags(struct spdk_ftl_dev *dev, int region_type);
348 
349 /**
350  * @brief Return the md destroy flags for a given md region type
351  *
352  * In a fast shutdown mode, returns FTL_MD_DESTROY_SHM_KEEP.
353  * Otherwise the SHM is unlinked.
354  *
355  * @param dev		The FTL device
356  * @param region_type	MD region type
357  *
358  * #return MD destroy flags
359  */
360 int ftl_md_destroy_region_flags(struct spdk_ftl_dev *dev, int region_type);
361 
362 /**
363  * @brief Return the SHM-backed md creation flags
364  *
365  * FTL_MD_CREATE_SHM is always set.
366  * FTL_MD_CREATE_SHM_NEW is added if not in a fast startup mode.
367  *
368  * @param dev	The FTL device
369  *
370  * @return MD creation flags
371  */
372 int ftl_md_create_shm_flags(struct spdk_ftl_dev *dev);
373 
374 /**
375  * @brief Return the md destroy flags
376  *
377  * In a fast shutdown mode, returns FTL_MD_DESTROY_SHM_KEEP.
378  * Otherwise the SHM is unlinked.
379  *
380  * @param dev			The FTL device
381  *
382  * @return MD destroy flags
383  */
384 int ftl_md_destroy_shm_flags(struct spdk_ftl_dev *dev);
385 #endif /* FTL_MD_H */
386