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