1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #ifndef FTL_BAND_H 35 #define FTL_BAND_H 36 37 #include "spdk/stdinc.h" 38 #include "spdk/bit_array.h" 39 #include "spdk/queue.h" 40 #include "spdk/bdev_zone.h" 41 42 #include "ftl_io.h" 43 #include "ftl_addr.h" 44 #include "ftl_core.h" 45 46 /* Number of LBAs that could be stored in a single block */ 47 #define FTL_NUM_LBA_IN_BLOCK (FTL_BLOCK_SIZE / sizeof(uint64_t)) 48 49 struct spdk_ftl_dev; 50 struct ftl_lba_map_request; 51 52 struct ftl_zone { 53 struct spdk_bdev_zone_info info; 54 55 /* Indicates that there is inflight write */ 56 bool busy; 57 58 CIRCLEQ_ENTRY(ftl_zone) circleq; 59 }; 60 61 enum ftl_md_status { 62 FTL_MD_SUCCESS, 63 /* Metadata read failure */ 64 FTL_MD_IO_FAILURE, 65 /* Invalid version */ 66 FTL_MD_INVALID_VER, 67 /* UUID doesn't match */ 68 FTL_MD_NO_MD, 69 /* UUID and version matches but CRC doesn't */ 70 FTL_MD_INVALID_CRC, 71 /* Vld or lba map size doesn't match */ 72 FTL_MD_INVALID_SIZE 73 }; 74 75 enum ftl_lba_map_seg_state { 76 FTL_LBA_MAP_SEG_CLEAR, 77 FTL_LBA_MAP_SEG_PENDING, 78 FTL_LBA_MAP_SEG_CACHED 79 }; 80 81 struct ftl_lba_map { 82 /* LBA/vld map lock */ 83 pthread_spinlock_t lock; 84 85 /* Number of valid LBAs */ 86 size_t num_vld; 87 88 /* LBA map's reference count */ 89 size_t ref_cnt; 90 91 /* Bitmap of valid LBAs */ 92 struct spdk_bit_array *vld; 93 94 /* LBA map (only valid for open/relocating bands) */ 95 uint64_t *map; 96 97 /* LBA map segment state map (clear, pending, cached) */ 98 uint8_t *segments; 99 100 LIST_HEAD(, ftl_lba_map_request) request_list; 101 102 /* Metadata DMA buffer (only valid for open/relocating bands) */ 103 void *dma_buf; 104 }; 105 106 enum ftl_band_state { 107 FTL_BAND_STATE_FREE, 108 FTL_BAND_STATE_PREP, 109 FTL_BAND_STATE_OPENING, 110 FTL_BAND_STATE_OPEN, 111 FTL_BAND_STATE_FULL, 112 FTL_BAND_STATE_CLOSING, 113 FTL_BAND_STATE_CLOSED, 114 FTL_BAND_STATE_MAX 115 }; 116 117 struct ftl_lba_map_request { 118 /* Completion callback */ 119 ftl_io_fn cb; 120 121 /* Completion callback context */ 122 void *cb_ctx; 123 124 /* Bit array of requested segments */ 125 struct spdk_bit_array *segments; 126 127 /* Number of pending segments to read */ 128 size_t num_pending; 129 130 LIST_ENTRY(ftl_lba_map_request) list_entry; 131 }; 132 133 struct ftl_band { 134 /* Device this band belongs to */ 135 struct spdk_ftl_dev *dev; 136 137 /* Number of operational zones */ 138 size_t num_zones; 139 140 /* Array of zones */ 141 struct ftl_zone *zone_buf; 142 143 /* List of operational zones */ 144 CIRCLEQ_HEAD(, ftl_zone) zones; 145 146 /* LBA map */ 147 struct ftl_lba_map lba_map; 148 149 /* Band's state */ 150 enum ftl_band_state state; 151 152 /* Band's index */ 153 unsigned int id; 154 155 /* Latest merit calculation */ 156 double merit; 157 158 /* High defrag priority - means that the metadata should be copied and */ 159 /* the band should be defragged immediately */ 160 int high_prio; 161 162 /* Sequence number */ 163 uint64_t seq; 164 165 /* Number of defrag cycles */ 166 uint64_t wr_cnt; 167 168 /* End metadata start addr */ 169 struct ftl_addr tail_md_addr; 170 171 /* Bitmap of all bands that have its data moved onto this band */ 172 struct spdk_bit_array *reloc_bitmap; 173 /* Number of open bands containing data moved from this band */ 174 size_t num_reloc_bands; 175 /* Number of blocks currently being moved from this band */ 176 size_t num_reloc_blocks; 177 178 /* Free/shut bands' lists */ 179 LIST_ENTRY(ftl_band) list_entry; 180 181 /* High priority queue link */ 182 STAILQ_ENTRY(ftl_band) prio_stailq; 183 }; 184 185 uint64_t ftl_band_block_offset_from_addr(struct ftl_band *band, struct ftl_addr addr); 186 struct ftl_addr ftl_band_addr_from_block_offset(struct ftl_band *band, uint64_t block_off); 187 void ftl_band_set_state(struct ftl_band *band, enum ftl_band_state state); 188 size_t ftl_band_age(const struct ftl_band *band); 189 void ftl_band_acquire_lba_map(struct ftl_band *band); 190 int ftl_band_alloc_lba_map(struct ftl_band *band); 191 void ftl_band_clear_lba_map(struct ftl_band *band); 192 void ftl_band_release_lba_map(struct ftl_band *band); 193 int ftl_band_read_lba_map(struct ftl_band *band, 194 size_t offset, size_t lba_cnt, 195 ftl_io_fn cb_fn, void *cb_ctx); 196 struct ftl_addr ftl_band_next_xfer_addr(struct ftl_band *band, struct ftl_addr addr, 197 size_t num_blocks); 198 struct ftl_addr ftl_band_next_addr(struct ftl_band *band, struct ftl_addr addr, 199 size_t offset); 200 size_t ftl_band_num_usable_blocks(const struct ftl_band *band); 201 size_t ftl_band_user_blocks_left(const struct ftl_band *band, size_t offset); 202 size_t ftl_band_user_blocks(const struct ftl_band *band); 203 void ftl_band_set_addr(struct ftl_band *band, uint64_t lba, 204 struct ftl_addr addr); 205 struct ftl_band *ftl_band_from_addr(struct spdk_ftl_dev *dev, struct ftl_addr addr); 206 struct ftl_zone *ftl_band_zone_from_addr(struct ftl_band *band, struct ftl_addr); 207 void ftl_band_md_clear(struct ftl_band *band); 208 int ftl_band_read_tail_md(struct ftl_band *band, struct ftl_addr, 209 ftl_io_fn cb_fn, void *cb_ctx); 210 int ftl_band_read_head_md(struct ftl_band *band, ftl_io_fn cb_fn, void *cb_ctx); 211 int ftl_band_write_tail_md(struct ftl_band *band, ftl_io_fn cb); 212 int ftl_band_write_head_md(struct ftl_band *band, ftl_io_fn cb); 213 struct ftl_addr ftl_band_tail_md_addr(struct ftl_band *band); 214 struct ftl_addr ftl_band_head_md_addr(struct ftl_band *band); 215 void ftl_band_write_failed(struct ftl_band *band); 216 int ftl_band_full(struct ftl_band *band, size_t offset); 217 int ftl_band_write_prep(struct ftl_band *band); 218 struct ftl_zone *ftl_band_next_operational_zone(struct ftl_band *band, 219 struct ftl_zone *zone); 220 size_t ftl_lba_map_pool_elem_size(struct spdk_ftl_dev *dev); 221 void ftl_band_remove_zone(struct ftl_band *band, struct ftl_zone *zone); 222 223 224 static inline int 225 ftl_band_empty(const struct ftl_band *band) 226 { 227 return band->lba_map.num_vld == 0; 228 } 229 230 static inline struct ftl_zone * 231 ftl_band_next_zone(struct ftl_band *band, struct ftl_zone *zone) 232 { 233 assert(zone->info.state != SPDK_BDEV_ZONE_STATE_OFFLINE); 234 return CIRCLEQ_LOOP_NEXT(&band->zones, zone, circleq); 235 } 236 237 static inline void 238 ftl_band_set_next_state(struct ftl_band *band) 239 { 240 ftl_band_set_state(band, (band->state + 1) % FTL_BAND_STATE_MAX); 241 } 242 243 static inline int 244 ftl_band_state_changing(struct ftl_band *band) 245 { 246 return band->state == FTL_BAND_STATE_OPENING || 247 band->state == FTL_BAND_STATE_CLOSING; 248 } 249 250 static inline int 251 ftl_band_block_offset_valid(struct ftl_band *band, size_t block_off) 252 { 253 struct ftl_lba_map *lba_map = &band->lba_map; 254 255 pthread_spin_lock(&lba_map->lock); 256 if (spdk_bit_array_get(lba_map->vld, block_off)) { 257 pthread_spin_unlock(&lba_map->lock); 258 return 1; 259 } 260 261 pthread_spin_unlock(&lba_map->lock); 262 return 0; 263 } 264 265 static inline int 266 ftl_band_zone_is_last(struct ftl_band *band, struct ftl_zone *zone) 267 { 268 return zone == CIRCLEQ_LAST(&band->zones); 269 } 270 271 static inline int 272 ftl_band_zone_is_first(struct ftl_band *band, struct ftl_zone *zone) 273 { 274 return zone == CIRCLEQ_FIRST(&band->zones); 275 } 276 277 static inline int 278 ftl_zone_is_writable(const struct spdk_ftl_dev *dev, const struct ftl_zone *zone) 279 { 280 bool busy = ftl_is_append_supported(dev) ? false : zone->busy; 281 282 return (zone->info.state == SPDK_BDEV_ZONE_STATE_OPEN || 283 zone->info.state == SPDK_BDEV_ZONE_STATE_EMPTY) && 284 !busy; 285 } 286 287 #endif /* FTL_BAND_H */ 288