Line data Source code
1 : /* SPDX-License-Identifier: BSD-3-Clause
2 : * Copyright 2023 Solidigm All Rights Reserved
3 : * Copyright (C) 2022 Intel Corporation.
4 : * All rights reserved.
5 : */
6 :
7 : #include "spdk/thread.h"
8 : #include "spdk/crc32.h"
9 : #include "spdk/string.h"
10 :
11 : #include "ftl_core.h"
12 : #include "ftl_mngt.h"
13 : #include "ftl_mngt_steps.h"
14 : #include "ftl_utils.h"
15 : #include "ftl_band.h"
16 : #include "ftl_internal.h"
17 : #include "ftl_sb.h"
18 : #include "base/ftl_base_dev.h"
19 : #include "nvc/ftl_nvc_dev.h"
20 : #include "upgrade/ftl_layout_upgrade.h"
21 : #include "upgrade/ftl_sb_upgrade.h"
22 :
23 : void
24 0 : ftl_mngt_init_layout(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
25 : {
26 0 : if (ftl_layout_setup(dev)) {
27 0 : ftl_mngt_fail_step(mngt);
28 : } else {
29 0 : ftl_mngt_next_step(mngt);
30 : }
31 0 : }
32 :
33 : static bool
34 0 : is_buffer_needed(enum ftl_layout_region_type type)
35 : {
36 0 : switch (type) {
37 0 : case FTL_LAYOUT_REGION_TYPE_SB:
38 : case FTL_LAYOUT_REGION_TYPE_SB_BASE:
39 : case FTL_LAYOUT_REGION_TYPE_DATA_NVC:
40 : case FTL_LAYOUT_REGION_TYPE_DATA_BASE:
41 : case FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR:
42 : case FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR:
43 : #ifndef SPDK_FTL_L2P_FLAT
44 : case FTL_LAYOUT_REGION_TYPE_L2P:
45 : #endif
46 : case FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR:
47 : case FTL_LAYOUT_REGION_TYPE_TRIM_LOG_MIRROR:
48 0 : return false;
49 :
50 0 : default:
51 0 : return true;
52 : }
53 : }
54 :
55 : void
56 0 : ftl_mngt_init_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
57 : {
58 0 : struct ftl_layout *layout = &dev->layout;
59 : struct ftl_layout_region *region;
60 : struct ftl_md *md, *md_mirror;
61 : enum ftl_layout_region_type i;
62 : int md_flags;
63 :
64 0 : for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++) {
65 0 : region = ftl_layout_region_get(dev, i);
66 0 : if (!region) {
67 0 : continue;
68 : }
69 0 : assert(i == region->type);
70 0 : if (layout->md[i]) {
71 : /*
72 : * Some metadata objects are initialized by other FTL
73 : * components. At the moment it's only used by superblock (and its mirror) -
74 : * during load time we need to read it earlier in order to get the layout for the
75 : * other regions.
76 : */
77 0 : continue;
78 : }
79 0 : md_flags = is_buffer_needed(i) ? ftl_md_create_region_flags(dev,
80 0 : region->type) : FTL_MD_CREATE_NO_MEM;
81 0 : layout->md[i] = ftl_md_create(dev, region->current.blocks, region->vss_blksz, region->name,
82 : md_flags, region);
83 0 : if (NULL == layout->md[i]) {
84 0 : ftl_mngt_fail_step(mngt);
85 0 : return;
86 : }
87 : }
88 :
89 : /* Initialize mirror regions */
90 0 : for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++) {
91 0 : region = ftl_layout_region_get(dev, i);
92 0 : if (!region) {
93 0 : continue;
94 : }
95 0 : assert(i == region->type);
96 0 : if (region->mirror_type != FTL_LAYOUT_REGION_TYPE_INVALID &&
97 0 : !is_buffer_needed(region->mirror_type)) {
98 0 : md = layout->md[i];
99 0 : md_mirror = layout->md[region->mirror_type];
100 :
101 0 : md_mirror->dev = md->dev;
102 0 : md_mirror->data_blocks = md->data_blocks;
103 0 : md_mirror->data = md->data;
104 0 : if (md_mirror->region->vss_blksz == md->region->vss_blksz) {
105 0 : md_mirror->vss_data = md->vss_data;
106 : }
107 0 : md_mirror->region = ftl_layout_region_get(dev, region->mirror_type);
108 0 : ftl_bug(md_mirror->region == NULL);
109 0 : md_mirror->is_mirror = true;
110 : }
111 : }
112 :
113 0 : ftl_mngt_next_step(mngt);
114 : }
115 :
116 : void
117 0 : ftl_mngt_deinit_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
118 : {
119 0 : struct ftl_layout *layout = &dev->layout;
120 : struct ftl_layout_region *region;
121 : enum ftl_layout_region_type i;
122 :
123 0 : for (i = 0; i < FTL_LAYOUT_REGION_TYPE_MAX; i++) {
124 0 : region = ftl_layout_region_get(dev, i);
125 0 : if (!region) {
126 0 : continue;
127 : }
128 0 : if (layout->md[i]) {
129 0 : ftl_md_destroy(layout->md[i], ftl_md_destroy_region_flags(dev, region->type));
130 0 : layout->md[i] = NULL;
131 : }
132 : }
133 :
134 0 : ftl_mngt_next_step(mngt);
135 0 : }
136 :
137 : static void
138 0 : persist_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status)
139 : {
140 0 : struct ftl_mngt_process *mngt = md->owner.cb_ctx;
141 :
142 0 : if (status) {
143 0 : ftl_mngt_fail_step(mngt);
144 : } else {
145 0 : ftl_mngt_next_step(mngt);
146 : }
147 0 : }
148 :
149 : static void
150 0 : persist(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt,
151 : enum ftl_layout_region_type type)
152 : {
153 0 : struct ftl_layout *layout = &dev->layout;
154 : struct ftl_md *md;
155 :
156 0 : assert(type < FTL_LAYOUT_REGION_TYPE_MAX);
157 :
158 0 : md = layout->md[type];
159 0 : if (!md) {
160 0 : ftl_mngt_fail_step(mngt);
161 0 : return;
162 : }
163 :
164 0 : md->owner.cb_ctx = mngt;
165 0 : md->cb = persist_cb;
166 0 : ftl_md_persist(md);
167 : }
168 :
169 : static int
170 0 : ftl_md_restore_region(struct spdk_ftl_dev *dev, int region_type)
171 : {
172 0 : int status = 0;
173 0 : switch (region_type) {
174 0 : case FTL_LAYOUT_REGION_TYPE_NVC_MD:
175 0 : status = ftl_nv_cache_load_state(&dev->nv_cache);
176 0 : break;
177 0 : case FTL_LAYOUT_REGION_TYPE_VALID_MAP:
178 0 : ftl_valid_map_load_state(dev);
179 0 : break;
180 0 : case FTL_LAYOUT_REGION_TYPE_BAND_MD:
181 0 : status = ftl_bands_load_state(dev);
182 0 : break;
183 0 : default:
184 0 : break;
185 : }
186 0 : return status;
187 : }
188 :
189 : static void
190 0 : restore_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status)
191 : {
192 0 : struct ftl_mngt_process *mngt = md->owner.cb_ctx;
193 0 : const struct ftl_layout_region *region = ftl_md_get_region(md);
194 :
195 0 : if (status) {
196 : /* Restore error, end step */
197 0 : ftl_mngt_fail_step(mngt);
198 0 : return;
199 : }
200 :
201 0 : assert(region);
202 0 : status = ftl_md_restore_region(dev, region->type);
203 :
204 0 : if (status) {
205 0 : ftl_mngt_fail_step(mngt);
206 : } else {
207 0 : ftl_mngt_next_step(mngt);
208 : }
209 : }
210 :
211 : static void
212 0 : restore(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt, enum ftl_layout_region_type type)
213 : {
214 0 : struct ftl_layout *layout = &dev->layout;
215 0 : assert(type < FTL_LAYOUT_REGION_TYPE_MAX);
216 0 : struct ftl_md *md = layout->md[type];
217 :
218 0 : if (!md) {
219 0 : ftl_mngt_fail_step(mngt);
220 0 : return;
221 : }
222 :
223 0 : md->owner.cb_ctx = mngt;
224 0 : md->cb = restore_cb;
225 0 : ftl_md_restore(md);
226 : }
227 :
228 : void
229 0 : ftl_mngt_persist_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
230 : {
231 0 : if (ftl_nv_cache_save_state(&dev->nv_cache)) {
232 0 : ftl_mngt_fail_step(mngt);
233 0 : return;
234 : }
235 :
236 0 : persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_NVC_MD);
237 : }
238 :
239 : static void
240 0 : ftl_mngt_fast_persist_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
241 : {
242 0 : if (ftl_nv_cache_save_state(&dev->nv_cache)) {
243 0 : ftl_mngt_fail_step(mngt);
244 0 : return;
245 : }
246 0 : ftl_mngt_next_step(mngt);
247 : }
248 :
249 : static void
250 0 : ftl_mngt_persist_vld_map_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
251 : {
252 0 : persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_VALID_MAP);
253 0 : }
254 :
255 : static void
256 0 : ftl_mngt_persist_p2l_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
257 : {
258 : /* Sync runtime P2L to persist any invalidation that may have happened */
259 :
260 0 : struct ftl_p2l_sync_ctx *ctx = ftl_mngt_get_step_ctx(mngt);
261 :
262 : /*
263 : * ftl_mngt_persist_bands_p2l will increment the md_region before the step_continue for next regions
264 : */
265 0 : if (ctx->md_region <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN) {
266 0 : ctx->md_region = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN;
267 : }
268 0 : ftl_mngt_persist_bands_p2l(mngt);
269 0 : }
270 :
271 : void
272 0 : ftl_mngt_persist_band_info_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
273 : {
274 0 : persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_BAND_MD);
275 0 : }
276 :
277 : static void
278 0 : ftl_mngt_persist_trim_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
279 : {
280 0 : persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_TRIM_MD);
281 0 : }
282 :
283 : static uint32_t
284 16 : get_sb_crc(struct ftl_superblock *sb)
285 : {
286 16 : uint32_t crc = 0;
287 :
288 : /* Calculate CRC excluding CRC field in superblock */
289 16 : void *buffer = sb;
290 16 : size_t offset = offsetof(struct ftl_superblock, header.crc);
291 16 : size_t size = offset;
292 16 : crc = spdk_crc32c_update(buffer, size, crc);
293 :
294 16 : buffer += offset + sizeof(sb->header.crc);
295 16 : if (sb->header.version > FTL_SB_VERSION_2) {
296 : /* whole buf for v3 and on: */
297 12 : size = FTL_SUPERBLOCK_SIZE - offset - sizeof(sb->header.crc);
298 12 : crc = spdk_crc32c_update(buffer, size, crc);
299 : } else {
300 : /* special for sb v2 only: */
301 4 : size = sizeof(struct ftl_superblock_v2) - offset - sizeof(sb->header.crc);
302 4 : sb->header.crc = spdk_crc32c_update(buffer, size, crc);
303 : }
304 :
305 16 : return crc;
306 : }
307 :
308 : static void
309 0 : ftl_mngt_persist_super_block(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
310 : {
311 0 : dev->sb->overprovisioning = dev->conf.overprovisioning;
312 0 : dev->sb->gc_info = dev->sb_shm->gc_info;
313 0 : dev->sb->header.crc = get_sb_crc(dev->sb);
314 0 : persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB);
315 0 : }
316 :
317 : /*
318 : * Persists all necessary metadata (band state, P2L, etc) during FTL's clean shutdown.
319 : */
320 : static const struct ftl_mngt_process_desc desc_persist = {
321 : .name = "Persist metadata",
322 : .steps = {
323 : {
324 : .name = "Persist NV cache metadata",
325 : .action = ftl_mngt_persist_nv_cache_metadata,
326 : },
327 : {
328 : .name = "Persist valid map metadata",
329 : .action = ftl_mngt_persist_vld_map_metadata,
330 : },
331 : {
332 : .name = "Persist P2L metadata",
333 : .action = ftl_mngt_persist_p2l_metadata,
334 : .ctx_size = sizeof(struct ftl_p2l_sync_ctx),
335 : },
336 : {
337 : .name = "persist band info metadata",
338 : .action = ftl_mngt_persist_band_info_metadata,
339 : },
340 : {
341 : .name = "persist trim metadata",
342 : .action = ftl_mngt_persist_trim_metadata,
343 : },
344 : {
345 : .name = "Persist superblock",
346 : .action = ftl_mngt_persist_super_block,
347 : },
348 : {}
349 : }
350 : };
351 :
352 : void
353 0 : ftl_mngt_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
354 : {
355 0 : ftl_mngt_call_process(mngt, &desc_persist, NULL);
356 0 : }
357 :
358 : /*
359 : * Fast clean shutdown path - skips the persistence of most metadata regions and
360 : * relies on their shared memory state instead.
361 : */
362 : static const struct ftl_mngt_process_desc desc_fast_persist = {
363 : .name = "Fast persist metadata",
364 : .steps = {
365 : {
366 : .name = "Fast persist NV cache metadata",
367 : .action = ftl_mngt_fast_persist_nv_cache_metadata,
368 : },
369 : {}
370 : }
371 : };
372 :
373 : void
374 0 : ftl_mngt_fast_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
375 : {
376 0 : ftl_mngt_call_process(mngt, &desc_fast_persist, NULL);
377 0 : }
378 :
379 : void
380 5 : ftl_mngt_init_default_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
381 : {
382 5 : struct ftl_superblock *sb = dev->sb;
383 :
384 5 : sb->header.magic = FTL_SUPERBLOCK_MAGIC;
385 5 : sb->header.version = FTL_SB_VERSION_CURRENT;
386 5 : sb->uuid = dev->conf.uuid;
387 5 : sb->clean = 0;
388 5 : dev->sb_shm->shm_clean = false;
389 5 : sb->ckpt_seq_id = 0;
390 :
391 : /* Max 16 IO depth per band relocate */
392 5 : sb->max_reloc_qdepth = 16;
393 :
394 5 : sb->overprovisioning = dev->conf.overprovisioning;
395 :
396 5 : ftl_band_init_gc_iter(dev);
397 :
398 : /* md layout isn't initialized yet.
399 : * empty region list => all regions in the default location */
400 5 : spdk_strcpy_pad(sb->base_dev_name, dev->base_type->name,
401 : SPDK_COUNTOF(sb->base_dev_name), '\0');
402 5 : sb->md_layout_base.df_id = FTL_DF_OBJ_ID_INVALID;
403 :
404 5 : spdk_strcpy_pad(sb->nvc_dev_name, dev->nv_cache.nvc_type->name,
405 : SPDK_COUNTOF(sb->nvc_dev_name), '\0');
406 5 : sb->md_layout_nvc.df_id = FTL_DF_OBJ_ID_INVALID;
407 :
408 5 : sb->header.crc = get_sb_crc(sb);
409 :
410 5 : ftl_mngt_next_step(mngt);
411 5 : }
412 :
413 : void
414 0 : ftl_mngt_set_dirty(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
415 : {
416 0 : struct ftl_superblock *sb = dev->sb;
417 :
418 0 : sb->clean = 0;
419 0 : sb->upgrade_ready = false;
420 0 : dev->sb_shm->shm_clean = false;
421 0 : sb->header.crc = get_sb_crc(sb);
422 0 : persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB);
423 0 : }
424 :
425 : void
426 0 : ftl_mngt_set_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
427 : {
428 0 : struct ftl_superblock *sb = dev->sb;
429 :
430 0 : sb->clean = 1;
431 0 : sb->upgrade_ready = dev->conf.prep_upgrade_on_shutdown;
432 0 : dev->sb_shm->shm_clean = false;
433 0 : sb->header.crc = get_sb_crc(sb);
434 0 : persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB);
435 :
436 0 : dev->sb_shm->shm_ready = false;
437 0 : }
438 :
439 : void
440 0 : ftl_mngt_set_shm_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
441 : {
442 0 : struct ftl_superblock *sb = dev->sb;
443 :
444 0 : sb->clean = 1;
445 0 : dev->sb_shm->shm_clean = true;
446 0 : sb->header.crc = get_sb_crc(sb);
447 0 : ftl_mngt_next_step(mngt);
448 0 : }
449 :
450 : void
451 0 : ftl_mngt_load_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
452 : {
453 0 : FTL_NOTICELOG(dev, "SHM: clean %"PRIu64", shm_clean %d\n", dev->sb->clean, dev->sb_shm->shm_clean);
454 :
455 0 : if (!ftl_fast_startup(dev)) {
456 0 : restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB);
457 0 : return;
458 : }
459 :
460 0 : FTL_DEBUGLOG(dev, "SHM: found SB\n");
461 0 : if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_SB)) {
462 0 : ftl_mngt_fail_step(mngt);
463 0 : return;
464 : }
465 0 : ftl_mngt_next_step(mngt);
466 : }
467 :
468 : void
469 0 : ftl_mngt_validate_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
470 : {
471 0 : struct ftl_superblock *sb = dev->sb;
472 :
473 0 : if (!ftl_superblock_check_magic(sb)) {
474 0 : FTL_ERRLOG(dev, "Invalid FTL superblock magic\n");
475 0 : ftl_mngt_fail_step(mngt);
476 0 : return;
477 : }
478 :
479 0 : if (sb->header.crc != get_sb_crc(sb)) {
480 0 : FTL_ERRLOG(dev, "Invalid FTL superblock CRC\n");
481 0 : ftl_mngt_fail_step(mngt);
482 0 : return;
483 : }
484 :
485 0 : if (ftl_superblock_upgrade(dev)) {
486 0 : FTL_ERRLOG(dev, "FTL superblock dirty or invalid version\n");
487 0 : ftl_mngt_fail_step(mngt);
488 0 : return;
489 : }
490 :
491 0 : if (spdk_uuid_compare(&sb->uuid, &dev->conf.uuid) != 0) {
492 0 : FTL_ERRLOG(dev, "Invalid FTL superblock UUID\n");
493 0 : ftl_mngt_fail_step(mngt);
494 0 : return;
495 : }
496 :
497 0 : if (sb->lba_cnt == 0) {
498 0 : FTL_ERRLOG(dev, "Invalid FTL superblock lba_cnt\n");
499 0 : ftl_mngt_fail_step(mngt);
500 0 : return;
501 : }
502 0 : dev->num_lbas = sb->lba_cnt;
503 :
504 : /* The sb has just been read. Validate and update the conf */
505 0 : if (sb->overprovisioning == 0 || sb->overprovisioning >= 100) {
506 0 : FTL_ERRLOG(dev, "Invalid FTL superblock lba_rsvd\n");
507 0 : ftl_mngt_fail_step(mngt);
508 0 : return;
509 : }
510 0 : dev->conf.overprovisioning = sb->overprovisioning;
511 :
512 0 : if (!ftl_superblock_validate_blob_area(dev)) {
513 0 : FTL_ERRLOG(dev, "Corrupted FTL superblock blob area\n");
514 0 : ftl_mngt_fail_step(mngt);
515 0 : return;
516 : }
517 :
518 0 : ftl_mngt_next_step(mngt);
519 : }
520 :
521 : /*
522 : * Loads and verifies superblock contents - utilized during the load of an FTL
523 : * instance (both from a clean and dirty shutdown).
524 : */
525 : static const struct ftl_mngt_process_desc desc_restore_sb = {
526 : .name = "SB restore",
527 : .steps = {
528 : {
529 : .name = "Load super block",
530 : .action = ftl_mngt_load_sb
531 : },
532 : {
533 : .name = "Validate super block",
534 : .action = ftl_mngt_validate_sb
535 : },
536 : {}
537 : }
538 : };
539 :
540 : /*
541 : * Initializes the superblock fields during first startup of FTL
542 : */
543 : static const struct ftl_mngt_process_desc desc_init_sb = {
544 : .name = "SB initialize",
545 : .steps = {
546 : {
547 : .name = "Default-initialize superblock",
548 : .action = ftl_mngt_init_default_sb,
549 : },
550 : {}
551 : }
552 : };
553 :
554 : void
555 0 : ftl_mngt_superblock_init(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
556 : {
557 : struct ftl_md *md;
558 : struct ftl_md *md_mirror;
559 0 : struct ftl_layout *layout = &dev->layout;
560 0 : struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB];
561 0 : char uuid[SPDK_UUID_STRING_LEN];
562 0 : int md_create_flags = ftl_md_create_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB);
563 :
564 : /* Must generate UUID before MD create on SHM for the SB */
565 0 : if (dev->conf.mode & SPDK_FTL_MODE_CREATE) {
566 0 : spdk_uuid_generate(&dev->conf.uuid);
567 0 : spdk_uuid_fmt_lower(uuid, sizeof(uuid), &dev->conf.uuid);
568 0 : FTL_NOTICELOG(dev, "Create new FTL, UUID %s\n", uuid);
569 : }
570 :
571 0 : shm_retry:
572 : /* Allocate md buf */
573 0 : dev->sb_shm = NULL;
574 0 : dev->sb_shm_md = ftl_md_create(dev, spdk_divide_round_up(sizeof(*dev->sb_shm), FTL_BLOCK_SIZE),
575 : 0, "sb_shm",
576 : md_create_flags, NULL);
577 0 : if (dev->sb_shm_md == NULL) {
578 : /* The first attempt may fail when trying to open SHM - try to create new */
579 0 : if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) {
580 0 : md_create_flags |= FTL_MD_CREATE_SHM_NEW;
581 0 : goto shm_retry;
582 : }
583 0 : if (dev->sb_shm_md == NULL) {
584 0 : ftl_mngt_fail_step(mngt);
585 0 : return;
586 : }
587 : }
588 :
589 0 : dev->sb_shm = ftl_md_get_buffer(dev->sb_shm_md);
590 :
591 : /* Setup the layout of a superblock */
592 0 : if (ftl_layout_setup_superblock(dev)) {
593 0 : ftl_mngt_fail_step(mngt);
594 0 : return;
595 : }
596 :
597 : /* Allocate md buf */
598 0 : layout->md[FTL_LAYOUT_REGION_TYPE_SB] = ftl_md_create(dev, region->current.blocks,
599 : region->vss_blksz, region->name,
600 : md_create_flags, region);
601 0 : if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB]) {
602 : /* The first attempt may fail when trying to open SHM - try to create new */
603 0 : if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) {
604 0 : md_create_flags |= FTL_MD_CREATE_SHM_NEW;
605 0 : ftl_md_destroy(dev->sb_shm_md, 0);
606 0 : dev->sb_shm_md = NULL;
607 0 : if (ftl_layout_clear_superblock(dev)) {
608 0 : ftl_mngt_fail_step(mngt);
609 0 : return;
610 : }
611 0 : goto shm_retry;
612 : }
613 0 : ftl_mngt_fail_step(mngt);
614 0 : return;
615 : }
616 :
617 : /* Link the md buf to the device */
618 0 : dev->sb = ftl_md_get_buffer(layout->md[FTL_LAYOUT_REGION_TYPE_SB]);
619 :
620 : /* Setup superblock mirror to QLC */
621 0 : region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB_BASE];
622 0 : layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = ftl_md_create(dev, region->current.blocks,
623 : region->vss_blksz, NULL, FTL_MD_CREATE_NO_MEM, region);
624 0 : if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) {
625 0 : ftl_mngt_fail_step(mngt);
626 0 : return;
627 : }
628 :
629 : /* Initialize mirror region buffer */
630 0 : md = layout->md[FTL_LAYOUT_REGION_TYPE_SB];
631 0 : md_mirror = layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE];
632 :
633 0 : md_mirror->dev = md->dev;
634 0 : md_mirror->data_blocks = md->data_blocks;
635 0 : md_mirror->data = md->data;
636 0 : md_mirror->is_mirror = true;
637 :
638 : /* Initialize the superblock */
639 0 : if (dev->conf.mode & SPDK_FTL_MODE_CREATE) {
640 0 : ftl_mngt_call_process(mngt, &desc_init_sb, NULL);
641 : } else {
642 0 : ftl_mngt_call_process(mngt, &desc_restore_sb, NULL);
643 : }
644 : }
645 :
646 : void
647 0 : ftl_mngt_superblock_deinit(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
648 : {
649 0 : struct ftl_layout *layout = &dev->layout;
650 :
651 0 : if (layout->md[FTL_LAYOUT_REGION_TYPE_SB]) {
652 0 : ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB],
653 : ftl_md_destroy_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB));
654 0 : layout->md[FTL_LAYOUT_REGION_TYPE_SB] = NULL;
655 : }
656 :
657 0 : if (layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE]) {
658 0 : ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE], 0);
659 0 : layout->md[FTL_LAYOUT_REGION_TYPE_SB_BASE] = NULL;
660 : }
661 :
662 0 : ftl_md_destroy(dev->sb_shm_md, ftl_md_destroy_shm_flags(dev));
663 0 : dev->sb_shm_md = NULL;
664 0 : dev->sb_shm = NULL;
665 :
666 0 : ftl_mngt_next_step(mngt);
667 0 : }
668 :
669 : static void
670 0 : ftl_mngt_restore_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
671 : {
672 0 : if (ftl_fast_startup(dev)) {
673 0 : FTL_DEBUGLOG(dev, "SHM: found nv cache md\n");
674 0 : if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_NVC_MD)) {
675 0 : ftl_mngt_fail_step(mngt);
676 0 : return;
677 : }
678 0 : ftl_mngt_next_step(mngt);
679 0 : return;
680 : }
681 0 : restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_NVC_MD);
682 : }
683 :
684 : static void
685 0 : ftl_mngt_restore_vld_map_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
686 : {
687 0 : if (ftl_fast_startup(dev)) {
688 0 : FTL_DEBUGLOG(dev, "SHM: found vldmap\n");
689 0 : if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_VALID_MAP)) {
690 0 : ftl_mngt_fail_step(mngt);
691 0 : return;
692 : }
693 0 : ftl_mngt_next_step(mngt);
694 0 : return;
695 : }
696 0 : restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_VALID_MAP);
697 : }
698 :
699 : static void
700 0 : ftl_mngt_restore_band_info_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
701 : {
702 0 : if (ftl_fast_startup(dev)) {
703 0 : FTL_DEBUGLOG(dev, "SHM: found band md\n");
704 0 : if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_BAND_MD)) {
705 0 : ftl_mngt_fail_step(mngt);
706 0 : return;
707 : }
708 0 : ftl_mngt_next_step(mngt);
709 0 : return;
710 : }
711 0 : restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_BAND_MD);
712 : }
713 :
714 : static void
715 0 : ftl_mngt_restore_trim_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
716 : {
717 0 : if (ftl_fast_startup(dev)) {
718 0 : FTL_DEBUGLOG(dev, "SHM: found trim md\n");
719 0 : if (ftl_md_restore_region(dev, FTL_LAYOUT_REGION_TYPE_TRIM_MD)) {
720 0 : ftl_mngt_fail_step(mngt);
721 0 : return;
722 : }
723 0 : ftl_mngt_next_step(mngt);
724 0 : return;
725 : }
726 0 : restore(dev, mngt, FTL_LAYOUT_REGION_TYPE_TRIM_MD);
727 : }
728 :
729 : /*
730 : * Loads metadata after a clean shutdown.
731 : */
732 : static const struct ftl_mngt_process_desc desc_restore = {
733 : .name = "Restore metadata",
734 : .steps = {
735 : {
736 : .name = "Restore NV cache metadata",
737 : .action = ftl_mngt_restore_nv_cache_metadata,
738 : },
739 : {
740 : .name = "Restore valid map metadata",
741 : .action = ftl_mngt_restore_vld_map_metadata,
742 : },
743 : {
744 : .name = "Restore band info metadata",
745 : .action = ftl_mngt_restore_band_info_metadata,
746 : },
747 : {
748 : .name = "Restore trim metadata",
749 : .action = ftl_mngt_restore_trim_metadata,
750 : },
751 : {}
752 : }
753 : };
754 :
755 : void
756 0 : ftl_mngt_restore_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
757 : {
758 0 : ftl_mngt_call_process(mngt, &desc_restore, NULL);
759 0 : }
760 :
761 : void
762 0 : ftl_mngt_persist_superblock(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
763 : {
764 0 : dev->sb->header.crc = get_sb_crc(dev->sb);
765 0 : persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_SB);
766 0 : }
|