xref: /spdk/lib/ftl/ftl_band.h (revision b30d57cdad6d2bc75cc1e4e2ebbcebcb0d98dcfa)
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