xref: /spdk/lib/ftl/mngt/ftl_mngt_md.c (revision c4acef02aa135112a727d8c233c770b1c99cd954)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (c) Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/thread.h"
7 #include "spdk/crc32.h"
8 
9 #include "ftl_core.h"
10 #include "ftl_mngt.h"
11 #include "ftl_mngt_steps.h"
12 #include "ftl_utils.h"
13 #include "ftl_internal.h"
14 #include "ftl_sb.h"
15 
16 void
17 ftl_mngt_init_layout(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
18 {
19 	if (ftl_layout_setup(dev)) {
20 		ftl_mngt_fail_step(mngt);
21 	} else {
22 		ftl_mngt_next_step(mngt);
23 	}
24 }
25 
26 static bool
27 is_buffer_needed(enum ftl_layout_region_type type)
28 {
29 	switch (type) {
30 #ifdef SPDK_FTL_VSS_EMU
31 	case FTL_LAYOUT_REGION_TYPE_VSS:
32 #endif
33 
34 	case FTL_LAYOUT_REGION_TYPE_SB:
35 	case FTL_LAYOUT_REGION_TYPE_SB_BASE:
36 	case FTL_LAYOUT_REGION_TYPE_DATA_NVC:
37 	case FTL_LAYOUT_REGION_TYPE_DATA_BASE:
38 	case FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR:
39 		return false;
40 
41 	default:
42 		return true;
43 	}
44 }
45 
46 void
47 ftl_mngt_init_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
48 {
49 	struct ftl_layout *layout = &dev->layout;
50 	struct ftl_layout_region *region = layout->region;
51 	uint64_t i;
52 
53 	for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++, region++) {
54 		if (layout->md[i]) {
55 			/*
56 			 * Some metadata objects are initialized by other FTL
57 			 * components. At the moment it's only used by superblock (and its mirror) -
58 			 * during load time we need to read it earlier in order to get the layout for the
59 			 * other regions.
60 			 */
61 			continue;
62 		}
63 		layout->md[i] = ftl_md_create(dev, region->current.blocks, region->vss_blksz, region->name,
64 					      !is_buffer_needed(i), region);
65 		if (NULL == layout->md[i]) {
66 			ftl_mngt_fail_step(mngt);
67 			return;
68 		}
69 	}
70 
71 	ftl_mngt_next_step(mngt);
72 }
73 
74 void
75 ftl_mngt_deinit_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
76 {
77 	struct ftl_layout *layout = &dev->layout;
78 	struct ftl_layout_region *region = layout->region;
79 	uint64_t i;
80 
81 	for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++, region++) {
82 		if (layout->md[i]) {
83 			ftl_md_destroy(layout->md[i]);
84 			layout->md[i] = NULL;
85 		}
86 	}
87 
88 	ftl_mngt_next_step(mngt);
89 }
90 
91 static void
92 persist_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status)
93 {
94 	struct ftl_mngt_process *mngt = md->owner.cb_ctx;
95 
96 	if (status) {
97 		ftl_mngt_fail_step(mngt);
98 	} else {
99 		ftl_mngt_next_step(mngt);
100 	}
101 }
102 
103 static void
104 persist(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt,
105 	enum ftl_layout_region_type type)
106 {
107 	struct ftl_layout *layout = &dev->layout;
108 	struct ftl_md *md;
109 
110 	assert(type < FTL_LAYOUT_REGION_TYPE_MAX);
111 
112 	md = layout->md[type];
113 	if (!md) {
114 		ftl_mngt_fail_step(mngt);
115 		return;
116 	}
117 
118 	md->owner.cb_ctx = mngt;
119 	md->cb = persist_cb;
120 	ftl_md_persist(md);
121 }
122 
123 static uint32_t
124 get_sb_crc(struct ftl_superblock *sb)
125 {
126 	uint32_t crc = 0;
127 
128 	/* Calculate CRC excluding CRC field in superblock */
129 	void *buffer = sb;
130 	size_t offset = offsetof(struct ftl_superblock, header.crc);
131 	size_t size = offset;
132 	crc = spdk_crc32c_update(buffer, size, crc);
133 
134 	buffer += offset + sizeof(sb->header.crc);
135 	size = FTL_SUPERBLOCK_SIZE - offset - sizeof(sb->header.crc);
136 	crc = spdk_crc32c_update(buffer, size, crc);
137 
138 	return crc;
139 }
140 
141 void
142 ftl_mngt_init_default_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
143 {
144 	struct ftl_superblock *sb = dev->sb;
145 
146 	sb->header.magic = FTL_SUPERBLOCK_MAGIC;
147 	sb->header.version = FTL_METADATA_VERSION_CURRENT;
148 	sb->uuid = dev->conf.uuid;
149 	sb->clean = 0;
150 
151 	/* Max 16 IO depth per band relocate */
152 	sb->max_reloc_qdepth = 16;
153 
154 	sb->overprovisioning = dev->conf.overprovisioning;
155 
156 	/* md layout isn't initialized yet.
157 	 * empty region list => all regions in the default location */
158 	sb->md_layout_head.type = FTL_LAYOUT_REGION_TYPE_INVALID;
159 
160 	sb->header.crc = get_sb_crc(sb);
161 
162 	ftl_mngt_next_step(mngt);
163 }
164 
165 void
166 ftl_mngt_set_dirty(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
167 {
168 	struct ftl_superblock *sb = dev->sb;
169 
170 	sb->clean = 0;
171 	sb->header.crc = get_sb_crc(sb);
172 	persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB);
173 }
174 
175 /*
176  * Initializes the superblock fields during first startup of FTL
177  */
178 static const struct ftl_mngt_process_desc desc_init_sb = {
179 	.name = "SB initialize",
180 	.steps = {
181 		{
182 			.name = "Default-initialize superblock",
183 			.action = ftl_mngt_init_default_sb,
184 		},
185 		{}
186 	}
187 };
188 
189 #ifdef SPDK_FTL_VSS_EMU
190 void
191 ftl_mngt_md_init_vss_emu(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
192 {
193 	struct ftl_layout *layout = &dev->layout;
194 	struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_VSS];
195 
196 	/* Initialize VSS layout */
197 	ftl_layout_setup_vss_emu(dev);
198 
199 	/* Allocate md buf */
200 	layout->md[FTL_LAYOUT_REGION_TYPE_VSS] = ftl_md_create(dev, region->current.blocks,
201 			region->vss_blksz, NULL, 0, region);
202 	if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_VSS]) {
203 		ftl_mngt_fail_step(mngt);
204 		return;
205 	}
206 	ftl_mngt_next_step(mngt);
207 }
208 
209 void
210 ftl_mngt_md_deinit_vss_emu(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
211 {
212 	struct ftl_layout *layout = &dev->layout;
213 
214 	if (layout->md[FTL_LAYOUT_REGION_TYPE_VSS]) {
215 		ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_VSS]);
216 		layout->md[FTL_LAYOUT_REGION_TYPE_VSS] = NULL;
217 	}
218 
219 	ftl_mngt_next_step(mngt);
220 }
221 #endif
222 
223 void
224 ftl_mngt_superblock_init(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
225 {
226 	struct ftl_layout *layout = &dev->layout;
227 	struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB];
228 	char uuid[SPDK_UUID_STRING_LEN];
229 
230 	/* Must generate UUID before MD create on SHM for the SB */
231 	if (dev->conf.mode & SPDK_FTL_MODE_CREATE) {
232 		spdk_uuid_generate(&dev->conf.uuid);
233 		spdk_uuid_fmt_lower(uuid, sizeof(uuid), &dev->conf.uuid);
234 		FTL_NOTICELOG(dev, "Create new FTL, UUID %s\n", uuid);
235 	}
236 
237 	/* Setup the layout of a superblock */
238 	if (ftl_layout_setup_superblock(dev)) {
239 		ftl_mngt_fail_step(mngt);
240 		return;
241 	}
242 
243 	/* Allocate md buf */
244 	layout->md[FTL_LAYOUT_REGION_TYPE_SB] = ftl_md_create(dev, region->current.blocks,
245 						region->vss_blksz, region->name, false, region);
246 	if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB]) {
247 		ftl_mngt_fail_step(mngt);
248 		return;
249 	}
250 
251 	/* Link the md buf to the device */
252 	dev->sb = ftl_md_get_buffer(layout->md[FTL_LAYOUT_REGION_TYPE_SB]);
253 
254 	/* Setup superblock mirror to QLC */
255 	region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB_BASE];
256 	layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = ftl_md_create(dev, region->current.blocks,
257 			region->vss_blksz, NULL, false, region);
258 	if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) {
259 		ftl_mngt_fail_step(mngt);
260 		return;
261 	}
262 
263 	/* Initialize the superblock */
264 	if (dev->conf.mode & SPDK_FTL_MODE_CREATE) {
265 		ftl_mngt_call_process(mngt, &desc_init_sb);
266 	} else {
267 		ftl_mngt_fail_step(mngt);
268 	}
269 }
270 
271 void
272 ftl_mngt_superblock_deinit(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
273 {
274 	struct ftl_layout *layout = &dev->layout;
275 
276 	if (layout->md[FTL_LAYOUT_REGION_TYPE_SB]) {
277 		ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB]);
278 		layout->md[FTL_LAYOUT_REGION_TYPE_SB] = NULL;
279 	}
280 
281 	if (layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) {
282 		ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]);
283 		layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = NULL;
284 	}
285 
286 	ftl_mngt_next_step(mngt);
287 }
288