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