xref: /spdk/lib/ftl/upgrade/ftl_layout_upgrade.c (revision 6d6179ff420a322c5161a49a5af5bfd30e78674e)
17ff28519SKozlowski Mateusz /*   SPDX-License-Identifier: BSD-3-Clause
217cf101bSMateusz Kozlowski  *   Copyright 2023 Solidigm All Rights Reserved
3a6dbe372Spaul luse  *   Copyright (C) 2022 Intel Corporation.
47ff28519SKozlowski Mateusz  *   All rights reserved.
57ff28519SKozlowski Mateusz  */
67ff28519SKozlowski Mateusz 
7f34b13ecSNathan Claudel #include "spdk/assert.h"
8f34b13ecSNathan Claudel 
97ff28519SKozlowski Mateusz #include "ftl_layout_upgrade.h"
107ff28519SKozlowski Mateusz #include "ftl_layout.h"
117ff28519SKozlowski Mateusz #include "ftl_sb_current.h"
12c8ab874dSKozlowski Mateusz #include "ftl_sb_prev.h"
137ff28519SKozlowski Mateusz #include "ftl_core.h"
147ff28519SKozlowski Mateusz #include "ftl_band.h"
15a5c04e6dSMateusz Kozlowski #include "utils/ftl_layout_tracker_bdev.h"
16a5c04e6dSMateusz Kozlowski 
17a5c04e6dSMateusz Kozlowski int
18a5c04e6dSMateusz Kozlowski ftl_region_major_upgrade_enabled(struct spdk_ftl_dev *dev, struct ftl_layout_region *region)
19a5c04e6dSMateusz Kozlowski {
20a5c04e6dSMateusz Kozlowski 	if (ftl_region_upgrade_enabled(dev, region)) {
21a5c04e6dSMateusz Kozlowski 		return -1;
22a5c04e6dSMateusz Kozlowski 	}
23a5c04e6dSMateusz Kozlowski 
24a5c04e6dSMateusz Kozlowski 	if (dev->sb->upgrade_ready) {
25a5c04e6dSMateusz Kozlowski 		return 0;
26a5c04e6dSMateusz Kozlowski 	} else {
27a5c04e6dSMateusz Kozlowski 		FTL_ERRLOG(dev, "FTL major upgrade ERROR, required upgrade shutdown in the previous version\n");
28a5c04e6dSMateusz Kozlowski 		return -1;
29a5c04e6dSMateusz Kozlowski 	}
30a5c04e6dSMateusz Kozlowski }
317ff28519SKozlowski Mateusz 
327ff28519SKozlowski Mateusz int
337ff28519SKozlowski Mateusz ftl_region_upgrade_disabled(struct spdk_ftl_dev *dev, struct ftl_layout_region *region)
347ff28519SKozlowski Mateusz {
357ff28519SKozlowski Mateusz 	return -1;
367ff28519SKozlowski Mateusz }
377ff28519SKozlowski Mateusz 
387ff28519SKozlowski Mateusz int
397ff28519SKozlowski Mateusz ftl_region_upgrade_enabled(struct spdk_ftl_dev *dev, struct ftl_layout_region *region)
407ff28519SKozlowski Mateusz {
417ff28519SKozlowski Mateusz 	if (!(dev->sb->clean == 1 && dev->sb_shm->shm_clean == 0)) {
427ff28519SKozlowski Mateusz 		FTL_ERRLOG(dev, "FTL region upgrade: SB dirty\n");
437ff28519SKozlowski Mateusz 		return -1;
447ff28519SKozlowski Mateusz 	}
457ff28519SKozlowski Mateusz 	return 0;
467ff28519SKozlowski Mateusz }
477ff28519SKozlowski Mateusz 
487ff28519SKozlowski Mateusz #ifndef UTEST
497ff28519SKozlowski Mateusz extern struct ftl_region_upgrade_desc sb_upgrade_desc[];
507ff28519SKozlowski Mateusz extern struct ftl_region_upgrade_desc p2l_upgrade_desc[];
517ff28519SKozlowski Mateusz extern struct ftl_region_upgrade_desc nvc_upgrade_desc[];
527ff28519SKozlowski Mateusz extern struct ftl_region_upgrade_desc band_upgrade_desc[];
532d613454SMateusz Kozlowski extern struct ftl_region_upgrade_desc trim_log_upgrade_desc[];
547ff28519SKozlowski Mateusz 
557ff28519SKozlowski Mateusz static struct ftl_layout_upgrade_desc_list layout_upgrade_desc[] = {
56c8ab874dSKozlowski Mateusz 	[FTL_LAYOUT_REGION_TYPE_SB] = {
578fc78fd8SMateusz Kozlowski 		.latest_ver = FTL_SB_VERSION_CURRENT,
58c8ab874dSKozlowski Mateusz 		.count = FTL_SB_VERSION_CURRENT,
59c8ab874dSKozlowski Mateusz 		.desc = sb_upgrade_desc,
60c8ab874dSKozlowski Mateusz 	},
61c8ab874dSKozlowski Mateusz 	[FTL_LAYOUT_REGION_TYPE_SB_BASE] = {
628fc78fd8SMateusz Kozlowski 		.latest_ver = FTL_SB_VERSION_CURRENT,
63c8ab874dSKozlowski Mateusz 		.count = FTL_SB_VERSION_CURRENT,
64c8ab874dSKozlowski Mateusz 		.desc = sb_upgrade_desc,
65c8ab874dSKozlowski Mateusz 	},
667ff28519SKozlowski Mateusz 	[FTL_LAYOUT_REGION_TYPE_L2P] = {},
678c41c403SKozlowski Mateusz 	[FTL_LAYOUT_REGION_TYPE_BAND_MD] = {
688fc78fd8SMateusz Kozlowski 		.latest_ver = FTL_BAND_VERSION_CURRENT,
698c41c403SKozlowski Mateusz 		.count = FTL_BAND_VERSION_CURRENT,
708c41c403SKozlowski Mateusz 		.desc = band_upgrade_desc,
718c41c403SKozlowski Mateusz 	},
728c41c403SKozlowski Mateusz 	[FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR] = {
738fc78fd8SMateusz Kozlowski 		.latest_ver = FTL_BAND_VERSION_CURRENT,
748c41c403SKozlowski Mateusz 		.count = FTL_BAND_VERSION_CURRENT,
758c41c403SKozlowski Mateusz 		.desc = band_upgrade_desc,
768c41c403SKozlowski Mateusz 	},
777ff28519SKozlowski Mateusz 	[FTL_LAYOUT_REGION_TYPE_VALID_MAP] = {},
788c41c403SKozlowski Mateusz 	[FTL_LAYOUT_REGION_TYPE_NVC_MD] = {
798fc78fd8SMateusz Kozlowski 		.latest_ver = FTL_NVC_VERSION_CURRENT,
808c41c403SKozlowski Mateusz 		.count = FTL_NVC_VERSION_CURRENT,
818c41c403SKozlowski Mateusz 		.desc = nvc_upgrade_desc,
828c41c403SKozlowski Mateusz 	},
838c41c403SKozlowski Mateusz 	[FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR] = {
848fc78fd8SMateusz Kozlowski 		.latest_ver = FTL_NVC_VERSION_CURRENT,
858c41c403SKozlowski Mateusz 		.count = FTL_NVC_VERSION_CURRENT,
868c41c403SKozlowski Mateusz 		.desc = nvc_upgrade_desc,
878c41c403SKozlowski Mateusz 	},
887ff28519SKozlowski Mateusz 	[FTL_LAYOUT_REGION_TYPE_DATA_NVC] = {},
897ff28519SKozlowski Mateusz 	[FTL_LAYOUT_REGION_TYPE_DATA_BASE] = {},
908c41c403SKozlowski Mateusz 	[FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC] = {
918fc78fd8SMateusz Kozlowski 		.latest_ver = FTL_P2L_VERSION_CURRENT,
928c41c403SKozlowski Mateusz 		.count = FTL_P2L_VERSION_CURRENT,
938c41c403SKozlowski Mateusz 		.desc = p2l_upgrade_desc,
948c41c403SKozlowski Mateusz 	},
958c41c403SKozlowski Mateusz 	[FTL_LAYOUT_REGION_TYPE_P2L_CKPT_GC_NEXT] = {
968fc78fd8SMateusz Kozlowski 		.latest_ver = FTL_P2L_VERSION_CURRENT,
978c41c403SKozlowski Mateusz 		.count = FTL_P2L_VERSION_CURRENT,
988c41c403SKozlowski Mateusz 		.desc = p2l_upgrade_desc,
998c41c403SKozlowski Mateusz 	},
1008c41c403SKozlowski Mateusz 	[FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP] = {
1018fc78fd8SMateusz Kozlowski 		.latest_ver = FTL_P2L_VERSION_CURRENT,
1028c41c403SKozlowski Mateusz 		.count = FTL_P2L_VERSION_CURRENT,
1038c41c403SKozlowski Mateusz 		.desc = p2l_upgrade_desc,
1048c41c403SKozlowski Mateusz 	},
1058c41c403SKozlowski Mateusz 	[FTL_LAYOUT_REGION_TYPE_P2L_CKPT_COMP_NEXT] = {
1068fc78fd8SMateusz Kozlowski 		.latest_ver = FTL_P2L_VERSION_CURRENT,
1078c41c403SKozlowski Mateusz 		.count = FTL_P2L_VERSION_CURRENT,
1088c41c403SKozlowski Mateusz 		.desc = p2l_upgrade_desc,
1098c41c403SKozlowski Mateusz 	},
1107ff28519SKozlowski Mateusz 	[FTL_LAYOUT_REGION_TYPE_TRIM_MD] = {},
1117ff28519SKozlowski Mateusz 	[FTL_LAYOUT_REGION_TYPE_TRIM_MD_MIRROR] = {},
1122d613454SMateusz Kozlowski 	[FTL_LAYOUT_REGION_TYPE_TRIM_LOG] = {
1132d613454SMateusz Kozlowski 		.latest_ver = FTL_TRIM_LOG_VERSION_CURRENT,
1142d613454SMateusz Kozlowski 		.count = FTL_TRIM_LOG_VERSION_CURRENT,
1152d613454SMateusz Kozlowski 		.desc = trim_log_upgrade_desc,
1162d613454SMateusz Kozlowski 	},
1172d613454SMateusz Kozlowski 	[FTL_LAYOUT_REGION_TYPE_TRIM_LOG_MIRROR] = {
1182d613454SMateusz Kozlowski 		.latest_ver = FTL_TRIM_LOG_VERSION_CURRENT,
1192d613454SMateusz Kozlowski 		.count = FTL_TRIM_LOG_VERSION_CURRENT,
1202d613454SMateusz Kozlowski 		.desc = trim_log_upgrade_desc,
1212d613454SMateusz Kozlowski 	},
122*6d6179ffSMateusz Kozlowski 	[FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MIN] = {},
123*6d6179ffSMateusz Kozlowski 	[FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MAX] = {},
1247ff28519SKozlowski Mateusz };
1257ff28519SKozlowski Mateusz 
1267ff28519SKozlowski Mateusz SPDK_STATIC_ASSERT(sizeof(layout_upgrade_desc) / sizeof(*layout_upgrade_desc) ==
1277ff28519SKozlowski Mateusz 		   FTL_LAYOUT_REGION_TYPE_MAX,
1287ff28519SKozlowski Mateusz 		   "Missing layout upgrade descriptors");
1297ff28519SKozlowski Mateusz #endif
1307ff28519SKozlowski Mateusz 
1315555d51cSLukasz Lasek uint64_t
1325555d51cSLukasz Lasek ftl_layout_upgrade_get_latest_version(enum ftl_layout_region_type reg_type)
1335555d51cSLukasz Lasek {
1345555d51cSLukasz Lasek 	assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX);
1355555d51cSLukasz Lasek 	return layout_upgrade_desc[reg_type].latest_ver;
1365555d51cSLukasz Lasek }
1375555d51cSLukasz Lasek 
1387ff28519SKozlowski Mateusz static int
1397ff28519SKozlowski Mateusz region_verify(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *ctx)
1407ff28519SKozlowski Mateusz {
1417ff28519SKozlowski Mateusz 	uint64_t ver;
1427ff28519SKozlowski Mateusz 
1437ff28519SKozlowski Mateusz 	assert(ctx->reg);
1448fc78fd8SMateusz Kozlowski 	ver = ctx->reg->current.version;
1458fc78fd8SMateusz Kozlowski 	if (ver > ctx->upgrade->latest_ver) {
1467ff28519SKozlowski Mateusz 		FTL_ERRLOG(dev, "Unknown region version\n");
1477ff28519SKozlowski Mateusz 		return -1;
1487ff28519SKozlowski Mateusz 	}
1497ff28519SKozlowski Mateusz 
1508fc78fd8SMateusz Kozlowski 	while (ver < ctx->upgrade->latest_ver) {
1517ff28519SKozlowski Mateusz 		int rc = ctx->upgrade->desc[ver].verify(dev, ctx->reg);
1527ff28519SKozlowski Mateusz 		if (rc) {
1537ff28519SKozlowski Mateusz 			return rc;
1547ff28519SKozlowski Mateusz 		}
1558fc78fd8SMateusz Kozlowski 		ftl_bug(ver > ctx->upgrade->desc[ver].new_version);
1568fc78fd8SMateusz Kozlowski 		ftl_bug(ctx->upgrade->desc[ver].new_version > ctx->upgrade->latest_ver);
1577ff28519SKozlowski Mateusz 		ver = ctx->upgrade->desc[ver].new_version;
1587ff28519SKozlowski Mateusz 	}
1597ff28519SKozlowski Mateusz 	return 0;
1607ff28519SKozlowski Mateusz }
1617ff28519SKozlowski Mateusz 
1627ff28519SKozlowski Mateusz int
1637ff28519SKozlowski Mateusz ftl_region_upgrade(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *ctx)
1647ff28519SKozlowski Mateusz {
1657ff28519SKozlowski Mateusz 	int rc = 0;
1667ff28519SKozlowski Mateusz 	uint64_t ver;
1677ff28519SKozlowski Mateusz 
1687ff28519SKozlowski Mateusz 	assert(ctx->reg);
1698fc78fd8SMateusz Kozlowski 	assert(ctx->reg->current.version <= ctx->upgrade->latest_ver);
1708fc78fd8SMateusz Kozlowski 	ver = ctx->reg->current.version;
1718fc78fd8SMateusz Kozlowski 	if (ver < ctx->upgrade->latest_ver) {
1727ff28519SKozlowski Mateusz 		ctx->next_reg_ver = ctx->upgrade->desc[ver].new_version;
1737ff28519SKozlowski Mateusz 		rc = ctx->upgrade->desc[ver].upgrade(dev, ctx);
1747ff28519SKozlowski Mateusz 	}
1757ff28519SKozlowski Mateusz 	return rc;
1767ff28519SKozlowski Mateusz }
1777ff28519SKozlowski Mateusz 
1787ff28519SKozlowski Mateusz void
1797ff28519SKozlowski Mateusz ftl_region_upgrade_completed(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *ctx,
1808fc78fd8SMateusz Kozlowski 			     uint64_t entry_size, uint64_t num_entries, int status)
1817ff28519SKozlowski Mateusz {
1828fc78fd8SMateusz Kozlowski 	int rc;
1837ff28519SKozlowski Mateusz 
1848fc78fd8SMateusz Kozlowski 	assert(ctx->reg);
1858fc78fd8SMateusz Kozlowski 	assert(ctx->reg->current.version < ctx->next_reg_ver);
1868fc78fd8SMateusz Kozlowski 	assert(ctx->next_reg_ver <= ctx->upgrade->latest_ver);
1878fc78fd8SMateusz Kozlowski 
1887ff28519SKozlowski Mateusz 	if (!status) {
1898fc78fd8SMateusz Kozlowski 		if (ctx->reg->type != FTL_LAYOUT_REGION_TYPE_SB) {
1908fc78fd8SMateusz Kozlowski 			/* Superblock region is always default-created in the latest version - see ftl_layout_setup_superblock() */
1918fc78fd8SMateusz Kozlowski 			rc = ftl_superblock_md_layout_upgrade_region(dev, ctx->reg, ctx->next_reg_ver);
1928fc78fd8SMateusz Kozlowski 			if (entry_size && num_entries) {
1938fc78fd8SMateusz Kozlowski 				dev->layout.region[ctx->reg->type].entry_size = entry_size;
1948fc78fd8SMateusz Kozlowski 				dev->layout.region[ctx->reg->type].num_entries = num_entries;
1958fc78fd8SMateusz Kozlowski 			}
1968fc78fd8SMateusz Kozlowski 
1977ff28519SKozlowski Mateusz 			ftl_bug(rc != 0);
1987ff28519SKozlowski Mateusz 		}
1997ff28519SKozlowski Mateusz 
2008fc78fd8SMateusz Kozlowski 		ctx->reg->current.version = ctx->next_reg_ver;
2017ff28519SKozlowski Mateusz 	}
2027ff28519SKozlowski Mateusz 
2037ff28519SKozlowski Mateusz 	if (ctx->cb) {
2047ff28519SKozlowski Mateusz 		ctx->cb(dev, ctx->cb_ctx, status);
2057ff28519SKozlowski Mateusz 	}
2067ff28519SKozlowski Mateusz }
2077ff28519SKozlowski Mateusz 
2087ff28519SKozlowski Mateusz int
2097ff28519SKozlowski Mateusz ftl_layout_verify(struct spdk_ftl_dev *dev)
2107ff28519SKozlowski Mateusz {
2117ff28519SKozlowski Mateusz 	struct ftl_layout *layout = &dev->layout;
2127ff28519SKozlowski Mateusz 	struct ftl_layout_upgrade_ctx ctx = {0};
2138fc78fd8SMateusz Kozlowski 	enum ftl_layout_region_type reg_type;
2147ff28519SKozlowski Mateusz 
2158fc78fd8SMateusz Kozlowski 	/**
2168fc78fd8SMateusz Kozlowski 	 * Upon SB upgrade some MD regions may be missing in the MD layout blob - e.g. v3 to v5, FTL_LAYOUT_REGION_TYPE_DATA_BASE.
2178fc78fd8SMateusz Kozlowski 	 * The regions couldn't have be added in the SB upgrade path, as the FTL layout wasn't initialized at that point.
2188fc78fd8SMateusz Kozlowski 	 * Now that the FTL layout is initialized, add the missing regions and store the MD layout blob again.
2198fc78fd8SMateusz Kozlowski 	 */
2207ff28519SKozlowski Mateusz 
2217ff28519SKozlowski Mateusz 	if (ftl_validate_regions(dev, layout)) {
2227ff28519SKozlowski Mateusz 		return -1;
2237ff28519SKozlowski Mateusz 	}
2247ff28519SKozlowski Mateusz 
2258fc78fd8SMateusz Kozlowski 	for (reg_type = 0; reg_type < FTL_LAYOUT_REGION_TYPE_MAX; reg_type++) {
2268fc78fd8SMateusz Kozlowski 		ctx.reg = ftl_layout_region_get(dev, reg_type);
2278fc78fd8SMateusz Kozlowski 		ctx.upgrade = &layout_upgrade_desc[reg_type];
2288fc78fd8SMateusz Kozlowski 		if (!ctx.reg) {
2298fc78fd8SMateusz Kozlowski 			continue;
2308fc78fd8SMateusz Kozlowski 		}
2317ff28519SKozlowski Mateusz 
2327ff28519SKozlowski Mateusz 		if (region_verify(dev, &ctx)) {
2337ff28519SKozlowski Mateusz 			return -1;
2347ff28519SKozlowski Mateusz 		}
2357ff28519SKozlowski Mateusz 	}
2367ff28519SKozlowski Mateusz 
2378fc78fd8SMateusz Kozlowski 	return 0;
2387ff28519SKozlowski Mateusz }
2397ff28519SKozlowski Mateusz 
2407ff28519SKozlowski Mateusz int
2417ff28519SKozlowski Mateusz ftl_upgrade_layout_dump(struct spdk_ftl_dev *dev)
2427ff28519SKozlowski Mateusz {
2437ff28519SKozlowski Mateusz 	if (ftl_validate_regions(dev, &dev->layout)) {
2447ff28519SKozlowski Mateusz 		return -1;
2457ff28519SKozlowski Mateusz 	}
2467ff28519SKozlowski Mateusz 
2477ff28519SKozlowski Mateusz 	ftl_layout_dump(dev);
2487ff28519SKozlowski Mateusz 	ftl_superblock_md_layout_dump(dev);
2497ff28519SKozlowski Mateusz 	return 0;
2507ff28519SKozlowski Mateusz }
2517ff28519SKozlowski Mateusz 
2527ff28519SKozlowski Mateusz int
2537ff28519SKozlowski Mateusz ftl_superblock_upgrade(struct spdk_ftl_dev *dev)
2547ff28519SKozlowski Mateusz {
2557ff28519SKozlowski Mateusz 	struct ftl_layout_upgrade_ctx ctx = {0};
25630ef80cdSMateusz Kozlowski 	struct ftl_layout_region *reg = ftl_layout_region_get(dev, FTL_LAYOUT_REGION_TYPE_SB);
2577ff28519SKozlowski Mateusz 	int rc;
2587ff28519SKozlowski Mateusz 
2597ff28519SKozlowski Mateusz 	ctx.reg = reg;
2607ff28519SKozlowski Mateusz 	ctx.upgrade = &layout_upgrade_desc[FTL_LAYOUT_REGION_TYPE_SB];
2618fc78fd8SMateusz Kozlowski 	reg->current.version = dev->sb->header.version;
2627ff28519SKozlowski Mateusz 
2637ff28519SKozlowski Mateusz 	rc = region_verify(dev, &ctx);
2647ff28519SKozlowski Mateusz 	if (rc) {
2657ff28519SKozlowski Mateusz 		return rc;
2667ff28519SKozlowski Mateusz 	}
2677ff28519SKozlowski Mateusz 
2688fc78fd8SMateusz Kozlowski 	while (reg->current.version < ctx.upgrade->latest_ver) {
2697ff28519SKozlowski Mateusz 		rc = ftl_region_upgrade(dev, &ctx);
2707ff28519SKozlowski Mateusz 		if (rc) {
2717ff28519SKozlowski Mateusz 			return rc;
2727ff28519SKozlowski Mateusz 		}
2737ff28519SKozlowski Mateusz 		/* SB upgrades are all synchronous */
2748fc78fd8SMateusz Kozlowski 		ftl_region_upgrade_completed(dev, &ctx, 0, 0, rc);
2757ff28519SKozlowski Mateusz 	}
2767ff28519SKozlowski Mateusz 
2778fc78fd8SMateusz Kozlowski 	/* The mirror shares the same DMA buf, so it is automatically updated upon SB store */
2788fc78fd8SMateusz Kozlowski 	dev->layout.region[FTL_LAYOUT_REGION_TYPE_SB_BASE].current.version = reg->current.version;
2797ff28519SKozlowski Mateusz 	return 0;
2807ff28519SKozlowski Mateusz }
2817ff28519SKozlowski Mateusz 
2827ff28519SKozlowski Mateusz static int
2837ff28519SKozlowski Mateusz layout_upgrade_select_next_region(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *ctx)
2847ff28519SKozlowski Mateusz {
2857ff28519SKozlowski Mateusz 	struct ftl_layout_region *reg;
2868fc78fd8SMateusz Kozlowski 	uint64_t reg_ver, reg_latest_ver;
2877ff28519SKozlowski Mateusz 	uint32_t reg_type = ctx->reg->type;
2887ff28519SKozlowski Mateusz 
2897ff28519SKozlowski Mateusz 	while (reg_type != FTL_LAYOUT_REGION_TYPE_MAX) {
2907ff28519SKozlowski Mateusz 		assert(ctx->reg);
2917ff28519SKozlowski Mateusz 		assert(ctx->upgrade);
2927ff28519SKozlowski Mateusz 		reg = ctx->reg;
2938fc78fd8SMateusz Kozlowski 		reg_latest_ver = ctx->upgrade->latest_ver;
2948fc78fd8SMateusz Kozlowski 		reg_ver = reg->current.version;
2957ff28519SKozlowski Mateusz 
2968fc78fd8SMateusz Kozlowski 		if (reg_ver == reg_latest_ver || reg->type == FTL_LAYOUT_REGION_TYPE_INVALID) {
2977ff28519SKozlowski Mateusz 			/* select the next region to upgrade */
2987ff28519SKozlowski Mateusz 			reg_type++;
2997ff28519SKozlowski Mateusz 			if (reg_type == FTL_LAYOUT_REGION_TYPE_MAX) {
3007ff28519SKozlowski Mateusz 				break;
3017ff28519SKozlowski Mateusz 			}
3027ff28519SKozlowski Mateusz 			ctx->reg++;
3037ff28519SKozlowski Mateusz 			ctx->upgrade++;
3048fc78fd8SMateusz Kozlowski 		} else if (reg_ver < reg_latest_ver) {
3058fc78fd8SMateusz Kozlowski 			/* qualify region version to upgrade */
3068fc78fd8SMateusz Kozlowski 			return FTL_LAYOUT_UPGRADE_CONTINUE;
3077ff28519SKozlowski Mateusz 		} else {
3087ff28519SKozlowski Mateusz 			/* unknown version */
3098fc78fd8SMateusz Kozlowski 			assert(reg_ver <= reg_latest_ver);
3107ff28519SKozlowski Mateusz 			FTL_ERRLOG(dev, "Region %d upgrade fault: version %"PRIu64"/%"PRIu64"\n", reg_type, reg_ver,
3118fc78fd8SMateusz Kozlowski 				   reg_latest_ver);
3127ff28519SKozlowski Mateusz 			return FTL_LAYOUT_UPGRADE_FAULT;
3137ff28519SKozlowski Mateusz 		}
3147ff28519SKozlowski Mateusz 	}
3157ff28519SKozlowski Mateusz 
3167ff28519SKozlowski Mateusz 	return FTL_LAYOUT_UPGRADE_DONE;
3177ff28519SKozlowski Mateusz }
3187ff28519SKozlowski Mateusz 
3197ff28519SKozlowski Mateusz int
3207ff28519SKozlowski Mateusz ftl_layout_upgrade_init_ctx(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *ctx)
3217ff28519SKozlowski Mateusz {
3227ff28519SKozlowski Mateusz 	if (!ctx->reg) {
32330ef80cdSMateusz Kozlowski 		ctx->reg = ftl_layout_region_get(dev, 0);
3247ff28519SKozlowski Mateusz 		ctx->upgrade = &layout_upgrade_desc[0];
325f34b13ecSNathan Claudel 		SPDK_STATIC_ASSERT(FTL_LAYOUT_REGION_TYPE_SB == 0, "Invalid SB region type");
3267ff28519SKozlowski Mateusz 	}
3277ff28519SKozlowski Mateusz 
3287ff28519SKozlowski Mateusz 	return layout_upgrade_select_next_region(dev, ctx);
3297ff28519SKozlowski Mateusz }
3308fc78fd8SMateusz Kozlowski 
3318fc78fd8SMateusz Kozlowski uint64_t
3328fc78fd8SMateusz Kozlowski ftl_layout_upgrade_region_get_latest_version(enum ftl_layout_region_type reg_type)
3338fc78fd8SMateusz Kozlowski {
3348fc78fd8SMateusz Kozlowski 	assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX);
3358fc78fd8SMateusz Kozlowski 	return layout_upgrade_desc[reg_type].latest_ver;
3368fc78fd8SMateusz Kozlowski }
337a5c04e6dSMateusz Kozlowski 
3385555d51cSLukasz Lasek int
3395555d51cSLukasz Lasek ftl_layout_upgrade_drop_region(struct spdk_ftl_dev *dev,
3405555d51cSLukasz Lasek 			       struct ftl_layout_tracker_bdev *layout_tracker,
341a5c04e6dSMateusz Kozlowski 			       enum ftl_layout_region_type reg_type, uint32_t reg_ver)
342a5c04e6dSMateusz Kozlowski {
343a5c04e6dSMateusz Kozlowski 	const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL;
344a5c04e6dSMateusz Kozlowski 	int rc = ftl_layout_tracker_bdev_rm_region(layout_tracker, reg_type, reg_ver);
345a5c04e6dSMateusz Kozlowski 
346a5c04e6dSMateusz Kozlowski 	ftl_layout_tracker_bdev_find_next_region(layout_tracker, reg_type, &reg_search_ctx);
347a5c04e6dSMateusz Kozlowski 	if (reg_search_ctx) {
348a5c04e6dSMateusz Kozlowski 		FTL_ERRLOG(dev,
349a5c04e6dSMateusz Kozlowski 			   "Error when dropping region type %"PRId32", ver %"PRIu32": rc:%"PRId32" but found reg ver %"PRIu32"\n",
350a5c04e6dSMateusz Kozlowski 			   reg_type, reg_ver, rc, reg_search_ctx->ver);
351a5c04e6dSMateusz Kozlowski 		return -1;
352a5c04e6dSMateusz Kozlowski 	}
353a5c04e6dSMateusz Kozlowski 	dev->layout.region[reg_type].type = FTL_LAYOUT_REGION_TYPE_INVALID;
354a5c04e6dSMateusz Kozlowski 	return 0;
355a5c04e6dSMateusz Kozlowski }
356