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