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