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