xref: /spdk/lib/ftl/mngt/ftl_mngt_upgrade.c (revision 588dfe314bb83d86effdf67ec42837b11c2620bf)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2022 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "ftl_core.h"
7 #include "ftl_mngt.h"
8 #include "ftl_mngt_steps.h"
9 #include "upgrade/ftl_layout_upgrade.h"
10 
11 struct ftl_mngt_upgrade_ctx {
12 	struct ftl_mngt_process *parent;
13 	struct ftl_mngt_process *mngt;
14 	struct ftl_layout_upgrade_ctx upgrade_ctx;
15 };
16 
17 static void
18 region_upgrade_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
19 {
20 	struct ftl_mngt_upgrade_ctx *ctx = _ctx;
21 
22 	free(ctx->upgrade_ctx.ctx);
23 	ctx->upgrade_ctx.ctx = NULL;
24 
25 	if (status) {
26 		FTL_ERRLOG(dev, "Upgrade failed for region %d (rc=%d)\n", ctx->upgrade_ctx.reg->type, status);
27 		ftl_mngt_fail_step(ctx->mngt);
28 	} else {
29 		ftl_mngt_next_step(ctx->mngt);
30 	}
31 }
32 
33 static void
34 region_upgrade(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
35 {
36 	struct ftl_mngt_upgrade_ctx *ctx = ftl_mngt_get_caller_ctx(mngt);
37 	struct ftl_layout_upgrade_ctx *upgrade_ctx = &ctx->upgrade_ctx;
38 	size_t ctx_size = upgrade_ctx->upgrade->desc[upgrade_ctx->reg->prev.version].ctx_size;
39 	int rc = -1;
40 
41 	assert(upgrade_ctx->ctx == NULL);
42 	if (ctx_size) {
43 		upgrade_ctx->ctx = calloc(1, ctx_size);
44 		if (!upgrade_ctx->ctx) {
45 			goto exit;
46 		}
47 	}
48 	upgrade_ctx->cb = region_upgrade_cb;
49 	upgrade_ctx->cb_ctx = ctx;
50 	ctx->mngt = mngt;
51 
52 	rc = ftl_region_upgrade(dev, upgrade_ctx);
53 exit:
54 	if (rc) {
55 		region_upgrade_cb(dev, ctx, rc);
56 	}
57 }
58 
59 static const struct ftl_mngt_process_desc desc_region_upgrade = {
60 	.name = "FTL region upgrade",
61 	.steps = {
62 		{
63 			.name = "Region upgrade",
64 			.action = region_upgrade,
65 		},
66 		{
67 			.name = "Persist superblock",
68 			.action = ftl_mngt_persist_superblock,
69 		},
70 		{}
71 	}
72 };
73 
74 static void
75 layout_upgrade_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
76 {
77 	struct ftl_mngt_upgrade_ctx *ctx = _ctx;
78 
79 	if (status) {
80 		free(ctx->upgrade_ctx.ctx);
81 		ctx->upgrade_ctx.ctx = NULL;
82 		ftl_mngt_fail_step(ctx->parent);
83 		return;
84 	}
85 
86 	/* go back to ftl_mngt_upgrade() step and select the next region/version to upgrade */
87 	ftl_mngt_continue_step(ctx->parent);
88 }
89 
90 static void
91 layout_upgrade(struct spdk_ftl_dev *dev, struct ftl_mngt_process *parent)
92 {
93 	struct ftl_mngt_upgrade_ctx *ctx = ftl_mngt_get_process_ctx(parent);
94 	int rc;
95 
96 	ctx->parent = parent;
97 	rc = ftl_layout_upgrade_init_ctx(dev, &ctx->upgrade_ctx);
98 
99 	switch (rc) {
100 	case FTL_LAYOUT_UPGRADE_CONTINUE:
101 		if (!ftl_mngt_process_execute(dev, &desc_region_upgrade, layout_upgrade_cb, ctx)) {
102 			return;
103 		}
104 
105 		ftl_mngt_fail_step(parent);
106 		break;
107 
108 	case FTL_LAYOUT_UPGRADE_DONE:
109 		if (ftl_upgrade_layout_dump(dev)) {
110 			FTL_ERRLOG(dev, "MD layout verification failed after upgrade.\n");
111 			ftl_mngt_fail_step(parent);
112 		} else {
113 			ftl_mngt_next_step(parent);
114 		}
115 		break;
116 
117 	case FTL_LAYOUT_UPGRADE_FAULT:
118 		ftl_mngt_fail_step(parent);
119 		break;
120 	}
121 	if (ctx->upgrade_ctx.ctx) {
122 		free(ctx->upgrade_ctx.ctx);
123 	}
124 }
125 
126 static const struct ftl_mngt_process_desc desc_layout_upgrade = {
127 	.name = "FTL layout upgrade",
128 	.ctx_size = sizeof(struct ftl_mngt_upgrade_ctx),
129 	.steps = {
130 		{
131 			.name = "Layout upgrade",
132 			.action = layout_upgrade,
133 		},
134 		{}
135 	}
136 };
137 
138 
139 void
140 ftl_mngt_layout_verify(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
141 {
142 	if (ftl_layout_verify(dev)) {
143 		ftl_mngt_fail_step(mngt);
144 	} else {
145 		ftl_mngt_next_step(mngt);
146 	}
147 }
148 
149 void
150 ftl_mngt_layout_upgrade(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
151 {
152 	ftl_mngt_call_process(mngt, &desc_layout_upgrade);
153 }
154