1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2018 Intel Corporation. 3 * Copyright 2023 Solidigm All Rights Reserved 4 * All rights reserved. 5 */ 6 7 #ifndef FTL_BAND_H 8 #define FTL_BAND_H 9 10 #include "spdk/stdinc.h" 11 #include "spdk/bit_array.h" 12 #include "spdk/queue.h" 13 #include "spdk/crc32.h" 14 15 #include "ftl_io.h" 16 #include "ftl_internal.h" 17 #include "ftl_core.h" 18 19 #include "utils/ftl_df.h" 20 21 #define FTL_MAX_OPEN_BANDS FTL_LAYOUT_REGION_TYPE_P2L_COUNT 22 23 #define FTL_BAND_VERSION_0 0 24 #define FTL_BAND_VERSION_1 1 25 #define FTL_BAND_VERSION_2 2 26 27 #define FTL_BAND_VERSION_CURRENT FTL_BAND_VERSION_2 28 29 struct spdk_ftl_dev; 30 struct ftl_band; 31 struct ftl_rq; 32 struct ftl_basic_rq; 33 34 enum ftl_band_state { 35 FTL_BAND_STATE_FREE, 36 FTL_BAND_STATE_PREP, 37 FTL_BAND_STATE_OPENING, 38 FTL_BAND_STATE_OPEN, 39 FTL_BAND_STATE_FULL, 40 FTL_BAND_STATE_CLOSING, 41 FTL_BAND_STATE_CLOSED, 42 FTL_BAND_STATE_MAX 43 }; 44 45 typedef void (*ftl_band_state_change_fn)(struct ftl_band *band); 46 typedef void (*ftl_band_ops_cb)(struct ftl_band *band, void *ctx, bool status); 47 typedef void (*ftl_band_md_cb)(struct ftl_band *band, void *ctx, enum ftl_md_status status); 48 typedef void (*ftl_band_validate_md_cb)(struct ftl_band *band, bool valid); 49 50 struct ftl_band_md { 51 /* Band metadata version */ 52 uint64_t version; 53 54 /* Band iterator for writing */ 55 struct { 56 /* Current physical address of the write pointer */ 57 ftl_addr addr; 58 59 /* Offset from the band's start of the write pointer */ 60 uint64_t offset; 61 } iter; 62 63 /* Band's state */ 64 enum ftl_band_state state; 65 66 /* Band type set during opening */ 67 enum ftl_band_type type; 68 69 /* nv_cache p2l md region associated with band */ 70 enum ftl_layout_region_type p2l_md_region; 71 72 /* Reserved */ 73 uint8_t reserved[4]; 74 75 /* Sequence ID when band was opened */ 76 uint64_t seq; 77 78 /* Sequence ID when band was closed */ 79 uint64_t close_seq_id; 80 81 /* Number of times band was fully written (ie. number of free -> closed state cycles) */ 82 uint64_t wr_cnt; 83 84 /* Durable format object id for P2L map, allocated on shared memory */ 85 ftl_df_obj_id df_p2l_map; 86 87 /* CRC32 checksum of the associated P2L map when band is in closed state */ 88 uint32_t p2l_map_checksum; 89 90 /* Reserved */ 91 uint8_t reserved2[4020]; 92 } __attribute__((packed)); 93 94 SPDK_STATIC_ASSERT(sizeof(struct ftl_band_md) == FTL_BLOCK_SIZE, "Incorrect band metadata size"); 95 SPDK_STATIC_ASSERT(offsetof(struct ftl_band_md, version) == 0, 96 "Incorrect band metadata version offset"); 97 98 struct ftl_band { 99 /* Device this band belongs to */ 100 struct spdk_ftl_dev *dev; 101 102 struct ftl_band_md *md; 103 104 /* IO queue depth (outstanding IOs) */ 105 uint64_t queue_depth; 106 107 /* Fields for owner of the band - compaction, or gc */ 108 struct { 109 /* Callback context for the owner */ 110 void *priv; 111 112 /* State change callback */ 113 ftl_band_state_change_fn state_change_fn; 114 115 /* Callback for the owner */ 116 union { 117 ftl_band_ops_cb ops_fn; 118 ftl_band_md_cb md_fn; 119 }; 120 121 /* Reference counter */ 122 uint64_t cnt; 123 } owner; 124 125 /* P2L map */ 126 struct ftl_p2l_map p2l_map; 127 128 /* Band relocation is in progress */ 129 bool reloc; 130 131 /* Band's index */ 132 uint32_t id; 133 134 /* Band's NAND id - a group multiple bands may be part of the same physical band on base device 135 * This way the write access pattern will match the actual physical layout more closely, leading 136 * to lower overall write amplification factor 137 */ 138 uint32_t phys_id; 139 140 /* Band start addr */ 141 ftl_addr start_addr; 142 143 /* End metadata start addr */ 144 ftl_addr tail_md_addr; 145 146 /* Metadata request */ 147 struct ftl_basic_rq metadata_rq; 148 149 /* Free/shut bands' lists 150 * Open bands are kept and managed directly by the writer (either GC or compaction). Each writer only 151 * needs to keep two bands (one currently written to, and a pre-assigned reserve band to make sure flow 152 * of data is always ongoing as the current one is closing). 153 */ 154 TAILQ_ENTRY(ftl_band) queue_entry; 155 156 /* For writing metadata */ 157 struct ftl_md_io_entry_ctx md_persist_entry_ctx; 158 159 /* Callback function for validate md */ 160 ftl_band_validate_md_cb validate_cb; 161 }; 162 163 164 uint64_t ftl_band_block_offset_from_addr(struct ftl_band *band, ftl_addr addr); 165 ftl_addr ftl_band_addr_from_block_offset(struct ftl_band *band, uint64_t block_off); 166 void ftl_band_set_type(struct ftl_band *band, enum ftl_band_type type); 167 void ftl_band_set_state(struct ftl_band *band, enum ftl_band_state state); 168 const char *ftl_band_get_state_name(struct ftl_band *band); 169 void ftl_band_acquire_p2l_map(struct ftl_band *band); 170 int ftl_band_alloc_p2l_map(struct ftl_band *band); 171 int ftl_band_open_p2l_map(struct ftl_band *band); 172 void ftl_band_release_p2l_map(struct ftl_band *band); 173 ftl_addr ftl_band_next_xfer_addr(struct ftl_band *band, ftl_addr addr, size_t num_blocks); 174 ftl_addr ftl_band_next_addr(struct ftl_band *band, ftl_addr addr, size_t offset); 175 size_t ftl_band_user_blocks_left(const struct ftl_band *band, size_t offset); 176 size_t ftl_band_user_blocks(const struct ftl_band *band); 177 void ftl_band_set_p2l(struct ftl_band *band, uint64_t lba, ftl_addr addr, uint64_t seq_id); 178 void ftl_band_set_addr(struct ftl_band *band, uint64_t lba, ftl_addr addr); 179 struct ftl_band *ftl_band_from_addr(struct spdk_ftl_dev *dev, ftl_addr addr); 180 ftl_addr ftl_band_tail_md_addr(struct ftl_band *band); 181 int ftl_band_filled(struct ftl_band *band, size_t offset); 182 int ftl_band_write_prep(struct ftl_band *band); 183 size_t ftl_p2l_map_pool_elem_size(struct spdk_ftl_dev *dev); 184 struct ftl_band *ftl_band_search_next_to_reloc(struct spdk_ftl_dev *dev); 185 void ftl_band_init_gc_iter(struct spdk_ftl_dev *dev); 186 ftl_addr ftl_band_p2l_map_addr(struct ftl_band *band); 187 void ftl_valid_map_load_state(struct spdk_ftl_dev *dev); 188 int ftl_bands_load_state(struct spdk_ftl_dev *dev); 189 void ftl_band_open(struct ftl_band *band, enum ftl_band_type type); 190 void ftl_band_close(struct ftl_band *band); 191 void ftl_band_free(struct ftl_band *band); 192 void ftl_band_rq_write(struct ftl_band *band, struct ftl_rq *rq); 193 void ftl_band_rq_read(struct ftl_band *band, struct ftl_rq *rq); 194 void ftl_band_basic_rq_write(struct ftl_band *band, struct ftl_basic_rq *brq); 195 void ftl_band_basic_rq_read(struct ftl_band *band, struct ftl_basic_rq *brq); 196 void ftl_band_get_next_gc(struct spdk_ftl_dev *dev, ftl_band_ops_cb cb, void *cntx); 197 void ftl_band_read_tail_brq_md(struct ftl_band *band, ftl_band_md_cb cb, void *cntx); 198 void ftl_band_initialize_free_state(struct ftl_band *band); 199 double ftl_band_invalidity(struct ftl_band *band); 200 201 static inline void 202 ftl_band_set_owner(struct ftl_band *band, 203 ftl_band_state_change_fn fn, 204 void *priv) 205 { 206 assert(NULL == band->owner.priv); 207 assert(NULL == band->owner.state_change_fn); 208 209 band->owner.state_change_fn = fn; 210 band->owner.priv = priv; 211 } 212 213 static inline void 214 ftl_band_clear_owner(struct ftl_band *band, 215 ftl_band_state_change_fn fn, 216 void *priv) 217 { 218 assert(priv == band->owner.priv); 219 assert(fn == band->owner.state_change_fn); 220 221 band->owner.state_change_fn = NULL; 222 band->owner.priv = NULL; 223 } 224 225 static inline int 226 ftl_band_empty(const struct ftl_band *band) 227 { 228 return band->p2l_map.num_valid == 0; 229 } 230 231 static inline uint64_t 232 ftl_band_qd(const struct ftl_band *band) 233 { 234 return band->queue_depth; 235 } 236 237 static inline bool 238 ftl_band_block_offset_valid(struct ftl_band *band, size_t block_off) 239 { 240 struct ftl_p2l_map *p2l_map = &band->p2l_map; 241 242 return ftl_bitmap_get(p2l_map->valid, block_off); 243 } 244 245 static inline void 246 ftl_band_iter_init(struct ftl_band *band) 247 { 248 /* Initialize band iterator to begin state */ 249 band->md->iter.addr = band->start_addr; 250 band->md->iter.offset = 0; 251 } 252 253 static inline void 254 ftl_band_iter_advance(struct ftl_band *band, uint64_t num_blocks) 255 { 256 band->md->iter.offset += num_blocks; 257 band->md->iter.addr = ftl_band_next_xfer_addr(band, band->md->iter.addr, num_blocks); 258 assert(band->md->iter.addr != FTL_ADDR_INVALID); 259 } 260 261 static inline void 262 ftl_band_iter_set(struct ftl_band *band, uint64_t num_blocks) 263 { 264 band->md->iter.offset = num_blocks; 265 band->md->iter.addr = ftl_band_next_xfer_addr(band, band->md->iter.addr, num_blocks); 266 assert(band->md->iter.addr != FTL_ADDR_INVALID); 267 } 268 269 #endif /* FTL_BAND_H */ 270