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 41 #include "ftl_ppa.h" 42 43 struct spdk_ftl_dev; 44 struct ftl_cb; 45 46 enum ftl_chunk_state { 47 FTL_CHUNK_STATE_FREE, 48 FTL_CHUNK_STATE_OPEN, 49 FTL_CHUNK_STATE_CLOSED, 50 FTL_CHUNK_STATE_BAD, 51 FTL_CHUNK_STATE_VACANT, 52 }; 53 54 struct ftl_chunk { 55 /* Block state */ 56 enum ftl_chunk_state state; 57 58 /* Indicates that there is inflight write */ 59 bool busy; 60 61 /* First PPA */ 62 struct ftl_ppa start_ppa; 63 64 /* Pointer to parallel unit */ 65 struct ftl_punit *punit; 66 67 /* Position in band's chunk_buf */ 68 uint32_t pos; 69 70 CIRCLEQ_ENTRY(ftl_chunk) circleq; 71 }; 72 73 enum ftl_md_status { 74 FTL_MD_SUCCESS, 75 /* Metadata read failure */ 76 FTL_MD_IO_FAILURE, 77 /* Invalid version */ 78 FTL_MD_INVALID_VER, 79 /* UUID doesn't match */ 80 FTL_MD_NO_MD, 81 /* UUID and version matches but CRC doesn't */ 82 FTL_MD_INVALID_CRC, 83 /* Vld or lba map size doesn't match */ 84 FTL_MD_INVALID_SIZE 85 }; 86 87 struct ftl_md { 88 /* Sequence number */ 89 uint64_t seq; 90 91 /* Number of defrag cycles */ 92 uint64_t wr_cnt; 93 94 /* LBA/vld map lock */ 95 pthread_spinlock_t lock; 96 97 /* Number of valid LBAs */ 98 size_t num_vld; 99 100 /* LBA map's reference count */ 101 size_t ref_cnt; 102 103 /* Bitmap of valid LBAs */ 104 struct spdk_bit_array *vld_map; 105 106 /* LBA map (only valid for open/relocating bands) */ 107 uint64_t *lba_map; 108 109 /* Metadata DMA buffer (only valid for open/relocating bands) */ 110 void *dma_buf; 111 }; 112 113 enum ftl_band_state { 114 FTL_BAND_STATE_FREE, 115 FTL_BAND_STATE_PREP, 116 FTL_BAND_STATE_OPENING, 117 FTL_BAND_STATE_OPEN, 118 FTL_BAND_STATE_FULL, 119 FTL_BAND_STATE_CLOSING, 120 FTL_BAND_STATE_CLOSED, 121 FTL_BAND_STATE_MAX 122 }; 123 124 struct ftl_band { 125 /* Device this band belongs to */ 126 struct spdk_ftl_dev *dev; 127 128 /* Number of operational chunks */ 129 size_t num_chunks; 130 131 /* Array of chunks */ 132 struct ftl_chunk *chunk_buf; 133 134 /* List of operational chunks */ 135 CIRCLEQ_HEAD(, ftl_chunk) chunks; 136 137 /* Band's metadata */ 138 struct ftl_md md; 139 140 /* Band's state */ 141 enum ftl_band_state state; 142 143 /* Band's index */ 144 unsigned int id; 145 146 /* Latest merit calculation */ 147 double merit; 148 149 /* High defrag priority - means that the metadata should be copied and */ 150 /* the band should be defragged immediately */ 151 int high_prio; 152 153 /* End metadata start ppa */ 154 struct ftl_ppa tail_md_ppa; 155 156 /* Free/shut bands' lists */ 157 LIST_ENTRY(ftl_band) list_entry; 158 159 /* High priority queue link */ 160 STAILQ_ENTRY(ftl_band) prio_stailq; 161 }; 162 163 uint64_t ftl_band_lbkoff_from_ppa(struct ftl_band *band, struct ftl_ppa ppa); 164 struct ftl_ppa ftl_band_ppa_from_lbkoff(struct ftl_band *band, uint64_t lbkoff); 165 void ftl_band_set_state(struct ftl_band *band, enum ftl_band_state state); 166 size_t ftl_band_age(const struct ftl_band *band); 167 void ftl_band_acquire_md(struct ftl_band *band); 168 int ftl_band_alloc_md(struct ftl_band *band); 169 void ftl_band_release_md(struct ftl_band *band); 170 struct ftl_ppa ftl_band_next_xfer_ppa(struct ftl_band *band, struct ftl_ppa ppa, 171 size_t num_lbks); 172 struct ftl_ppa ftl_band_next_ppa(struct ftl_band *band, struct ftl_ppa ppa, 173 size_t offset); 174 size_t ftl_band_num_usable_lbks(const struct ftl_band *band); 175 size_t ftl_band_user_lbks(const struct ftl_band *band); 176 void ftl_band_set_addr(struct ftl_band *band, uint64_t lba, 177 struct ftl_ppa ppa); 178 struct ftl_band *ftl_band_from_ppa(struct spdk_ftl_dev *dev, struct ftl_ppa ppa); 179 struct ftl_chunk *ftl_band_chunk_from_ppa(struct ftl_band *band, struct ftl_ppa); 180 void ftl_band_md_clear(struct ftl_md *md); 181 int ftl_band_read_tail_md(struct ftl_band *band, struct ftl_md *md, 182 void *data, struct ftl_ppa, 183 const struct ftl_cb *cb); 184 int ftl_band_read_head_md(struct ftl_band *band, struct ftl_md *md, 185 void *data, const struct ftl_cb *cb); 186 int ftl_band_read_lba_map(struct ftl_band *band, struct ftl_md *md, 187 void *data, const struct ftl_cb *cb); 188 int ftl_band_write_tail_md(struct ftl_band *band, void *data, spdk_ftl_fn cb); 189 int ftl_band_write_head_md(struct ftl_band *band, void *data, spdk_ftl_fn cb); 190 struct ftl_ppa ftl_band_tail_md_ppa(struct ftl_band *band); 191 struct ftl_ppa ftl_band_head_md_ppa(struct ftl_band *band); 192 void ftl_band_write_failed(struct ftl_band *band); 193 void ftl_band_clear_md(struct ftl_band *band); 194 int ftl_band_full(struct ftl_band *band, size_t offset); 195 int ftl_band_erase(struct ftl_band *band); 196 int ftl_band_write_prep(struct ftl_band *band); 197 struct ftl_chunk *ftl_band_next_operational_chunk(struct ftl_band *band, 198 struct ftl_chunk *chunk); 199 200 static inline int 201 ftl_band_empty(const struct ftl_band *band) 202 { 203 return band->md.num_vld == 0; 204 } 205 206 static inline struct ftl_chunk * 207 ftl_band_next_chunk(struct ftl_band *band, struct ftl_chunk *chunk) 208 { 209 assert(chunk->state != FTL_CHUNK_STATE_BAD); 210 return CIRCLEQ_LOOP_NEXT(&band->chunks, chunk, circleq); 211 } 212 213 static inline void 214 ftl_band_set_next_state(struct ftl_band *band) 215 { 216 ftl_band_set_state(band, (band->state + 1) % FTL_BAND_STATE_MAX); 217 } 218 219 static inline int 220 ftl_band_state_changing(struct ftl_band *band) 221 { 222 return band->state == FTL_BAND_STATE_OPENING || 223 band->state == FTL_BAND_STATE_CLOSING; 224 } 225 226 static inline int 227 ftl_band_lbkoff_valid(struct ftl_band *band, size_t lbkoff) 228 { 229 struct ftl_md *md = &band->md; 230 231 pthread_spin_lock(&md->lock); 232 if (spdk_bit_array_get(md->vld_map, lbkoff)) { 233 pthread_spin_unlock(&md->lock); 234 return 1; 235 } 236 237 pthread_spin_unlock(&md->lock); 238 return 0; 239 } 240 241 static inline int 242 ftl_band_chunk_is_last(struct ftl_band *band, struct ftl_chunk *chunk) 243 { 244 return chunk == CIRCLEQ_LAST(&band->chunks); 245 } 246 247 static inline int 248 ftl_band_chunk_is_first(struct ftl_band *band, struct ftl_chunk *chunk) 249 { 250 return chunk == CIRCLEQ_FIRST(&band->chunks); 251 } 252 253 static inline int 254 ftl_chunk_is_writable(const struct ftl_chunk *chunk) 255 { 256 return (chunk->state == FTL_CHUNK_STATE_OPEN || 257 chunk->state == FTL_CHUNK_STATE_FREE) && 258 !chunk->busy; 259 } 260 261 #endif /* FTL_BAND_H */ 262