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 uint64_t seq_id; 123 } unmap; 124 125 struct { 126 uint64_t seq_id; 127 uint32_t p2l_checksum; 128 } p2l_ckpt; 129 130 struct { 131 uint64_t lba; 132 uint64_t seq_id; 133 } nv_cache; 134 }; 135 136 SPDK_STATIC_ASSERT(sizeof(union ftl_md_vss) == FTL_MD_VSS_SZ, "Invalid md vss size"); 137 138 /** 139 * FTL metadata creation flags 140 */ 141 enum ftl_md_create_flags { 142 /** FTL metadata will be created without memory allocation */ 143 FTL_MD_CREATE_NO_MEM = 0x0, 144 145 /** FTL metadata data buf will be allocated in SHM */ 146 FTL_MD_CREATE_SHM = 0x1, 147 148 /** Always create a new SHM obj, i.e. issue shm_unlink() before shm_open(), only valid with FTL_MD_CREATE_SHM */ 149 FTL_MD_CREATE_SHM_NEW = 0x2, 150 151 /** FTL metadata will be created on heap */ 152 FTL_MD_CREATE_HEAP = 0x4, 153 }; 154 155 /** 156 * @brief Creates FTL metadata 157 * 158 * @param dev The FTL device 159 * @param blocks Size of buffer in FTL block size unit 160 * @param vss_blksz Size of VSS MD 161 * @param name Name of the object being created 162 * @param flags Bit flags of ftl_md_create_flags type 163 * @param region Region associated with FTL metadata 164 * 165 * @note if buffer is NULL, the buffer will be allocated internally by the object 166 * 167 * @return FTL metadata 168 */ 169 struct ftl_md *ftl_md_create(struct spdk_ftl_dev *dev, uint64_t blocks, 170 uint64_t vss_blksz, const char *name, int flags, 171 const struct ftl_layout_region *region); 172 173 /** 174 * @brief Unlinks metadata object from FS 175 * @param dev The FTL device 176 * @param name Name of the object being unlinked 177 * @param flags Bit flag describing the MD object 178 * 179 * @note Unlink is possible only for objects created with FTL_MD_CREATE_SHM flag 180 * 181 * @return Operation result 182 */ 183 int ftl_md_unlink(struct spdk_ftl_dev *dev, const char *name, int flags); 184 185 /** 186 * FTL metadata destroy flags 187 */ 188 enum ftl_md_destroy_flags { 189 /** FTL metadata data buf will be kept in SHM */ 190 FTL_MD_DESTROY_SHM_KEEP = 0x1, 191 }; 192 193 /** 194 * @brief Destroys metadata 195 * 196 * @param md Metadata to be destroyed 197 * @param flags Bit flags of type ftl_md_destroy_flags 198 */ 199 void ftl_md_destroy(struct ftl_md *md, int flags); 200 201 /** 202 * @brief Free the data buf associated with the metadata 203 * 204 * @param md Metadata object 205 * @param flags Bit flags of type ftl_md_destroy_flags 206 */ 207 void ftl_md_free_buf(struct ftl_md *md, int flags); 208 209 /** 210 * @brief Sets the region of a device on which to perform IO when persisting, 211 * restoring, or clearing. 212 * 213 * @param md The FTL metadata 214 * @param region The device region to be set 215 * 216 * @return Operation status 217 */ 218 int ftl_md_set_region(struct ftl_md *md, 219 const struct ftl_layout_region *region); 220 221 /** 222 * @brief Gets layout region on which ongoing an IO procedure is executed 223 * 224 * @param md Metadata object 225 * 226 * @return Layout region 227 */ 228 const struct ftl_layout_region *ftl_md_get_region(struct ftl_md *md); 229 230 /** 231 * @brief Gets metadata's data buffer 232 * 233 * @param md The FTL metadata 234 * 235 * @result FTL metadata data buffer 236 */ 237 void *ftl_md_get_buffer(struct ftl_md *md); 238 239 /** 240 * @brief Gets metadata object corresponding buffer size 241 * 242 * @param md The FTL metadata 243 * 244 * @return Buffer size 245 */ 246 uint64_t ftl_md_get_buffer_size(struct ftl_md *md); 247 248 /** 249 * @brief Heap allocate and initialize a vss buffer for MD region. 250 * 251 * The buffer is aligned to FTL_BLOCK_SIZE. 252 * The buffer is zeroed. 253 * The VSS version is inherited from the MD region. 254 * 255 * @param region The MD region 256 * @param count Number of VSS items to allocate 257 * 258 * @return VSS buffer 259 */ 260 union ftl_md_vss *ftl_md_vss_buf_alloc(struct ftl_layout_region *region, uint32_t count); 261 262 /** 263 * @brief Get the VSS metadata data buffer 264 * 265 * @param md The FTL metadata 266 * 267 * @return VSS metadata data buffer 268 */ 269 union ftl_md_vss *ftl_md_get_vss_buffer(struct ftl_md *md); 270 271 /** 272 * Restores metadata from the region which is set 273 * 274 * @param md Metadata to be restored 275 */ 276 void ftl_md_restore(struct ftl_md *md); 277 278 /** 279 * Persists all metadata to the region which is set 280 * 281 * @param md Metadata to be persisted 282 */ 283 void ftl_md_persist(struct ftl_md *md); 284 285 /** 286 * Persists given entries in metadata to the region which is set 287 * 288 * @param md Metadata to be persisted 289 * @param start_entry Starting index of entry to be persisted 290 * @param buffer DMA buffer for writing the entry to the device 291 * @param vss_buffer DMA buffer for writing the entry VSS to the device 292 * @param cb Completion called on persist entry end 293 * @param cb_arg Context returned on completion 294 * @param ctx Operation context structure 295 */ 296 void ftl_md_persist_entry(struct ftl_md *md, uint64_t start_entry, void *buffer, void *vss_buffer, 297 ftl_md_io_entry_cb cb, void *cb_arg, 298 struct ftl_md_io_entry_ctx *ctx); 299 300 /** 301 * Retries a persist operation performed by ftl_md_persist_entry. 302 * 303 * @param ctx Operation context structure. 304 */ 305 void ftl_md_persist_entry_retry(struct ftl_md_io_entry_ctx *ctx); 306 307 /** 308 * Reads given entries from metadata region 309 * 310 * @param md Metadata to be read 311 * @param start_entry Starting index of entry to be read 312 * @param buffer DMA buffer for reading the entry from the device 313 * @param vss_buffer DMA buffer for reading the entry VSS from the device 314 * @param cb Completion called on read entry end 315 * @param cb_arg Context returned on completion 316 * @param ctx Operation context structure 317 */ 318 void ftl_md_read_entry(struct ftl_md *md, uint64_t start_entry, void *buffer, void *vss_buffer, 319 ftl_md_io_entry_cb cb, void *cb_arg, struct ftl_md_io_entry_ctx *ctx); 320 321 /** 322 * @brief Clears metadata on the region which is set 323 * 324 * @param md Metadata to be cleared 325 * @param pattern Pattern used to initialize metadata 326 * @param vss_pattern Pattern used to initialize metadata VSS 327 * 328 * @note size of pattern needs to be aligned to FTL device transfer size 329 */ 330 void ftl_md_clear(struct ftl_md *md, int pattern, union ftl_md_vss *vss_pattern); 331 332 /** 333 * @brief Gets the number of blocks that are transfered in a single IO operation 334 * 335 * @param dev The FTL device 336 * 337 * @return Number of blocks 338 */ 339 uint64_t ftl_md_xfer_blocks(struct spdk_ftl_dev *dev); 340 341 /** 342 * @brief Return the md creation flags for a given md region type 343 * 344 * Controls MD regions backed up on SHM via FTL_MD_CREATE_SHM. 345 * FTL_MD_CREATE_SHM_NEW is added for: 346 * 1. superblock upon SPDK_FTL_MODE_CREATE flag set, 347 * 2. other regions if not in a fast startup mode. 348 * 349 * @param dev The FTL device 350 * @param region_type MD region type 351 * 352 * @return MD creation flags 353 */ 354 int ftl_md_create_region_flags(struct spdk_ftl_dev *dev, int region_type); 355 356 /** 357 * @brief Return the md destroy flags for a given md region type 358 * 359 * In a fast shutdown mode, returns FTL_MD_DESTROY_SHM_KEEP. 360 * Otherwise the SHM is unlinked. 361 * 362 * @param dev The FTL device 363 * @param region_type MD region type 364 * 365 * #return MD destroy flags 366 */ 367 int ftl_md_destroy_region_flags(struct spdk_ftl_dev *dev, int region_type); 368 369 /** 370 * @brief Return the SHM-backed md creation flags 371 * 372 * FTL_MD_CREATE_SHM is always set. 373 * FTL_MD_CREATE_SHM_NEW is added if not in a fast startup mode. 374 * 375 * @param dev The FTL device 376 * 377 * @return MD creation flags 378 */ 379 int ftl_md_create_shm_flags(struct spdk_ftl_dev *dev); 380 381 /** 382 * @brief Return the md destroy flags 383 * 384 * In a fast shutdown mode, returns FTL_MD_DESTROY_SHM_KEEP. 385 * Otherwise the SHM is unlinked. 386 * 387 * @param dev The FTL device 388 * 389 * @return MD destroy flags 390 */ 391 int ftl_md_destroy_shm_flags(struct spdk_ftl_dev *dev); 392 #endif /* FTL_MD_H */ 393