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 /* FTL metadata container which allows to store/restore/recover */ 24 struct ftl_md { 25 /* Context of owner (Caller of restore/persist/clear operation) */ 26 struct { 27 /* Private context of the metadata's owner */ 28 void *private; 29 30 /* Additional context of the owner */ 31 void *cb_ctx; 32 } owner; 33 34 /* Callback for signaling end of procedures like restore, persist, or clear */ 35 ftl_md_cb cb; 36 37 /* Pointer to the FTL device */ 38 struct spdk_ftl_dev *dev; 39 40 /* Region of device on which store/restore the metadata */ 41 const struct ftl_layout_region *region; 42 43 /* Pointer to data */ 44 void *data; 45 46 /* Size of buffer in FTL block size unit */ 47 uint64_t data_blocks; 48 49 /* Pointer to VSS metadata data */ 50 void *vss_data; 51 52 /* Default DMA buffer for VSS of a single entry. Used by ftl_md_persist_entry(). */ 53 void *entry_vss_dma_buf; 54 55 /* Fields for doing IO */ 56 struct { 57 void *data; 58 void *md; 59 uint64_t address; 60 uint64_t remaining; 61 uint64_t data_offset; 62 int status; 63 enum ftl_md_ops op; 64 struct spdk_bdev_io_wait_entry bdev_io_wait; 65 } io; 66 67 /* Metadata primary object */ 68 struct ftl_md *mirror; 69 70 /* This flag is used by the primary to disable mirror temporarily */ 71 bool mirror_enabled; 72 }; 73 74 typedef void (*ftl_md_io_entry_cb)(int status, void *cb_arg); 75 76 struct ftl_md_io_entry_ctx { 77 uint32_t remaining; 78 int status; 79 ftl_md_io_entry_cb cb; 80 void *cb_arg; 81 struct ftl_md *md; 82 uint64_t start_entry; 83 void *buffer; 84 void *vss_buffer; 85 struct spdk_bdev_io_wait_entry bdev_io_wait; 86 }; 87 88 #define FTL_MD_VSS_SZ 64 89 union ftl_md_vss { 90 struct { 91 uint8_t unused[FTL_MD_VSS_SZ - sizeof(uint64_t)]; 92 uint64_t md_version; 93 } version; 94 95 struct { 96 uint64_t start_lba; 97 uint64_t num_blocks; 98 } unmap; 99 100 struct { 101 uint64_t lba; 102 } nv_cache; 103 }; 104 105 SPDK_STATIC_ASSERT(sizeof(union ftl_md_vss) == FTL_MD_VSS_SZ, "Invalid md vss size"); 106 107 /** 108 * @brief Creates FTL metadata 109 * 110 * @param dev The FTL device 111 * @param blocks Size of buffer in FTL block size unit 112 * @param vss_blksz Size of VSS MD 113 * @param name Name of the object being created 114 * @param no_mem If true metadata will be created without memory allocation 115 * @param region Region associated with FTL metadata 116 * 117 * @note if buffer is NULL, the buffer will be allocated internally by the object 118 * 119 * @return FTL metadata 120 */ 121 struct ftl_md *ftl_md_create(struct spdk_ftl_dev *dev, uint64_t blocks, 122 uint64_t vss_blksz, const char *name, bool no_mem, 123 const struct ftl_layout_region *region); 124 125 /** 126 * @brief Destroys metadata 127 * 128 * @param md Metadata to be destroyed 129 */ 130 void ftl_md_destroy(struct ftl_md *md); 131 132 /** 133 * @brief Free the data buf associated with the metadata 134 * 135 * @param md Metadata object 136 */ 137 void ftl_md_free_buf(struct ftl_md *md); 138 139 /** 140 * @brief Sets the region of a device on which to perform IO when persisting, 141 * restoring, or clearing. 142 * 143 * @param md The FTL metadata 144 * @param region The device region to be set 145 * 146 * @return Operation status 147 */ 148 int ftl_md_set_region(struct ftl_md *md, 149 const struct ftl_layout_region *region); 150 151 /** 152 * @brief Gets layout region on which ongoing an IO procedure is executed 153 * 154 * @param md Metadata object 155 * 156 * @return Layout region 157 */ 158 const struct ftl_layout_region *ftl_md_get_region(struct ftl_md *md); 159 160 /** 161 * @brief Gets metadata's data buffer 162 * 163 * @param md The FTL metadata 164 * 165 * @result FTL metadata data buffer 166 */ 167 void *ftl_md_get_buffer(struct ftl_md *md); 168 169 /** 170 * @brief Gets metadata object corresponding buffer size 171 * 172 * @param md The FTL metadata 173 * 174 * @return Buffer size 175 */ 176 uint64_t ftl_md_get_buffer_size(struct ftl_md *md); 177 178 /** 179 * @brief Heap allocate and initialize a vss buffer for MD region. 180 * 181 * The buffer is aligned to FTL_BLOCK_SIZE. 182 * The buffer is zeroed. 183 * The VSS version is inherited from the MD region. 184 * 185 * @param region The MD region 186 * @param count Number of VSS items to allocate 187 * 188 * @return VSS buffer 189 */ 190 union ftl_md_vss *ftl_md_vss_buf_alloc(struct ftl_layout_region *region, uint32_t count); 191 192 /** 193 * @brief Get the VSS metadata data buffer 194 * 195 * @param md The FTL metadata 196 * 197 * @return VSS metadata data buffer 198 */ 199 union ftl_md_vss *ftl_md_get_vss_buffer(struct ftl_md *md); 200 201 /** 202 * Restores metadata from the region which is set 203 * 204 * @param md Metadata to be restored 205 */ 206 void ftl_md_restore(struct ftl_md *md); 207 208 /** 209 * Persists all metadata to the region which is set 210 * 211 * @param md Metadata to be persisted 212 */ 213 void ftl_md_persist(struct ftl_md *md); 214 215 /** 216 * Persists given entries in metadata to the region which is set 217 * 218 * @param md Metadata to be persisted 219 * @param start_entry Starting index of entry to be persisted 220 * @param buffer DMA buffer for writing the entry to the device 221 * @param vss_buffer DMA buffer for writing the entry VSS to the device 222 * @param cb Completion called on persist entry end 223 * @param cb_arg Context returned on completion 224 * @param ctx Operation context structure 225 */ 226 void ftl_md_persist_entry(struct ftl_md *md, uint64_t start_entry, void *buffer, void *vss_buffer, 227 ftl_md_io_entry_cb cb, void *cb_arg, 228 struct ftl_md_io_entry_ctx *ctx); 229 230 /** 231 * Retries a persist operation performed by ftl_md_persist_entry. 232 * 233 * @param ctx Operation context structure. 234 */ 235 void ftl_md_persist_entry_retry(struct ftl_md_io_entry_ctx *ctx); 236 237 /** 238 * Reads given entries from metadata region 239 * 240 * @param md Metadata to be read 241 * @param start_entry Starting index of entry to be read 242 * @param buffer DMA buffer for reading the entry from the device 243 * @param vss_buffer DMA buffer for reading the entry VSS from the device 244 * @param cb Completion called on read entry end 245 * @param cb_arg Context returned on completion 246 * @param ctx Operation context structure 247 */ 248 void ftl_md_read_entry(struct ftl_md *md, uint64_t start_entry, void *buffer, void *vss_buffer, 249 ftl_md_io_entry_cb cb, void *cb_arg, struct ftl_md_io_entry_ctx *ctx); 250 251 /** 252 * @brief Clears metadata on the region which is set 253 * 254 * @param md Metadata to be cleared 255 * @param pattern Pattern used to initialize metadata 256 * @param vss_pattern Pattern used to initialize metadata VSS 257 * 258 * @note size of pattern needs to be aligned to FTL device transfer size 259 */ 260 void ftl_md_clear(struct ftl_md *md, int pattern, union ftl_md_vss *vss_pattern); 261 262 /** 263 * @brief Gets the number of blocks that are transfered in a single IO operation 264 * 265 * @param dev The FTL device 266 * 267 * @return Number of blocks 268 */ 269 uint64_t ftl_md_xfer_blocks(struct spdk_ftl_dev *dev); 270 271 #endif /* FTL_MD_H */ 272