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