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