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