Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2018 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #ifndef FTL_CORE_H
7 : : #define FTL_CORE_H
8 : :
9 : : #include "spdk/stdinc.h"
10 : : #include "spdk/uuid.h"
11 : : #include "spdk/thread.h"
12 : : #include "spdk/util.h"
13 : : #include "spdk/likely.h"
14 : : #include "spdk/queue.h"
15 : : #include "spdk/ftl.h"
16 : : #include "spdk/bdev.h"
17 : :
18 : : #include "ftl_internal.h"
19 : : #include "ftl_io.h"
20 : : #include "ftl_trace.h"
21 : : #include "ftl_nv_cache.h"
22 : : #include "ftl_writer.h"
23 : : #include "ftl_layout.h"
24 : : #include "ftl_sb.h"
25 : : #include "ftl_l2p.h"
26 : : #include "base/ftl_base_dev.h"
27 : : #include "utils/ftl_bitmap.h"
28 : : #include "utils/ftl_log.h"
29 : : #include "utils/ftl_property.h"
30 : :
31 : : /*
32 : : * We need to reserve at least 2 buffers for band close / open sequence
33 : : * alone, plus additional (8) buffers for handling relocations.
34 : : */
35 : : #define P2L_MEMPOOL_SIZE (2 + 8)
36 : :
37 : : /* When using VSS on nvcache, FTL sometimes doesn't require the contents of metadata.
38 : : * Some devices have bugs when sending a NULL pointer as part of metadata when namespace
39 : : * is formatted with VSS. This buffer is passed to such calls to avoid the bug. */
40 : : #define FTL_ZERO_BUFFER_SIZE 0x100000
41 : : extern void *g_ftl_write_buf;
42 : : extern void *g_ftl_read_buf;
43 : :
44 : : struct ftl_layout_tracker_bdev;
45 : :
46 : : struct spdk_ftl_dev {
47 : : /* Configuration */
48 : : struct spdk_ftl_conf conf;
49 : :
50 : : /* FTL device layout */
51 : : struct ftl_layout layout;
52 : :
53 : : /* FTL superblock */
54 : : struct ftl_superblock *sb;
55 : :
56 : : /* FTL shm superblock */
57 : : struct ftl_superblock_shm *sb_shm;
58 : : struct ftl_md *sb_shm_md;
59 : :
60 : : /* Queue of registered IO channels */
61 : : TAILQ_HEAD(, ftl_io_channel) ioch_queue;
62 : :
63 : : /* Underlying device */
64 : : struct spdk_bdev_desc *base_bdev_desc;
65 : :
66 : : /* Base device type */
67 : : const struct ftl_base_device_type *base_type;
68 : :
69 : : /* Cached properties of the underlying device */
70 : : uint64_t num_blocks_in_band;
71 : : bool is_zoned;
72 : :
73 : : /* Indicates the device is fully initialized */
74 : : bool initialized;
75 : :
76 : : /* Indicates the device is about to be stopped */
77 : : bool halt;
78 : :
79 : : /* Indicates if the device is registered as an IO device */
80 : : bool io_device_registered;
81 : :
82 : : /* Management process to be continued after IO device unregistration completes */
83 : : struct ftl_mngt_process *unregister_process;
84 : :
85 : : /* Non-volatile write buffer cache */
86 : : struct ftl_nv_cache nv_cache;
87 : :
88 : : /* P2L map memory pool */
89 : : struct ftl_mempool *p2l_pool;
90 : :
91 : : /* Underlying SHM buf for P2L map mempool */
92 : : struct ftl_md *p2l_pool_md;
93 : :
94 : : /* Band md memory pool */
95 : : struct ftl_mempool *band_md_pool;
96 : :
97 : : /* Traces */
98 : : struct ftl_trace trace;
99 : :
100 : : /* Statistics */
101 : : struct ftl_stats stats;
102 : :
103 : : /* Array of bands */
104 : : struct ftl_band *bands;
105 : :
106 : : /* Number of operational bands */
107 : : uint64_t num_bands;
108 : :
109 : : /* Next write band */
110 : : struct ftl_band *next_band;
111 : :
112 : : /* Free band list */
113 : : TAILQ_HEAD(, ftl_band) free_bands;
114 : :
115 : : /* Closed bands list */
116 : : TAILQ_HEAD(, ftl_band) shut_bands;
117 : :
118 : : /* Number of free bands */
119 : : uint64_t num_free;
120 : :
121 : : /* Logical -> physical table */
122 : : void *l2p;
123 : :
124 : : /* l2p deferred pins list */
125 : : TAILQ_HEAD(, ftl_l2p_pin_ctx) l2p_deferred_pins;
126 : :
127 : : /* Size of the l2p table */
128 : : uint64_t num_lbas;
129 : :
130 : : /* P2L valid map */
131 : : struct ftl_bitmap *valid_map;
132 : :
133 : : /* Metadata size */
134 : : uint64_t md_size;
135 : :
136 : : /* Transfer unit size */
137 : : uint64_t xfer_size;
138 : :
139 : : /* Current user write limit */
140 : : int limit;
141 : :
142 : : /* Inflight IO operations */
143 : : uint32_t num_inflight;
144 : :
145 : : /* Manages data relocation */
146 : : struct ftl_reloc *reloc;
147 : :
148 : : /* Thread on which the poller is running */
149 : : struct spdk_thread *core_thread;
150 : :
151 : : /* IO channel to the FTL device, used for internal management operations
152 : : * consuming FTL's external API
153 : : */
154 : : struct spdk_io_channel *ioch;
155 : :
156 : : /* Underlying device IO channel */
157 : : struct spdk_io_channel *base_ioch;
158 : :
159 : : /* Poller */
160 : : struct spdk_poller *core_poller;
161 : :
162 : : /* Read submission queue */
163 : : TAILQ_HEAD(, ftl_io) rd_sq;
164 : :
165 : : /* Write submission queue */
166 : : TAILQ_HEAD(, ftl_io) wr_sq;
167 : :
168 : : /* Trim submission queue */
169 : : TAILQ_HEAD(, ftl_io) unmap_sq;
170 : :
171 : : /* Trim valid map */
172 : : struct ftl_bitmap *unmap_map;
173 : : struct ftl_md *unmap_map_md;
174 : : size_t unmap_qd;
175 : : bool unmap_in_progress;
176 : :
177 : : /* Writer for user IOs */
178 : : struct ftl_writer writer_user;
179 : :
180 : : /* Writer for GC IOs */
181 : : struct ftl_writer writer_gc;
182 : :
183 : : uint32_t num_logical_bands_in_physical;
184 : :
185 : : /* Retry init sequence */
186 : : bool init_retry;
187 : :
188 : : /* P2L checkpointing */
189 : : struct {
190 : : /* Free regions */
191 : : TAILQ_HEAD(, ftl_p2l_ckpt) free;
192 : : /* In use regions */
193 : : TAILQ_HEAD(, ftl_p2l_ckpt) inuse;
194 : : } p2l_ckpt;
195 : :
196 : : /* MD layout region tracker for nvc device */
197 : : struct ftl_layout_tracker_bdev *nvc_layout_tracker;
198 : :
199 : : /* MD layout region tracker for a base devics */
200 : : struct ftl_layout_tracker_bdev *base_layout_tracker;
201 : :
202 : : /* FTL properties which can be configured by user */
203 : : struct ftl_properties *properties;
204 : : };
205 : :
206 : : void ftl_apply_limits(struct spdk_ftl_dev *dev);
207 : :
208 : : void ftl_invalidate_addr(struct spdk_ftl_dev *dev, ftl_addr addr);
209 : :
210 : : int ftl_core_poller(void *ctx);
211 : :
212 : : int ftl_io_channel_poll(void *arg);
213 : :
214 : : struct ftl_io_channel *ftl_io_channel_get_ctx(struct spdk_io_channel *ioch);
215 : :
216 : : bool ftl_needs_reloc(struct spdk_ftl_dev *dev);
217 : :
218 : : struct ftl_band *ftl_band_get_next_free(struct spdk_ftl_dev *dev);
219 : :
220 : : void ftl_set_unmap_map(struct spdk_ftl_dev *dev, uint64_t lba, uint64_t num_blocks,
221 : : uint64_t seq_id);
222 : :
223 : : void ftl_recover_max_seq(struct spdk_ftl_dev *dev);
224 : :
225 : : void ftl_stats_bdev_io_completed(struct spdk_ftl_dev *dev, enum ftl_stats_type type,
226 : : struct spdk_bdev_io *bdev_io);
227 : :
228 : : void ftl_stats_crc_error(struct spdk_ftl_dev *dev, enum ftl_stats_type type);
229 : :
230 : : int ftl_unmap(struct spdk_ftl_dev *dev, struct ftl_io *io, struct spdk_io_channel *ch,
231 : : uint64_t lba, size_t lba_cnt, spdk_ftl_fn cb_fn, void *cb_arg);
232 : :
233 : : static inline uint64_t
234 : 4371343 : ftl_get_num_blocks_in_band(const struct spdk_ftl_dev *dev)
235 : : {
236 [ + - + - ]: 4371343 : return dev->num_blocks_in_band;
237 : : }
238 : :
239 : : static inline uint32_t
240 : 22 : ftl_get_write_unit_size(struct spdk_bdev *bdev)
241 : : {
242 : : /* Full block of P2L map worth of xfer_sz is needed for P2L checkpointing */
243 : 22 : return FTL_NUM_LBA_IN_BLOCK;
244 : : }
245 : :
246 : : static inline struct spdk_thread *
247 : 42 : ftl_get_core_thread(const struct spdk_ftl_dev *dev)
248 : : {
249 [ # # # # ]: 42 : return dev->core_thread;
250 : : }
251 : :
252 : : static inline void
253 : 3099583 : ftl_add_io_activity(struct spdk_ftl_dev *dev)
254 : : {
255 [ # # # # ]: 3099583 : dev->stats.io_activity_total++;
256 : 3099583 : }
257 : :
258 : : static inline uint64_t
259 : 949581 : ftl_get_num_bands(const struct spdk_ftl_dev *dev)
260 : : {
261 [ + - + - ]: 949581 : return dev->num_bands;
262 : : }
263 : :
264 : : static inline bool
265 : 2705974 : ftl_check_core_thread(const struct spdk_ftl_dev *dev)
266 : : {
267 [ # # # # ]: 2705974 : return dev->core_thread == spdk_get_thread();
268 : : }
269 : :
270 : : static inline int
271 : 16268688 : ftl_addr_packed(const struct spdk_ftl_dev *dev)
272 : : {
273 [ + - + - : 16268688 : return dev->layout.l2p.addr_size < sizeof(ftl_addr);
+ - + - ]
274 : : }
275 : :
276 : : static inline int
277 : 18568376 : ftl_addr_in_nvc(const struct spdk_ftl_dev *dev, ftl_addr addr)
278 : : {
279 [ + + # # ]: 18568376 : assert(addr != FTL_ADDR_INVALID);
280 [ + - + - : 18568376 : return addr >= dev->layout.base.total_blocks;
+ - + - ]
281 : : }
282 : :
283 : : static inline uint64_t
284 : 7965331 : ftl_addr_to_nvc_offset(const struct spdk_ftl_dev *dev, ftl_addr addr)
285 : : {
286 [ + + # # ]: 7965331 : assert(ftl_addr_in_nvc(dev, addr));
287 [ + - + - : 7965331 : return addr - dev->layout.base.total_blocks;
+ - + - ]
288 : : }
289 : :
290 : : static inline ftl_addr
291 : 2045636 : ftl_addr_from_nvc_offset(const struct spdk_ftl_dev *dev, uint64_t cache_offset)
292 : : {
293 [ + - + - : 2045636 : return cache_offset + dev->layout.base.total_blocks;
+ - + - ]
294 : : }
295 : :
296 : : static inline uint64_t
297 : 74 : ftl_get_next_seq_id(struct spdk_ftl_dev *dev)
298 : : {
299 [ # # # # : 74 : return ++dev->sb->seq_id;
# # ]
300 : : }
301 : :
302 : : static inline size_t
303 : 10882 : ftl_p2l_map_num_blocks(const struct spdk_ftl_dev *dev)
304 : : {
305 : 10882 : return spdk_divide_round_up(ftl_get_num_blocks_in_band(dev) *
306 : : sizeof(struct ftl_p2l_map_entry), FTL_BLOCK_SIZE);
307 : : }
308 : :
309 : : static inline size_t
310 : 10837 : ftl_tail_md_num_blocks(const struct spdk_ftl_dev *dev)
311 : : {
312 : 10837 : return spdk_divide_round_up(
313 : 0 : ftl_p2l_map_num_blocks(dev),
314 [ # # # # : 21674 : dev->xfer_size) * dev->xfer_size;
# # # # #
# ]
315 : : }
316 : :
317 : : /*
318 : : * shm_ready being set is a necessary part of the validity of the shm superblock
319 : : * If it's not set, then the recovery or startup must proceed from disk
320 : : *
321 : : * - If both sb and shm_sb are clean, then shm memory can be relied on for startup
322 : : * - If shm_sb wasn't set to clean, then disk startup/recovery needs to be done (which depends on the sb->clean flag)
323 : : * - sb->clean clear and sb_shm->clean is technically not possible (due to the order of these operations), but it should
324 : : * probably do a full recovery from disk to be on the safe side (which the ftl_fast_recovery will guarantee)
325 : : */
326 : :
327 : : static inline bool
328 : 2416 : ftl_fast_startup(const struct spdk_ftl_dev *dev)
329 : : {
330 [ + + - + : 2416 : return dev->sb->clean && dev->sb_shm->shm_clean && dev->sb_shm->shm_ready;
- + - - -
- # # # #
# # # # #
# # # # #
# # # # #
# # # ]
331 : : }
332 : :
333 : : static inline bool
334 : 198 : ftl_fast_recovery(const struct spdk_ftl_dev *dev)
335 : : {
336 [ + + - + : 198 : return !dev->sb->clean && !dev->sb_shm->shm_clean && dev->sb_shm->shm_ready;
+ - - + +
+ # # # #
# # # # #
# # # # #
# # # # #
# # # ]
337 : : }
338 : :
339 : : #endif /* FTL_CORE_H */
|