xref: /spdk/lib/ftl/ftl_internal.h (revision 784b9d48746955f210926648a0131f84f58de76f)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2022 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #ifndef FTL_INTERNAL_H
7 #define FTL_INTERNAL_H
8 
9 #include "spdk/stdinc.h"
10 #include "spdk/crc32.h"
11 #include "spdk/util.h"
12 #include "spdk/uuid.h"
13 
14 #include "utils/ftl_bitmap.h"
15 
16 /* Marks address as invalid */
17 #define FTL_ADDR_INVALID	((ftl_addr)-1)
18 /* Marks LBA as invalid */
19 #define FTL_LBA_INVALID		((uint64_t)-1)
20 /* Smallest data unit size */
21 #define FTL_BLOCK_SIZE		4096ULL
22 
23 #define FTL_P2L_VERSION_0	0
24 #define FTL_P2L_VERSION_1	1
25 
26 #define FTL_P2L_VERSION_CURRENT FTL_P2L_VERSION_1
27 
28 /*
29  * This type represents address in the ftl address space. Values from 0 to based bdev size are
30  * mapped directly to base device lbas. Values above that represent nv cache lbas.
31  */
32 typedef uint64_t ftl_addr;
33 
34 struct spdk_ftl_dev;
35 
36 enum ftl_md_type {
37 	FTL_MD_TYPE_BAND,
38 	FTL_MD_TYPE_CHUNK
39 };
40 
41 enum ftl_band_type {
42 	FTL_BAND_TYPE_GC = 1,
43 	FTL_BAND_TYPE_COMPACTION
44 };
45 
46 enum ftl_md_status {
47 	FTL_MD_SUCCESS,
48 	/* Metadata read failure */
49 	FTL_MD_IO_FAILURE,
50 	/* Invalid version */
51 	FTL_MD_INVALID_VER,
52 	/* UUID doesn't match */
53 	FTL_MD_NO_MD,
54 	/* UUID and version matches but CRC doesn't */
55 	FTL_MD_INVALID_CRC,
56 	/* Vld or p2l map size doesn't match */
57 	FTL_MD_INVALID_SIZE
58 };
59 
60 struct ftl_p2l_map_entry {
61 	uint64_t lba;
62 	uint64_t seq_id;
63 };
64 
65 /* Number of LBAs that could be stored in a single block */
66 #define FTL_NUM_LBA_IN_BLOCK	(FTL_BLOCK_SIZE / sizeof(struct ftl_p2l_map_entry))
67 
68 /*
69  * Mapping of physical (actual location on disk) to logical (user's POV) addresses. Used in two main scenarios:
70  * - during relocation FTL needs to pin L2P pages (this allows to check which pages to pin) and move still valid blocks
71  * (valid map allows for preliminary elimination of invalid physical blocks, but user data could invalidate a location
72  * during read/write operation, so actual comparison against L2P needs to be done)
73  * - After dirty shutdown the state of the L2P is unknown and needs to be rebuilt - it is done by applying all P2L, taking
74  * into account ordering of user writes
75  */
76 struct ftl_p2l_map {
77 	/* Number of valid LBAs */
78 	size_t					num_valid;
79 
80 	/* P2L map's reference count, prevents premature release of resources during dirty shutdown recovery for open bands */
81 	size_t					ref_cnt;
82 
83 	/* Bitmap of valid LBAs */
84 	struct ftl_bitmap			*valid;
85 
86 	/* P2L map (only valid for open/relocating bands) */
87 	union {
88 		struct ftl_p2l_map_entry	*band_map;
89 		void				*chunk_map;
90 	};
91 
92 	/* DMA buffer for region's metadata entry */
93 	union {
94 		struct ftl_band_md		*band_dma_md;
95 
96 		struct ftl_nv_cache_chunk_md	*chunk_dma_md;
97 	};
98 
99 	/* P2L checkpointing region */
100 	struct ftl_p2l_ckpt			*p2l_ckpt;
101 };
102 
103 struct ftl_p2l_sync_ctx {
104 	struct ftl_band *band;
105 	uint64_t	page_start;
106 	uint64_t	page_end;
107 	int		md_region;
108 };
109 
110 struct ftl_p2l_ckpt_page {
111 	struct ftl_p2l_map_entry map[FTL_NUM_LBA_IN_BLOCK];
112 };
113 
114 struct ftl_p2l_ckpt;
115 struct ftl_band;
116 struct spdk_ftl_dev;
117 struct ftl_mngt_process;
118 struct ftl_rq;
119 
120 int ftl_p2l_ckpt_init(struct spdk_ftl_dev *dev);
121 
122 void ftl_p2l_ckpt_deinit(struct spdk_ftl_dev *dev);
123 
124 void ftl_p2l_ckpt_issue(struct ftl_rq *rq);
125 
126 struct ftl_p2l_ckpt *ftl_p2l_ckpt_acquire(struct spdk_ftl_dev *dev);
127 
128 struct ftl_p2l_ckpt *ftl_p2l_ckpt_acquire_region_type(struct spdk_ftl_dev *dev,
129 		uint32_t region_type);
130 
131 void ftl_p2l_ckpt_release(struct spdk_ftl_dev *dev, struct ftl_p2l_ckpt *ckpt);
132 
133 enum ftl_layout_region_type ftl_p2l_ckpt_region_type(const struct ftl_p2l_ckpt *ckpt);
134 
135 #if defined(DEBUG)
136 void ftl_p2l_validate_ckpt(struct ftl_band *band);
137 #else
138 static inline void
139 ftl_p2l_validate_ckpt(struct ftl_band *band)
140 {
141 }
142 #endif
143 
144 int ftl_mngt_p2l_ckpt_get_seq_id(struct spdk_ftl_dev *dev, int md_region);
145 
146 int ftl_mngt_p2l_ckpt_restore(struct ftl_band *band, uint32_t md_region, uint64_t seq_id);
147 
148 int ftl_mngt_p2l_ckpt_restore_clean(struct ftl_band *band);
149 
150 void ftl_mngt_p2l_ckpt_restore_shm_clean(struct ftl_band *band);
151 
152 void ftl_mngt_persist_bands_p2l(struct ftl_mngt_process *mngt);
153 
154 struct ftl_reloc *ftl_reloc_init(struct spdk_ftl_dev *dev);
155 
156 void ftl_reloc_free(struct ftl_reloc *reloc);
157 
158 void ftl_reloc(struct ftl_reloc *reloc);
159 
160 void ftl_reloc_halt(struct ftl_reloc *reloc);
161 
162 void ftl_reloc_resume(struct ftl_reloc *reloc);
163 
164 bool ftl_reloc_is_halted(const struct ftl_reloc *reloc);
165 
166 #endif /* FTL_INTERNAL_H */
167