1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2023 Solidigm All Rights Reserved 3 * Copyright (C) 2022 Intel Corporation. 4 * All rights reserved. 5 */ 6 7 #include "ftl_band.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_persist_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 void 44 v2_upgrade_md_restore_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status) 45 { 46 struct ftl_layout_upgrade_ctx *lctx = md->owner.cb_ctx; 47 struct upgrade_ctx *ctx = lctx->ctx; 48 struct ftl_band_md *band = ftl_md_get_buffer(md); 49 uint64_t move = sizeof(band->version); 50 51 if (status) { 52 v2_upgrade_finish(dev, lctx, status); 53 return; 54 } 55 56 /* If the upgrade process is interrupted while only part of the update persisted, 57 * then the V1 version will be read from again and this section will rewrite the whole band md. 58 */ 59 for (uint64_t i = 0; i < dev->num_bands; i++, band++) { 60 char *buffer = (char *)band; 61 62 memmove(buffer + move, buffer, sizeof(*band) - move); 63 band->version = FTL_BAND_VERSION_2; 64 65 if (band->state != FTL_BAND_STATE_CLOSED && band->state != FTL_BAND_STATE_FREE) { 66 v2_upgrade_finish(dev, lctx, -EINVAL); 67 return; 68 } 69 } 70 71 ctx->md->cb = v2_upgrade_md_persist_cb; 72 ftl_md_set_region(ctx->md, &ctx->reg); 73 ftl_md_persist(ctx->md); 74 } 75 76 static int 77 v2_upgrade_setup_ctx(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *lctx) 78 { 79 struct upgrade_ctx *ctx = lctx->ctx; 80 const struct ftl_md_layout_ops *md_ops = &dev->nv_cache.nvc_type->ops.md_layout_ops; 81 82 assert(sizeof(struct ftl_band_md) == FTL_BLOCK_SIZE); 83 84 if (lctx->reg->num_entries != dev->num_bands) { 85 return -1; 86 } 87 88 /* Open metadata region */ 89 if (md_ops->region_open(dev, lctx->reg->type, FTL_BAND_VERSION_2, sizeof(struct ftl_band_md), 90 dev->num_bands, &ctx->reg)) { 91 return -1; 92 } 93 94 if (lctx->reg->current.blocks != ctx->reg.current.blocks) { 95 return -1; 96 } 97 98 ctx->md = ftl_md_create(dev, lctx->reg->current.blocks, 0, ctx->reg.name, FTL_MD_CREATE_HEAP, 99 lctx->reg); 100 if (!ctx->md) { 101 return -1; 102 } 103 104 ctx->md->owner.cb_ctx = lctx; 105 ctx->md->cb = v2_upgrade_md_restore_cb; 106 107 return 0; 108 } 109 110 static int 111 v2_upgrade(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *lctx) 112 { 113 struct upgrade_ctx *ctx = lctx->ctx; 114 115 if (v2_upgrade_setup_ctx(dev, lctx)) { 116 goto error; 117 } 118 /* At this point we're reading the contents of the v1 md */ 119 ftl_md_restore(ctx->md); 120 return 0; 121 error: 122 v2_upgrade_cleanup(lctx); 123 return -1; 124 } 125 126 static int 127 v1_to_v2_upgrade_enabled(struct spdk_ftl_dev *dev, struct ftl_layout_region *region) 128 { 129 const struct ftl_md_layout_ops *md_ops = &dev->nv_cache.nvc_type->ops.md_layout_ops; 130 131 if (ftl_region_major_upgrade_enabled(dev, region)) { 132 return -1; 133 } 134 135 /* Create the new band metadata region (v2) up front - this allocates a separate entry in the superblock and 136 * area on the cache for us. This is to reserve space for other region upgrades allocating new regions and it 137 * allows us to do an atomic upgrade of the whole region. 138 * 139 * If the upgrade is stopped by power failure/crash after the V2 region has been added, then the upgrade process 140 * will start again (since V1 still exists), but region_create will fail (since the v2 region has already been 141 * created). In such a case only verification of the region length by region_open is needed. 142 * 143 * Once the upgrade is fully done, the old v1 region entry will be removed from the SB and its area on the cache 144 * freed. 145 */ 146 if (md_ops->region_create(dev, region->type, FTL_BAND_VERSION_2, dev->num_bands) && 147 md_ops->region_open(dev, region->type, FTL_BAND_VERSION_2, sizeof(struct ftl_band_md), 148 dev->num_bands, NULL)) { 149 return -1; 150 } 151 152 return 0; 153 } 154 155 struct ftl_region_upgrade_desc band_upgrade_desc[] = { 156 [FTL_BAND_VERSION_0] = { 157 .verify = ftl_region_upgrade_disabled, 158 }, 159 [FTL_BAND_VERSION_1] = { 160 .verify = v1_to_v2_upgrade_enabled, 161 .ctx_size = sizeof(struct upgrade_ctx), 162 .new_version = FTL_BAND_VERSION_2, 163 .upgrade = v2_upgrade, 164 }, 165 }; 166 167 SPDK_STATIC_ASSERT(SPDK_COUNTOF(band_upgrade_desc) == FTL_BAND_VERSION_CURRENT, 168 "Missing band region upgrade descriptors"); 169