]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/lib/ftl/ftl_band.h
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / lib / ftl / ftl_band.h
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 */