1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2018 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 /* Reserved */ 68 uint8_t reserved[4]; 69 70 /* Sequence ID when band was opened */ 71 uint64_t seq; 72 73 /* Sequence ID when band was closed */ 74 uint64_t close_seq_id; 75 76 /* Number of times band was fully written (ie. number of free -> closed state cycles) */ 77 uint64_t wr_cnt; 78 79 /* Durable format object id for P2L map, allocated on shared memory */ 80 ftl_df_obj_id df_p2l_map; 81 82 /* CRC32 checksum of the associated P2L map when band is in closed state */ 83 uint32_t p2l_map_checksum; 84 85 /* Reserved */ 86 uint8_t reserved2[4028]; 87 } __attribute__((packed)); 88 89 SPDK_STATIC_ASSERT(sizeof(struct ftl_band_md) == FTL_BLOCK_SIZE, "Incorrect metadata size"); 90 91 struct ftl_band { 92 /* Device this band belongs to */ 93 struct spdk_ftl_dev *dev; 94 95 struct ftl_band_md *md; 96 97 /* IO queue depth (outstanding IOs) */ 98 uint64_t queue_depth; 99 100 /* Fields for owner of the band - compaction, or gc */ 101 struct { 102 /* Callback context for the owner */ 103 void *priv; 104 105 /* State change callback */ 106 ftl_band_state_change_fn state_change_fn; 107 108 /* Callback for the owner */ 109 union { 110 ftl_band_ops_cb ops_fn; 111 ftl_band_md_cb md_fn; 112 }; 113 114 /* Reference counter */ 115 uint64_t cnt; 116 } owner; 117 118 /* P2L map */ 119 struct ftl_p2l_map p2l_map; 120 121 /* Band relocation is in progress */ 122 bool reloc; 123 124 /* Band's index */ 125 uint32_t id; 126 127 /* Band's NAND id - a group multiple bands may be part of the same physical band on base device 128 * This way the write access pattern will match the actual physical layout more closely, leading 129 * to lower overall write amplification factor 130 */ 131 uint32_t phys_id; 132 133 /* Band start addr */ 134 ftl_addr start_addr; 135 136 /* End metadata start addr */ 137 ftl_addr tail_md_addr; 138 139 /* Metadata request */ 140 struct ftl_basic_rq metadata_rq; 141 142 /* Free/shut bands' lists 143 * Open bands are kept and managed directly by the writer (either GC or compaction). Each writer only 144 * needs to keep two bands (one currently written to, and a pre-assigned reserve band to make sure flow 145 * of data is always ongoing as the current one is closing). 146 */ 147 TAILQ_ENTRY(ftl_band) queue_entry; 148 149 /* For writing metadata */ 150 struct ftl_md_io_entry_ctx md_persist_entry_ctx; 151 152 /* Callback function for validate md */ 153 ftl_band_validate_md_cb validate_cb; 154 }; 155 156 157 uint64_t ftl_band_block_offset_from_addr(struct ftl_band *band, ftl_addr addr); 158 ftl_addr ftl_band_addr_from_block_offset(struct ftl_band *band, uint64_t block_off); 159 void ftl_band_set_type(struct ftl_band *band, enum ftl_band_type type); 160 void ftl_band_set_state(struct ftl_band *band, enum ftl_band_state state); 161 void ftl_band_acquire_p2l_map(struct ftl_band *band); 162 int ftl_band_alloc_p2l_map(struct ftl_band *band); 163 int ftl_band_open_p2l_map(struct ftl_band *band); 164 void ftl_band_release_p2l_map(struct ftl_band *band); 165 ftl_addr ftl_band_next_xfer_addr(struct ftl_band *band, ftl_addr addr, size_t num_blocks); 166 ftl_addr ftl_band_next_addr(struct ftl_band *band, ftl_addr addr, size_t offset); 167 size_t ftl_band_user_blocks_left(const struct ftl_band *band, size_t offset); 168 size_t ftl_band_user_blocks(const struct ftl_band *band); 169 void ftl_band_set_p2l(struct ftl_band *band, uint64_t lba, ftl_addr addr, uint64_t seq_id); 170 void ftl_band_set_addr(struct ftl_band *band, uint64_t lba, ftl_addr addr); 171 struct ftl_band *ftl_band_from_addr(struct spdk_ftl_dev *dev, ftl_addr addr); 172 ftl_addr ftl_band_tail_md_addr(struct ftl_band *band); 173 int ftl_band_filled(struct ftl_band *band, size_t offset); 174 int ftl_band_write_prep(struct ftl_band *band); 175 size_t ftl_p2l_map_pool_elem_size(struct spdk_ftl_dev *dev); 176 struct ftl_band *ftl_band_search_next_to_reloc(struct spdk_ftl_dev *dev); 177 void ftl_band_init_gc_iter(struct spdk_ftl_dev *dev); 178 ftl_addr ftl_band_p2l_map_addr(struct ftl_band *band); 179 void ftl_valid_map_load_state(struct spdk_ftl_dev *dev); 180 void ftl_bands_load_state(struct spdk_ftl_dev *dev); 181 void ftl_band_open(struct ftl_band *band, enum ftl_band_type type); 182 void ftl_band_close(struct ftl_band *band); 183 void ftl_band_free(struct ftl_band *band); 184 void ftl_band_rq_write(struct ftl_band *band, struct ftl_rq *rq); 185 void ftl_band_rq_read(struct ftl_band *band, struct ftl_rq *rq); 186 void ftl_band_basic_rq_write(struct ftl_band *band, struct ftl_basic_rq *brq); 187 void ftl_band_basic_rq_read(struct ftl_band *band, struct ftl_basic_rq *brq); 188 void ftl_band_get_next_gc(struct spdk_ftl_dev *dev, ftl_band_ops_cb cb, void *cntx); 189 void ftl_band_read_tail_brq_md(struct ftl_band *band, ftl_band_md_cb cb, void *cntx); 190 void ftl_band_initialize_free_state(struct ftl_band *band); 191 192 static inline void 193 ftl_band_set_owner(struct ftl_band *band, 194 ftl_band_state_change_fn fn, 195 void *priv) 196 { 197 assert(NULL == band->owner.priv); 198 assert(NULL == band->owner.state_change_fn); 199 200 band->owner.state_change_fn = fn; 201 band->owner.priv = priv; 202 } 203 204 static inline void 205 ftl_band_clear_owner(struct ftl_band *band, 206 ftl_band_state_change_fn fn, 207 void *priv) 208 { 209 assert(priv == band->owner.priv); 210 assert(fn == band->owner.state_change_fn); 211 212 band->owner.state_change_fn = NULL; 213 band->owner.priv = NULL; 214 } 215 216 static inline int 217 ftl_band_empty(const struct ftl_band *band) 218 { 219 return band->p2l_map.num_valid == 0; 220 } 221 222 static inline uint64_t 223 ftl_band_qd(const struct ftl_band *band) 224 { 225 return band->queue_depth; 226 } 227 228 static inline bool 229 ftl_band_block_offset_valid(struct ftl_band *band, size_t block_off) 230 { 231 struct ftl_p2l_map *p2l_map = &band->p2l_map; 232 233 return ftl_bitmap_get(p2l_map->valid, block_off); 234 } 235 236 static inline void 237 ftl_band_iter_init(struct ftl_band *band) 238 { 239 /* Initialize band iterator to begin state */ 240 band->md->iter.addr = band->start_addr; 241 band->md->iter.offset = 0; 242 } 243 244 static inline void 245 ftl_band_iter_advance(struct ftl_band *band, uint64_t num_blocks) 246 { 247 band->md->iter.offset += num_blocks; 248 band->md->iter.addr = ftl_band_next_xfer_addr(band, band->md->iter.addr, num_blocks); 249 assert(band->md->iter.addr != FTL_ADDR_INVALID); 250 } 251 252 static inline void 253 ftl_band_iter_set(struct ftl_band *band, uint64_t num_blocks) 254 { 255 band->md->iter.offset = num_blocks; 256 band->md->iter.addr = ftl_band_next_xfer_addr(band, band->md->iter.addr, num_blocks); 257 assert(band->md->iter.addr != FTL_ADDR_INVALID); 258 } 259 260 #endif /* FTL_BAND_H */ 261