xref: /spdk/lib/ftl/utils/ftl_md.h (revision 081f080a49a3dbe31acb2a8557db90b08bbeaf9c)
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 /* FTL metadata container which allows to store/restore/recover */
24 struct ftl_md {
25 	/* Context of owner (Caller of restore/persist/clear operation) */
26 	struct {
27 		/* Private context of the metadata's owner */
28 		void *private;
29 
30 		/* Additional context of the owner */
31 		void *cb_ctx;
32 	} owner;
33 
34 	/* Callback for signaling end of procedures like restore, persist, or clear */
35 	ftl_md_cb cb;
36 
37 	/* Pointer to the FTL device */
38 	struct spdk_ftl_dev *dev;
39 
40 	/* Region of device on which store/restore the metadata */
41 	const struct ftl_layout_region  *region;
42 
43 	/* Pointer to data */
44 	void *data;
45 
46 	/* Size of buffer in FTL block size unit */
47 	uint64_t data_blocks;
48 
49 	/* Pointer to VSS metadata data */
50 	void *vss_data;
51 
52 	/* Default DMA buffer for VSS of a single entry. Used by ftl_md_persist_entry(). */
53 	void *entry_vss_dma_buf;
54 
55 	/* Fields for doing IO */
56 	struct {
57 		void *data;
58 		void *md;
59 		uint64_t address;
60 		uint64_t remaining;
61 		uint64_t data_offset;
62 		int status;
63 		enum ftl_md_ops op;
64 		struct spdk_bdev_io_wait_entry bdev_io_wait;
65 	} io;
66 
67 	/* Metadata primary object */
68 	struct ftl_md *mirror;
69 
70 	/* This flag is used by the primary to disable mirror temporarily */
71 	bool mirror_enabled;
72 };
73 
74 typedef void (*ftl_md_io_entry_cb)(int status, void *cb_arg);
75 
76 struct ftl_md_io_entry_ctx {
77 	uint32_t remaining;
78 	int status;
79 	ftl_md_io_entry_cb cb;
80 	void *cb_arg;
81 	struct ftl_md *md;
82 	uint64_t start_entry;
83 	void *buffer;
84 	void *vss_buffer;
85 	struct spdk_bdev_io_wait_entry bdev_io_wait;
86 };
87 
88 #define FTL_MD_VSS_SZ	64
89 union ftl_md_vss {
90 	struct {
91 		uint8_t		unused[FTL_MD_VSS_SZ - sizeof(uint64_t)];
92 		uint64_t	md_version;
93 	} version;
94 
95 	struct {
96 		uint64_t	start_lba;
97 		uint64_t	num_blocks;
98 	} unmap;
99 
100 	struct {
101 		uint64_t	lba;
102 	} nv_cache;
103 };
104 
105 SPDK_STATIC_ASSERT(sizeof(union ftl_md_vss) == FTL_MD_VSS_SZ, "Invalid md vss size");
106 
107 /**
108  * @brief Creates FTL metadata
109  *
110  * @param dev The FTL device
111  * @param blocks Size of buffer in FTL block size unit
112  * @param vss_blksz Size of VSS MD
113  * @param name Name of the object being created
114  * @param no_mem If true metadata will be created without memory allocation
115  * @param region Region associated with FTL metadata
116  *
117  * @note if buffer is NULL, the buffer will be allocated internally by the object
118  *
119  * @return FTL metadata
120  */
121 struct ftl_md *ftl_md_create(struct spdk_ftl_dev *dev, uint64_t blocks,
122 			     uint64_t vss_blksz, const char *name, bool no_mem,
123 			     const struct ftl_layout_region *region);
124 
125 /**
126  * @brief Destroys metadata
127  *
128  * @param md Metadata to be destroyed
129  */
130 void ftl_md_destroy(struct ftl_md *md);
131 
132 /**
133  * @brief Free the data buf associated with the metadata
134  *
135  * @param md Metadata object
136  */
137 void ftl_md_free_buf(struct ftl_md *md);
138 
139 /**
140  * @brief Sets the region of a device on which to perform IO when persisting,
141  * restoring, or clearing.
142  *
143  * @param md The FTL metadata
144  * @param region The device region to be set
145  *
146  * @return Operation status
147  */
148 int ftl_md_set_region(struct ftl_md *md,
149 		      const struct ftl_layout_region *region);
150 
151 /**
152  * @brief Gets layout region on which ongoing an IO procedure is executed
153  *
154  * @param md Metadata object
155  *
156  * @return Layout region
157  */
158 const struct ftl_layout_region *ftl_md_get_region(struct ftl_md *md);
159 
160 /**
161  * @brief Gets metadata's data buffer
162  *
163  * @param md The FTL metadata
164  *
165  * @result FTL metadata data buffer
166  */
167 void *ftl_md_get_buffer(struct ftl_md *md);
168 
169 /**
170  * @brief Gets metadata object corresponding buffer size
171  *
172  * @param md The FTL metadata
173  *
174  * @return Buffer size
175  */
176 uint64_t ftl_md_get_buffer_size(struct ftl_md *md);
177 
178 /**
179  * @brief Heap allocate and initialize a vss buffer for MD region.
180  *
181  * The buffer is aligned to FTL_BLOCK_SIZE.
182  * The buffer is zeroed.
183  * The VSS version is inherited from the MD region.
184  *
185  * @param region The MD region
186  * @param count Number of VSS items to allocate
187  *
188  * @return VSS buffer
189  */
190 union ftl_md_vss *ftl_md_vss_buf_alloc(struct ftl_layout_region *region, uint32_t count);
191 
192 /**
193  * @brief Get the VSS metadata data buffer
194  *
195  * @param md The FTL metadata
196  *
197  * @return VSS metadata data buffer
198  */
199 union ftl_md_vss *ftl_md_get_vss_buffer(struct ftl_md *md);
200 
201 /**
202  * Restores metadata from the region which is set
203  *
204  * @param md Metadata to be restored
205  */
206 void ftl_md_restore(struct ftl_md *md);
207 
208 /**
209  * Persists all metadata to the region which is set
210  *
211  * @param md Metadata to be persisted
212  */
213 void ftl_md_persist(struct ftl_md *md);
214 
215 /**
216  * Persists given entries in metadata to the region which is set
217  *
218  * @param md Metadata to be persisted
219  * @param start_entry Starting index of entry to be persisted
220  * @param buffer DMA buffer for writing the entry to the device
221  * @param vss_buffer DMA buffer for writing the entry VSS to the device
222  * @param cb Completion called on persist entry end
223  * @param cb_arg Context returned on completion
224  * @param ctx Operation context structure
225  */
226 void ftl_md_persist_entry(struct ftl_md *md, uint64_t start_entry, void *buffer, void *vss_buffer,
227 			  ftl_md_io_entry_cb cb, void *cb_arg,
228 			  struct ftl_md_io_entry_ctx *ctx);
229 
230 /**
231  * Retries a persist operation performed by ftl_md_persist_entry.
232  *
233  * @param ctx Operation context structure.
234  */
235 void ftl_md_persist_entry_retry(struct ftl_md_io_entry_ctx *ctx);
236 
237 /**
238  * Reads given entries from metadata region
239  *
240  * @param md Metadata to be read
241  * @param start_entry Starting index of entry to be read
242  * @param buffer DMA buffer for reading the entry from the device
243  * @param vss_buffer DMA buffer for reading the entry VSS from the device
244  * @param cb Completion called on read entry end
245  * @param cb_arg Context returned on completion
246  * @param ctx Operation context structure
247  */
248 void ftl_md_read_entry(struct ftl_md *md, uint64_t start_entry, void *buffer, void *vss_buffer,
249 		       ftl_md_io_entry_cb cb, void *cb_arg, struct ftl_md_io_entry_ctx *ctx);
250 
251 /**
252  * @brief Clears metadata on the region which is set
253  *
254  * @param md Metadata to be cleared
255  * @param pattern Pattern used to initialize metadata
256  * @param vss_pattern Pattern used to initialize metadata VSS
257  *
258  * @note size of pattern needs to be aligned to FTL device transfer size
259  */
260 void ftl_md_clear(struct ftl_md *md, int pattern, union ftl_md_vss *vss_pattern);
261 
262 /**
263  * @brief Gets the number of blocks that are transfered in a single IO operation
264  *
265  * @param dev The FTL device
266  *
267  * @return Number of blocks
268  */
269 uint64_t ftl_md_xfer_blocks(struct spdk_ftl_dev *dev);
270 
271 #endif /* FTL_MD_H */
272