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