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