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_INTERNAL_H 8 #define FTL_INTERNAL_H 9 10 #include "spdk/stdinc.h" 11 #include "spdk/crc32.h" 12 #include "spdk/util.h" 13 #include "spdk/uuid.h" 14 #include "spdk/ftl.h" 15 16 #include "utils/ftl_bitmap.h" 17 #include "utils/ftl_md.h" 18 19 /* Marks address as invalid */ 20 #define FTL_ADDR_INVALID ((ftl_addr)-1) 21 /* Marks LBA as invalid */ 22 #define FTL_LBA_INVALID ((uint64_t)-1) 23 /* Smallest data unit size */ 24 #define FTL_BLOCK_SIZE 4096ULL 25 26 #define FTL_P2L_VERSION_0 0 27 #define FTL_P2L_VERSION_1 1 28 #define FTL_P2L_VERSION_2 2 29 30 #define FTL_P2L_VERSION_CURRENT FTL_P2L_VERSION_2 31 32 #define FTL_P2L_LOG_VERSION_0 0 33 34 #define FTL_P2L_LOG_VERSION_CURRENT FTL_P2L_LOG_VERSION_0 35 36 /* 37 * This type represents address in the ftl address space. Values from 0 to based bdev size are 38 * mapped directly to base device lbas. Values above that represent nv cache lbas. 39 */ 40 typedef uint64_t ftl_addr; 41 42 struct spdk_ftl_dev; 43 44 enum ftl_md_type { 45 FTL_MD_TYPE_BAND, 46 FTL_MD_TYPE_CHUNK 47 }; 48 49 enum ftl_band_type { 50 FTL_BAND_TYPE_GC = 1, 51 FTL_BAND_TYPE_COMPACTION 52 }; 53 54 enum ftl_md_status { 55 FTL_MD_SUCCESS, 56 /* Metadata read failure */ 57 FTL_MD_IO_FAILURE, 58 /* Invalid version */ 59 FTL_MD_INVALID_VER, 60 /* UUID doesn't match */ 61 FTL_MD_NO_MD, 62 /* UUID and version matches but CRC doesn't */ 63 FTL_MD_INVALID_CRC, 64 /* Vld or p2l map size doesn't match */ 65 FTL_MD_INVALID_SIZE 66 }; 67 68 struct ftl_p2l_map_entry { 69 uint64_t lba; 70 uint64_t seq_id; 71 }; 72 73 /* Number of p2l entries that could be stored in a single block for bands */ 74 #define FTL_NUM_LBA_IN_BLOCK (FTL_BLOCK_SIZE / sizeof(struct ftl_p2l_map_entry)) 75 76 /* 77 * Mapping of physical (actual location on disk) to logical (user's POV) addresses. Used in two main scenarios: 78 * - during relocation FTL needs to pin L2P pages (this allows to check which pages to pin) and move still valid blocks 79 * (valid map allows for preliminary elimination of invalid physical blocks, but user data could invalidate a location 80 * during read/write operation, so actual comparison against L2P needs to be done) 81 * - After dirty shutdown the state of the L2P is unknown and needs to be rebuilt - it is done by applying all P2L, taking 82 * into account ordering of user writes 83 */ 84 struct ftl_p2l_map { 85 /* Number of valid LBAs */ 86 size_t num_valid; 87 88 /* P2L map's reference count, prevents premature release of resources during dirty shutdown recovery for open bands */ 89 size_t ref_cnt; 90 91 /* Bitmap of valid LBAs */ 92 struct ftl_bitmap *valid; 93 94 /* P2L map (only valid for open/relocating bands) */ 95 union { 96 struct ftl_p2l_map_entry *band_map; 97 void *chunk_map; 98 }; 99 100 /* DMA buffer for region's metadata entry */ 101 union { 102 struct ftl_band_md *band_dma_md; 103 104 struct ftl_nv_cache_chunk_md *chunk_dma_md; 105 }; 106 107 /* P2L checkpointing region */ 108 struct ftl_p2l_ckpt *p2l_ckpt; 109 }; 110 111 struct ftl_p2l_sync_ctx { 112 struct ftl_band *band; 113 uint64_t xfer_start; 114 uint64_t xfer_end; 115 int md_region; 116 }; 117 118 struct ftl_p2l_ckpt_page { 119 struct ftl_p2l_map_entry map[FTL_NUM_LBA_IN_BLOCK]; 120 }; 121 122 struct ftl_p2l_ckpt_page_no_vss { 123 union ftl_md_vss metadata; 124 struct ftl_p2l_map_entry map[FTL_NUM_LBA_IN_BLOCK - sizeof(union ftl_md_vss) / sizeof( 125 struct ftl_p2l_map_entry)]; 126 } __attribute__((packed)); 127 SPDK_STATIC_ASSERT(sizeof(struct ftl_p2l_ckpt_page_no_vss) == FTL_BLOCK_SIZE, 128 "ftl_p2l_ckpt_page_no_vss incorrect size"); 129 130 #define FTL_NUM_P2L_ENTRIES_NO_VSS (SPDK_COUNTOF_MEMBER(struct ftl_p2l_ckpt_page_no_vss, map)) 131 132 #define FTL_TRIM_LOG_VERSION_0 0 133 #define FTL_TRIM_LOG_VERSION_1 1 134 #define FTL_TRIM_LOG_VERSION_CURRENT FTL_TRIM_LOG_VERSION_1 135 136 struct ftl_trim_log { 137 union ftl_md_vss hdr; 138 char reserved[FTL_BLOCK_SIZE - sizeof(union ftl_md_vss)]; 139 }; 140 SPDK_STATIC_ASSERT(sizeof(struct ftl_trim_log) == FTL_BLOCK_SIZE, "Invalid trim log page size"); 141 142 struct ftl_p2l_ckpt; 143 struct ftl_p2l_log; 144 struct ftl_band; 145 struct spdk_ftl_dev; 146 struct ftl_mngt_process; 147 struct ftl_io; 148 struct ftl_rq; 149 150 int ftl_p2l_ckpt_init(struct spdk_ftl_dev *dev); 151 152 void ftl_p2l_ckpt_deinit(struct spdk_ftl_dev *dev); 153 154 void ftl_p2l_ckpt_issue(struct ftl_rq *rq); 155 156 struct ftl_p2l_ckpt *ftl_p2l_ckpt_acquire(struct spdk_ftl_dev *dev); 157 158 struct ftl_p2l_ckpt *ftl_p2l_ckpt_acquire_region_type(struct spdk_ftl_dev *dev, 159 uint32_t region_type); 160 161 void ftl_p2l_ckpt_release(struct spdk_ftl_dev *dev, struct ftl_p2l_ckpt *ckpt); 162 163 enum ftl_layout_region_type ftl_p2l_ckpt_region_type(const struct ftl_p2l_ckpt *ckpt); 164 165 #if defined(DEBUG) 166 void ftl_p2l_validate_ckpt(struct ftl_band *band); 167 #else 168 static inline void 169 ftl_p2l_validate_ckpt(struct ftl_band *band) 170 { 171 } 172 #endif 173 174 uint64_t ftl_mngt_p2l_ckpt_get_seq_id(struct spdk_ftl_dev *dev, int md_region); 175 176 int ftl_mngt_p2l_ckpt_restore(struct ftl_band *band, uint32_t md_region, uint64_t seq_id); 177 178 int ftl_mngt_p2l_ckpt_restore_clean(struct ftl_band *band); 179 180 void ftl_mngt_p2l_ckpt_restore_shm_clean(struct ftl_band *band); 181 182 void ftl_mngt_persist_bands_p2l(struct ftl_mngt_process *mngt); 183 184 struct ftl_reloc *ftl_reloc_init(struct spdk_ftl_dev *dev); 185 186 void ftl_reloc_free(struct ftl_reloc *reloc); 187 188 void ftl_reloc(struct ftl_reloc *reloc); 189 190 void ftl_reloc_halt(struct ftl_reloc *reloc); 191 192 void ftl_reloc_resume(struct ftl_reloc *reloc); 193 194 bool ftl_reloc_is_halted(const struct ftl_reloc *reloc); 195 196 /** 197 * P2L IO log 198 */ 199 /* 200 * @brief Initialize P2L IO log 201 * 202 * @param dev FTL device 203 * 204 * @return Initialization result 205 */ 206 int ftl_p2l_log_init(struct spdk_ftl_dev *dev); 207 208 /** 209 * @brief Deinitialize P2L IO log 210 * 211 * @param dev FTL device 212 */ 213 void ftl_p2l_log_deinit(struct spdk_ftl_dev *dev); 214 215 /** 216 * @brief Get number of blocks required in FTL MD object to store P2L IO log 217 * 218 * @param dev FTL device 219 * @param write_unit_blocks number of blocks in a write unit 220 * @param max_user_data_blocks maximum number of user data blocks within a chunk/band 221 * 222 * @return Number of blocks required 223 */ 224 uint64_t ftl_p2l_log_get_md_blocks_required(struct spdk_ftl_dev *dev, 225 uint64_t write_unit_blocks, 226 uint64_t max_user_data_blocks); 227 228 /** 229 * @brief Add an IO to the P2L IO log 230 * 231 * @param p2l P2L IO log 232 * @param io The IO to be logged 233 */ 234 void ftl_p2l_log_io(struct ftl_p2l_log *p2l, struct ftl_io *io); 235 236 /** 237 * @brief Flush the P2L IO logs 238 * 239 * @param dev FTL device 240 */ 241 void ftl_p2l_log_flush(struct spdk_ftl_dev *dev); 242 243 /** 244 * @brief Callback function invoked when IO is logged 245 * 246 * @param io IO that P2L logging was finished 247 */ 248 typedef void (*ftl_p2l_log_cb)(struct ftl_io *io); 249 250 /** 251 * @brief Get layout region type corresponding to the specific P2L log 252 * 253 * @param p2l P2L log 254 * 255 * @return Layout region type 256 */ 257 enum ftl_layout_region_type ftl_p2l_log_type(struct ftl_p2l_log *p2l); 258 259 /** 260 * @brief Acquire P2L IO log 261 * 262 * @param dev FTL device 263 * @param seq_id Sequence ID of the P2L IO log 264 * @param cb Callback function invoked when IO logging is finished 265 * 266 * @return The P2L IO log 267 */ 268 struct ftl_p2l_log *ftl_p2l_log_acquire(struct spdk_ftl_dev *dev, 269 uint64_t seq_id, 270 ftl_p2l_log_cb cb); 271 272 /** 273 * @brief Release P2L IO log 274 * 275 * @param dev FTL device 276 * @param p2l P2L IO log to be released 277 */ 278 void ftl_p2l_log_release(struct spdk_ftl_dev *dev, struct ftl_p2l_log *p2l); 279 280 /** 281 * @brief P2L Log read callback 282 * 283 * @param dev FTL device 284 * @param cb_arg The callback argument 285 * @param lba LBA value of P2L log entry 286 * @param addr Physical address of P2L log entry 287 * @param seq_id Sequence ID of P2L log entry 288 * 289 * @retval 0 Continue reading 290 * @retval Non-zero Stop reading 291 */ 292 typedef int (*ftl_p2l_log_rd_cb)(struct spdk_ftl_dev *dev, void *cb_arg, 293 uint64_t lba, ftl_addr addr, uint64_t seq_id); 294 295 /** 296 * @brief Read P2L IO log 297 * 298 * @param dev FTL device 299 * @param type The P2L IO log layout region type 300 * @param seq_id The sequence number of the log 301 * @param cb_fn The callback function which will be invoked when reading process finished 302 * @param cb_arg The callback argument 303 * @param cb_rd The callback function to report items found in the P2L log 304 * 305 * @return Operation result 306 * @retval 0 - The reading procedure started successfully 307 * @retval non-zero - An error occurred and the reading did not started 308 */ 309 int ftl_p2l_log_read(struct spdk_ftl_dev *dev, enum ftl_layout_region_type type, uint64_t seq_id, 310 spdk_ftl_fn cb_fn, void *cb_arg, ftl_p2l_log_rd_cb cb_rd); 311 312 313 #endif /* FTL_INTERNAL_H */ 314