xref: /spdk/lib/ftl/ftl_band.h (revision 0e33da49749d6ceba57497997d8a777f6ba20745)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (c) Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #ifndef FTL_BAND_H
7 #define FTL_BAND_H
8 
9 #include "spdk/stdinc.h"
10 #include "spdk/bit_array.h"
11 #include "spdk/queue.h"
12 #include "spdk/crc32.h"
13 
14 #include "ftl_io.h"
15 #include "ftl_internal.h"
16 #include "ftl_core.h"
17 
18 #include "utils/ftl_df.h"
19 
20 #define FTL_MAX_OPEN_BANDS 4
21 
22 #define FTL_BAND_VERSION_0	0
23 #define FTL_BAND_VERSION_1	1
24 
25 #define FTL_BAND_VERSION_CURRENT FTL_BAND_VERSION_1
26 
27 struct spdk_ftl_dev;
28 struct ftl_band;
29 struct ftl_rq;
30 struct ftl_basic_rq;
31 
32 enum ftl_band_state {
33 	FTL_BAND_STATE_FREE,
34 	FTL_BAND_STATE_PREP,
35 	FTL_BAND_STATE_OPENING,
36 	FTL_BAND_STATE_OPEN,
37 	FTL_BAND_STATE_FULL,
38 	FTL_BAND_STATE_CLOSING,
39 	FTL_BAND_STATE_CLOSED,
40 	FTL_BAND_STATE_MAX
41 };
42 
43 typedef void (*ftl_band_state_change_fn)(struct ftl_band *band);
44 typedef void (*ftl_band_ops_cb)(struct ftl_band *band, void *ctx, bool status);
45 typedef void (*ftl_band_md_cb)(struct ftl_band *band, void *ctx, enum ftl_md_status status);
46 
47 struct ftl_band_md {
48 	/* Band iterator for writing */
49 	struct {
50 		/* Current physical address of the write pointer */
51 		ftl_addr		addr;
52 
53 		/* Offset from the band's start of the write pointer */
54 		uint64_t		offset;
55 	} iter;
56 
57 	/* Band's state */
58 	enum ftl_band_state		state;
59 
60 	/* Band type set during opening */
61 	enum ftl_band_type		type;
62 
63 	/* Number of times band was fully written (ie. number of free -> closed state cycles) */
64 	uint64_t			wr_cnt;
65 
66 	/* Durable format object id for P2L map, allocated on shared memory */
67 	ftl_df_obj_id			df_p2l_map;
68 
69 	/* CRC32 checksum of the associated P2L map when band is in closed state */
70 	uint32_t			p2l_map_checksum;
71 } __attribute__((aligned(FTL_BLOCK_SIZE)));
72 
73 SPDK_STATIC_ASSERT(sizeof(struct ftl_band_md) == FTL_BLOCK_SIZE, "Incorrect metadata size");
74 
75 struct ftl_band {
76 	/* Device this band belongs to */
77 	struct spdk_ftl_dev		*dev;
78 
79 	struct ftl_band_md		*md;
80 
81 	/* IO queue depth (outstanding IOs) */
82 	uint64_t			queue_depth;
83 
84 	/* Fields for owner of the band - compaction, or gc */
85 	struct {
86 		/* Callback context for the owner */
87 		void *priv;
88 
89 		/* State change callback */
90 		ftl_band_state_change_fn state_change_fn;
91 
92 		/* Callback for the owner */
93 		union {
94 			ftl_band_ops_cb ops_fn;
95 			ftl_band_md_cb md_fn;
96 		};
97 
98 		/* Reference counter */
99 		uint64_t cnt;
100 	} owner;
101 
102 	/* P2L map */
103 	struct ftl_p2l_map		p2l_map;
104 
105 	/* Band relocation is in progress */
106 	bool				reloc;
107 
108 	/* Band's index */
109 	uint32_t			id;
110 
111 	/* Band's NAND id - a group multiple bands may be part of the same physical band on base device
112 	 * This way the write access pattern will match the actual physical layout more closely, leading
113 	 * to lower overall write amplification factor
114 	 */
115 	uint32_t			phys_id;
116 
117 	/* Band start addr */
118 	ftl_addr			start_addr;
119 
120 	/* End metadata start addr */
121 	ftl_addr			tail_md_addr;
122 
123 	/* Metadata request */
124 	struct ftl_basic_rq		metadata_rq;
125 
126 	/* Free/shut bands' lists
127 	 * Open bands are kept and managed directly by the writer (either GC or compaction). Each writer only
128 	 * needs to keep two bands (one currently written to, and a pre-assigned reserve band to make sure flow
129 	 * of data is always ongoing as the current one is closing).
130 	 */
131 	TAILQ_ENTRY(ftl_band)		queue_entry;
132 
133 	/* For writing metadata */
134 	struct ftl_md_io_entry_ctx	md_persist_entry_ctx;
135 };
136 
137 
138 uint64_t ftl_band_block_offset_from_addr(struct ftl_band *band, ftl_addr addr);
139 ftl_addr ftl_band_addr_from_block_offset(struct ftl_band *band, uint64_t block_off);
140 void ftl_band_set_type(struct ftl_band *band, enum ftl_band_type type);
141 void ftl_band_set_state(struct ftl_band *band, enum ftl_band_state state);
142 void ftl_band_acquire_p2l_map(struct ftl_band *band);
143 int ftl_band_alloc_p2l_map(struct ftl_band *band);
144 void ftl_band_release_p2l_map(struct ftl_band *band);
145 ftl_addr ftl_band_next_xfer_addr(struct ftl_band *band, ftl_addr addr, size_t num_blocks);
146 ftl_addr ftl_band_next_addr(struct ftl_band *band, ftl_addr addr, size_t offset);
147 size_t ftl_band_user_blocks_left(const struct ftl_band *band, size_t offset);
148 size_t ftl_band_user_blocks(const struct ftl_band *band);
149 void ftl_band_set_addr(struct ftl_band *band, uint64_t lba, ftl_addr addr);
150 struct ftl_band *ftl_band_from_addr(struct spdk_ftl_dev *dev, ftl_addr addr);
151 ftl_addr ftl_band_tail_md_addr(struct ftl_band *band);
152 int ftl_band_filled(struct ftl_band *band, size_t offset);
153 int ftl_band_write_prep(struct ftl_band *band);
154 size_t ftl_p2l_map_pool_elem_size(struct spdk_ftl_dev *dev);
155 struct ftl_band *ftl_band_search_next_to_reloc(struct spdk_ftl_dev *dev);
156 void ftl_band_init_gc_iter(struct spdk_ftl_dev *dev);
157 ftl_addr ftl_band_p2l_map_addr(struct ftl_band *band);
158 void ftl_band_open(struct ftl_band *band, enum ftl_band_type type);
159 void ftl_band_close(struct ftl_band *band);
160 void ftl_band_free(struct ftl_band *band);
161 void ftl_band_rq_write(struct ftl_band *band, struct ftl_rq *rq);
162 void ftl_band_rq_read(struct ftl_band *band, struct ftl_rq *rq);
163 void ftl_band_basic_rq_write(struct ftl_band *band, struct ftl_basic_rq *brq);
164 void ftl_band_basic_rq_read(struct ftl_band *band, struct ftl_basic_rq *brq);
165 void ftl_band_get_next_gc(struct spdk_ftl_dev *dev, ftl_band_ops_cb cb, void *cntx);
166 void ftl_band_read_tail_brq_md(struct ftl_band *band, ftl_band_md_cb cb, void *cntx);
167 
168 static inline void
169 ftl_band_set_owner(struct ftl_band *band,
170 		   ftl_band_state_change_fn fn,
171 		   void *priv)
172 {
173 	assert(NULL == band->owner.priv);
174 	assert(NULL == band->owner.state_change_fn);
175 
176 	band->owner.state_change_fn = fn;
177 	band->owner.priv = priv;
178 }
179 
180 static inline void
181 ftl_band_clear_owner(struct ftl_band *band,
182 		     ftl_band_state_change_fn fn,
183 		     void *priv)
184 {
185 	assert(priv == band->owner.priv);
186 	assert(fn == band->owner.state_change_fn);
187 
188 	band->owner.state_change_fn = NULL;
189 	band->owner.priv = NULL;
190 }
191 
192 static inline int
193 ftl_band_empty(const struct ftl_band *band)
194 {
195 	return band->p2l_map.num_valid == 0;
196 }
197 
198 static inline uint64_t
199 ftl_band_qd(const struct ftl_band *band)
200 {
201 	return band->queue_depth;
202 }
203 
204 static inline void
205 ftl_band_iter_init(struct ftl_band *band)
206 {
207 	/* Initialize band iterator to begin state */
208 	band->md->iter.addr = band->start_addr;
209 	band->md->iter.offset = 0;
210 }
211 
212 static inline void
213 ftl_band_iter_advance(struct ftl_band *band, uint64_t num_blocks)
214 {
215 	band->md->iter.offset += num_blocks;
216 	band->md->iter.addr = ftl_band_next_xfer_addr(band, band->md->iter.addr, num_blocks);
217 	assert(band->md->iter.addr != FTL_ADDR_INVALID);
218 }
219 
220 static inline void
221 ftl_band_iter_set(struct ftl_band *band, uint64_t num_blocks)
222 {
223 	band->md->iter.offset = num_blocks;
224 	band->md->iter.addr = ftl_band_next_xfer_addr(band, band->md->iter.addr, num_blocks);
225 	assert(band->md->iter.addr != FTL_ADDR_INVALID);
226 }
227 
228 #endif /* FTL_BAND_H */
229