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 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 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 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 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 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 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