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