xref: /spdk/lib/ftl/ftl_band.h (revision a6dbe3721eb3b5990707fc3e378c95e505dd8ab5)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2018 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 FTL_LAYOUT_REGION_TYPE_P2L_COUNT
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 typedef void (*ftl_band_validate_md_cb)(struct ftl_band *band, bool valid);
47 
48 struct ftl_band_md {
49 	/* Band iterator for writing */
50 	struct {
51 		/* Current physical address of the write pointer */
52 		ftl_addr		addr;
53 
54 		/* Offset from the band's start of the write pointer */
55 		uint64_t		offset;
56 	} iter;
57 
58 	/* Band's state */
59 	enum ftl_band_state		state;
60 
61 	/* Band type set during opening */
62 	enum ftl_band_type		type;
63 
64 	/* nv_cache p2l md region associated with band */
65 	enum ftl_layout_region_type	p2l_md_region;
66 
67 	/* Reserved */
68 	uint8_t				reserved[4];
69 
70 	/* Sequence ID when band was opened */
71 	uint64_t			seq;
72 
73 	/* Sequence ID when band was closed */
74 	uint64_t			close_seq_id;
75 
76 	/* Number of times band was fully written (ie. number of free -> closed state cycles) */
77 	uint64_t			wr_cnt;
78 
79 	/* Durable format object id for P2L map, allocated on shared memory */
80 	ftl_df_obj_id			df_p2l_map;
81 
82 	/* CRC32 checksum of the associated P2L map when band is in closed state */
83 	uint32_t			p2l_map_checksum;
84 
85 	/* Reserved */
86 	uint8_t				reserved2[4028];
87 } __attribute__((packed));
88 
89 SPDK_STATIC_ASSERT(sizeof(struct ftl_band_md) == FTL_BLOCK_SIZE, "Incorrect metadata size");
90 
91 struct ftl_band {
92 	/* Device this band belongs to */
93 	struct spdk_ftl_dev		*dev;
94 
95 	struct ftl_band_md		*md;
96 
97 	/* IO queue depth (outstanding IOs) */
98 	uint64_t			queue_depth;
99 
100 	/* Fields for owner of the band - compaction, or gc */
101 	struct {
102 		/* Callback context for the owner */
103 		void *priv;
104 
105 		/* State change callback */
106 		ftl_band_state_change_fn state_change_fn;
107 
108 		/* Callback for the owner */
109 		union {
110 			ftl_band_ops_cb ops_fn;
111 			ftl_band_md_cb md_fn;
112 		};
113 
114 		/* Reference counter */
115 		uint64_t cnt;
116 	} owner;
117 
118 	/* P2L map */
119 	struct ftl_p2l_map		p2l_map;
120 
121 	/* Band relocation is in progress */
122 	bool				reloc;
123 
124 	/* Band's index */
125 	uint32_t			id;
126 
127 	/* Band's NAND id - a group multiple bands may be part of the same physical band on base device
128 	 * This way the write access pattern will match the actual physical layout more closely, leading
129 	 * to lower overall write amplification factor
130 	 */
131 	uint32_t			phys_id;
132 
133 	/* Band start addr */
134 	ftl_addr			start_addr;
135 
136 	/* End metadata start addr */
137 	ftl_addr			tail_md_addr;
138 
139 	/* Metadata request */
140 	struct ftl_basic_rq		metadata_rq;
141 
142 	/* Free/shut bands' lists
143 	 * Open bands are kept and managed directly by the writer (either GC or compaction). Each writer only
144 	 * needs to keep two bands (one currently written to, and a pre-assigned reserve band to make sure flow
145 	 * of data is always ongoing as the current one is closing).
146 	 */
147 	TAILQ_ENTRY(ftl_band)		queue_entry;
148 
149 	/* For writing metadata */
150 	struct ftl_md_io_entry_ctx	md_persist_entry_ctx;
151 
152 	/* Callback function for validate md */
153 	ftl_band_validate_md_cb		validate_cb;
154 };
155 
156 
157 uint64_t ftl_band_block_offset_from_addr(struct ftl_band *band, ftl_addr addr);
158 ftl_addr ftl_band_addr_from_block_offset(struct ftl_band *band, uint64_t block_off);
159 void ftl_band_set_type(struct ftl_band *band, enum ftl_band_type type);
160 void ftl_band_set_state(struct ftl_band *band, enum ftl_band_state state);
161 void ftl_band_acquire_p2l_map(struct ftl_band *band);
162 int ftl_band_alloc_p2l_map(struct ftl_band *band);
163 int ftl_band_open_p2l_map(struct ftl_band *band);
164 void ftl_band_release_p2l_map(struct ftl_band *band);
165 ftl_addr ftl_band_next_xfer_addr(struct ftl_band *band, ftl_addr addr, size_t num_blocks);
166 ftl_addr ftl_band_next_addr(struct ftl_band *band, ftl_addr addr, size_t offset);
167 size_t ftl_band_user_blocks_left(const struct ftl_band *band, size_t offset);
168 size_t ftl_band_user_blocks(const struct ftl_band *band);
169 void ftl_band_set_p2l(struct ftl_band *band, uint64_t lba, ftl_addr addr, uint64_t seq_id);
170 void ftl_band_set_addr(struct ftl_band *band, uint64_t lba, ftl_addr addr);
171 struct ftl_band *ftl_band_from_addr(struct spdk_ftl_dev *dev, ftl_addr addr);
172 ftl_addr ftl_band_tail_md_addr(struct ftl_band *band);
173 int ftl_band_filled(struct ftl_band *band, size_t offset);
174 int ftl_band_write_prep(struct ftl_band *band);
175 size_t ftl_p2l_map_pool_elem_size(struct spdk_ftl_dev *dev);
176 struct ftl_band *ftl_band_search_next_to_reloc(struct spdk_ftl_dev *dev);
177 void ftl_band_init_gc_iter(struct spdk_ftl_dev *dev);
178 ftl_addr ftl_band_p2l_map_addr(struct ftl_band *band);
179 void ftl_valid_map_load_state(struct spdk_ftl_dev *dev);
180 void ftl_bands_load_state(struct spdk_ftl_dev *dev);
181 void ftl_band_open(struct ftl_band *band, enum ftl_band_type type);
182 void ftl_band_close(struct ftl_band *band);
183 void ftl_band_free(struct ftl_band *band);
184 void ftl_band_rq_write(struct ftl_band *band, struct ftl_rq *rq);
185 void ftl_band_rq_read(struct ftl_band *band, struct ftl_rq *rq);
186 void ftl_band_basic_rq_write(struct ftl_band *band, struct ftl_basic_rq *brq);
187 void ftl_band_basic_rq_read(struct ftl_band *band, struct ftl_basic_rq *brq);
188 void ftl_band_get_next_gc(struct spdk_ftl_dev *dev, ftl_band_ops_cb cb, void *cntx);
189 void ftl_band_read_tail_brq_md(struct ftl_band *band, ftl_band_md_cb cb, void *cntx);
190 void ftl_band_initialize_free_state(struct ftl_band *band);
191 
192 static inline void
193 ftl_band_set_owner(struct ftl_band *band,
194 		   ftl_band_state_change_fn fn,
195 		   void *priv)
196 {
197 	assert(NULL == band->owner.priv);
198 	assert(NULL == band->owner.state_change_fn);
199 
200 	band->owner.state_change_fn = fn;
201 	band->owner.priv = priv;
202 }
203 
204 static inline void
205 ftl_band_clear_owner(struct ftl_band *band,
206 		     ftl_band_state_change_fn fn,
207 		     void *priv)
208 {
209 	assert(priv == band->owner.priv);
210 	assert(fn == band->owner.state_change_fn);
211 
212 	band->owner.state_change_fn = NULL;
213 	band->owner.priv = NULL;
214 }
215 
216 static inline int
217 ftl_band_empty(const struct ftl_band *band)
218 {
219 	return band->p2l_map.num_valid == 0;
220 }
221 
222 static inline uint64_t
223 ftl_band_qd(const struct ftl_band *band)
224 {
225 	return band->queue_depth;
226 }
227 
228 static inline bool
229 ftl_band_block_offset_valid(struct ftl_band *band, size_t block_off)
230 {
231 	struct ftl_p2l_map *p2l_map = &band->p2l_map;
232 
233 	return ftl_bitmap_get(p2l_map->valid, block_off);
234 }
235 
236 static inline void
237 ftl_band_iter_init(struct ftl_band *band)
238 {
239 	/* Initialize band iterator to begin state */
240 	band->md->iter.addr = band->start_addr;
241 	band->md->iter.offset = 0;
242 }
243 
244 static inline void
245 ftl_band_iter_advance(struct ftl_band *band, uint64_t num_blocks)
246 {
247 	band->md->iter.offset += num_blocks;
248 	band->md->iter.addr = ftl_band_next_xfer_addr(band, band->md->iter.addr, num_blocks);
249 	assert(band->md->iter.addr != FTL_ADDR_INVALID);
250 }
251 
252 static inline void
253 ftl_band_iter_set(struct ftl_band *band, uint64_t num_blocks)
254 {
255 	band->md->iter.offset = num_blocks;
256 	band->md->iter.addr = ftl_band_next_xfer_addr(band, band->md->iter.addr, num_blocks);
257 	assert(band->md->iter.addr != FTL_ADDR_INVALID);
258 }
259 
260 #endif /* FTL_BAND_H */
261