xref: /spdk/lib/ftl/upgrade/ftl_p2l_upgrade.c (revision 8afdeef3becfe9409cc9e7372bd0bc10e8b7d46d)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2022 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "mngt/ftl_mngt.h"
7 #include "mngt/ftl_mngt_steps.h"
8 #include "ftl_layout_upgrade.h"
9 
10 struct upgrade_ctx {
11 	struct ftl_md			*md;
12 	struct ftl_layout_region	reg;
13 };
14 
15 static void
16 v2_upgrade_cleanup(struct ftl_layout_upgrade_ctx *lctx)
17 {
18 	struct upgrade_ctx *ctx = lctx->ctx;
19 
20 	if (ctx->md) {
21 		ftl_md_destroy(ctx->md, 0);
22 		ctx->md = NULL;
23 	}
24 }
25 
26 static void
27 v2_upgrade_finish(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *lctx, int status)
28 {
29 	struct upgrade_ctx *ctx = lctx->ctx;
30 
31 	v2_upgrade_cleanup(lctx);
32 	ftl_region_upgrade_completed(dev, lctx, ctx->reg.entry_size, ctx->reg.num_entries, status);
33 }
34 
35 static void
36 v2_upgrade_md_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status)
37 {
38 	struct ftl_layout_upgrade_ctx *lctx = md->owner.cb_ctx;
39 
40 	v2_upgrade_finish(dev, lctx, status);
41 }
42 
43 static int
44 v2_upgrade_setup_ctx(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *lctx, uint32_t type)
45 {
46 	struct upgrade_ctx *ctx = lctx->ctx;
47 	const struct ftl_md_layout_ops *md_ops = &dev->nv_cache.nvc_type->ops.md_layout_ops;
48 
49 	/* TODO Add validation if no open bands */
50 
51 	/* Open metadata region */
52 	if (md_ops->region_open(dev, lctx->reg->type, FTL_P2L_VERSION_2,
53 				sizeof(struct ftl_p2l_ckpt_page_no_vss),
54 				dev->layout.p2l.ckpt_pages, &ctx->reg)) {
55 		return -1;
56 	}
57 
58 	ctx->md = ftl_md_create(dev, ctx->reg.current.blocks, 0, ctx->reg.name, FTL_MD_CREATE_HEAP,
59 				&ctx->reg);
60 	if (!ctx->md) {
61 		return -1;
62 	}
63 
64 	ctx->md->owner.cb_ctx = lctx;
65 	ctx->md->cb = v2_upgrade_md_cb;
66 
67 	return 0;
68 }
69 
70 static int
71 v2_upgrade(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *lctx)
72 {
73 	struct upgrade_ctx *ctx = lctx->ctx;
74 
75 	if (v2_upgrade_setup_ctx(dev, lctx, lctx->reg->type)) {
76 		goto error;
77 	}
78 	ftl_md_clear(ctx->md, 0, NULL);
79 	return 0;
80 error:
81 	v2_upgrade_cleanup(lctx);
82 	return -1;
83 }
84 
85 static int
86 v1_to_v2_upgrade_enabled(struct spdk_ftl_dev *dev, struct ftl_layout_region *region)
87 {
88 	const struct ftl_md_layout_ops *md_ops = &dev->nv_cache.nvc_type->ops.md_layout_ops;
89 
90 	if (ftl_region_major_upgrade_enabled(dev, region)) {
91 		return -1;
92 	}
93 
94 	/* Create the new P2L metadata region (v2) up front - this allocates a separate entry in the superblock and
95 	 * area on the cache for us. This is to reserve space for other region upgrades allocating new regions and it
96 	 * allows us to do an atomic upgrade of the whole region.
97 	 *
98 	 * If the upgrade is stopped by power failure/crash after the V2 region has been added, then the upgrade process
99 	 * will start again (since V1 still exists), but region_create will fail (since the v2 region has already been
100 	 * created). In such a case only verification of the region length by region_open is needed.
101 	 *
102 	 * Once the upgrade is fully done, the old v1 region entry will be removed from the SB and its area on the cache
103 	 * freed.
104 	 */
105 	if (md_ops->region_create(dev, region->type, FTL_P2L_VERSION_2, dev->layout.p2l.ckpt_pages) &&
106 	    md_ops->region_open(dev, region->type, FTL_P2L_VERSION_2, sizeof(struct ftl_p2l_ckpt_page_no_vss),
107 				dev->layout.p2l.ckpt_pages, NULL)) {
108 		return -1;
109 	}
110 
111 	return 0;
112 }
113 
114 struct ftl_region_upgrade_desc p2l_upgrade_desc[] = {
115 	[FTL_P2L_VERSION_0] = {
116 		.verify = ftl_region_upgrade_disabled
117 	},
118 	[FTL_P2L_VERSION_1] = {
119 		.verify = v1_to_v2_upgrade_enabled,
120 		.ctx_size = sizeof(struct upgrade_ctx),
121 		.new_version = FTL_P2L_VERSION_2,
122 		.upgrade = v2_upgrade,
123 	},
124 };
125 
126 SPDK_STATIC_ASSERT(SPDK_COUNTOF(p2l_upgrade_desc) == FTL_P2L_VERSION_CURRENT,
127 		   "Missing P2L region upgrade descriptors");
128