]> git.proxmox.com Git - ceph.git/blame - 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
CommitLineData
9f95a23c
TL
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"
f67539c2 40#include "spdk/bdev_zone.h"
9f95a23c
TL
41
42#include "ftl_io.h"
f67539c2
TL
43#include "ftl_addr.h"
44#include "ftl_core.h"
9f95a23c
TL
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
49struct spdk_ftl_dev;
50struct ftl_lba_map_request;
51
f67539c2
TL
52struct ftl_zone {
53 struct spdk_bdev_zone_info info;
9f95a23c
TL
54
55 /* Indicates that there is inflight write */
56 bool busy;
57
f67539c2 58 CIRCLEQ_ENTRY(ftl_zone) circleq;
9f95a23c
TL
59};
60
61enum 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
75enum 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
81struct 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
106enum 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
117struct 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
133struct ftl_band {
134 /* Device this band belongs to */
135 struct spdk_ftl_dev *dev;
136
f67539c2
TL
137 /* Number of operational zones */
138 size_t num_zones;
9f95a23c 139
f67539c2
TL
140 /* Array of zones */
141 struct ftl_zone *zone_buf;
9f95a23c 142
f67539c2
TL
143 /* List of operational zones */
144 CIRCLEQ_HEAD(, ftl_zone) zones;
9f95a23c
TL
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
f67539c2
TL
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;
9f95a23c
TL
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
f67539c2
TL
185uint64_t ftl_band_block_offset_from_addr(struct ftl_band *band, struct ftl_addr addr);
186struct ftl_addr ftl_band_addr_from_block_offset(struct ftl_band *band, uint64_t block_off);
9f95a23c
TL
187void ftl_band_set_state(struct ftl_band *band, enum ftl_band_state state);
188size_t ftl_band_age(const struct ftl_band *band);
189void ftl_band_acquire_lba_map(struct ftl_band *band);
190int ftl_band_alloc_lba_map(struct ftl_band *band);
191void ftl_band_clear_lba_map(struct ftl_band *band);
192void ftl_band_release_lba_map(struct ftl_band *band);
193int 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);
f67539c2
TL
196struct ftl_addr ftl_band_next_xfer_addr(struct ftl_band *band, struct ftl_addr addr,
197 size_t num_blocks);
198struct ftl_addr ftl_band_next_addr(struct ftl_band *band, struct ftl_addr addr,
199 size_t offset);
200size_t ftl_band_num_usable_blocks(const struct ftl_band *band);
201size_t ftl_band_user_blocks_left(const struct ftl_band *band, size_t offset);
202size_t ftl_band_user_blocks(const struct ftl_band *band);
9f95a23c 203void ftl_band_set_addr(struct ftl_band *band, uint64_t lba,
f67539c2
TL
204 struct ftl_addr addr);
205struct ftl_band *ftl_band_from_addr(struct spdk_ftl_dev *dev, struct ftl_addr addr);
206struct ftl_zone *ftl_band_zone_from_addr(struct ftl_band *band, struct ftl_addr);
9f95a23c 207void ftl_band_md_clear(struct ftl_band *band);
f67539c2 208int ftl_band_read_tail_md(struct ftl_band *band, struct ftl_addr,
9f95a23c
TL
209 ftl_io_fn cb_fn, void *cb_ctx);
210int ftl_band_read_head_md(struct ftl_band *band, ftl_io_fn cb_fn, void *cb_ctx);
211int ftl_band_write_tail_md(struct ftl_band *band, ftl_io_fn cb);
212int ftl_band_write_head_md(struct ftl_band *band, ftl_io_fn cb);
f67539c2
TL
213struct ftl_addr ftl_band_tail_md_addr(struct ftl_band *band);
214struct ftl_addr ftl_band_head_md_addr(struct ftl_band *band);
9f95a23c
TL
215void ftl_band_write_failed(struct ftl_band *band);
216int ftl_band_full(struct ftl_band *band, size_t offset);
9f95a23c 217int ftl_band_write_prep(struct ftl_band *band);
f67539c2
TL
218struct ftl_zone *ftl_band_next_operational_zone(struct ftl_band *band,
219 struct ftl_zone *zone);
9f95a23c 220size_t ftl_lba_map_pool_elem_size(struct spdk_ftl_dev *dev);
f67539c2
TL
221void ftl_band_remove_zone(struct ftl_band *band, struct ftl_zone *zone);
222
9f95a23c
TL
223
224static inline int
225ftl_band_empty(const struct ftl_band *band)
226{
227 return band->lba_map.num_vld == 0;
228}
229
f67539c2
TL
230static inline struct ftl_zone *
231ftl_band_next_zone(struct ftl_band *band, struct ftl_zone *zone)
9f95a23c 232{
f67539c2
TL
233 assert(zone->info.state != SPDK_BDEV_ZONE_STATE_OFFLINE);
234 return CIRCLEQ_LOOP_NEXT(&band->zones, zone, circleq);
9f95a23c
TL
235}
236
237static inline void
238ftl_band_set_next_state(struct ftl_band *band)
239{
240 ftl_band_set_state(band, (band->state + 1) % FTL_BAND_STATE_MAX);
241}
242
243static inline int
244ftl_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
250static inline int
f67539c2 251ftl_band_block_offset_valid(struct ftl_band *band, size_t block_off)
9f95a23c
TL
252{
253 struct ftl_lba_map *lba_map = &band->lba_map;
254
255 pthread_spin_lock(&lba_map->lock);
f67539c2 256 if (spdk_bit_array_get(lba_map->vld, block_off)) {
9f95a23c
TL
257 pthread_spin_unlock(&lba_map->lock);
258 return 1;
259 }
260
261 pthread_spin_unlock(&lba_map->lock);
262 return 0;
263}
264
265static inline int
f67539c2 266ftl_band_zone_is_last(struct ftl_band *band, struct ftl_zone *zone)
9f95a23c 267{
f67539c2 268 return zone == CIRCLEQ_LAST(&band->zones);
9f95a23c
TL
269}
270
271static inline int
f67539c2 272ftl_band_zone_is_first(struct ftl_band *band, struct ftl_zone *zone)
9f95a23c 273{
f67539c2 274 return zone == CIRCLEQ_FIRST(&band->zones);
9f95a23c
TL
275}
276
277static inline int
f67539c2 278ftl_zone_is_writable(const struct spdk_ftl_dev *dev, const struct ftl_zone *zone)
9f95a23c 279{
f67539c2
TL
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;
9f95a23c
TL
285}
286
287#endif /* FTL_BAND_H */