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