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