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