Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2022 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "ftl_sb_upgrade.h"
7 : : #include "ftl_layout_upgrade.h"
8 : : #include "ftl_layout.h"
9 : : #include "ftl_core.h"
10 : : #include "ftl_sb_v3.h"
11 : : #include "utils/ftl_df.h"
12 : : #include "utils/ftl_layout_tracker_bdev.h"
13 : :
14 : : static int
15 : 0 : sb_v4_to_v5_verify(struct spdk_ftl_dev *dev, struct ftl_layout_region *region)
16 : : {
17 : : struct ftl_layout_region *reg;
18 : : uint32_t reg_no;
19 : 0 : int rc = ftl_region_upgrade_enabled(dev, region);
20 : :
21 [ # # ]: 0 : if (rc) {
22 : 0 : return rc;
23 : : }
24 : :
25 : : /* Verify there are no pending major upgrades */
26 [ # # ]: 0 : for (reg_no = 0; reg_no < FTL_LAYOUT_REGION_TYPE_MAX; reg_no++) {
27 : 0 : reg = ftl_layout_region_get(dev, reg_no);
28 [ # # ]: 0 : if (!reg) {
29 : : /* This region does not exist */
30 : 0 : continue;
31 : : }
32 : :
33 [ # # ]: 0 : if (reg->current.version <= ftl_layout_upgrade_region_get_latest_version(reg->type)) {
34 : : /* Only latest region version found */
35 : 0 : continue;
36 : : }
37 : :
38 : : /* Previous version found, major upgrade */
39 [ # # ]: 0 : FTL_WARNLOG(dev, "FTL superblock upgrade v4 to v5 disabled: " \
40 : : "cannot upgrade region type 0x%"PRIx32" v%"PRId64" to v%"PRId64", " \
41 : : "offs 0x%"PRIx64", blks 0x%"PRIx64"\n",
42 : : reg->type, reg->current.version, ftl_layout_upgrade_region_get_latest_version(reg->type),
43 : : reg->current.offset, reg->current.blocks);
44 : 0 : return -1;
45 : : }
46 : :
47 : 0 : return 0;
48 : : }
49 : :
50 : : static bool
51 : 0 : sb_v3_md_region_is_fixed(int reg_type)
52 : : {
53 [ # # ]: 0 : switch (reg_type) {
54 : 0 : case FTL_LAYOUT_REGION_TYPE_SB:
55 : : case FTL_LAYOUT_REGION_TYPE_SB_BASE:
56 : : case FTL_LAYOUT_REGION_TYPE_DATA_BASE:
57 : 0 : return true;
58 : :
59 : 0 : default:
60 : 0 : return false;
61 : : }
62 : : }
63 : :
64 : : static bool
65 : 432 : sb_v3_md_region_is_nvc(int reg_type)
66 : : {
67 [ + + ]: 432 : switch (reg_type) {
68 : 72 : case FTL_LAYOUT_REGION_TYPE_SB_BASE:
69 : : case FTL_LAYOUT_REGION_TYPE_VALID_MAP:
70 : : case FTL_LAYOUT_REGION_TYPE_DATA_BASE:
71 : 72 : return false;
72 : :
73 : 360 : default:
74 : 360 : return true;
75 : : }
76 : : }
77 : :
78 : : static int
79 : 0 : sb_v3_md_layout_convert(struct spdk_ftl_dev *dev)
80 : : {
81 : 0 : struct ftl_superblock_v3 *sb = (struct ftl_superblock_v3 *)dev->sb;
82 : 0 : struct ftl_superblock_v3_md_region *sb_reg = &sb->md_layout_head;
83 : : const struct ftl_layout_tracker_bdev_region_props *reg_props;
84 : :
85 [ # # ]: 0 : while (sb_reg->type != FTL_LAYOUT_REGION_TYPE_INVALID) {
86 [ # # ]: 0 : if (sb_reg->type == FTL_LAYOUT_REGION_TYPE_FREE_NVC ||
87 [ # # ]: 0 : sb_reg->type == FTL_LAYOUT_REGION_TYPE_FREE_BASE) {
88 : 0 : goto next_sb_reg;
89 : : }
90 : :
91 [ # # ]: 0 : if (sb_reg->type >= FTL_LAYOUT_REGION_TYPE_MAX) {
92 [ # # ]: 0 : FTL_ERRLOG(dev, "Invalid MD region type found\n");
93 : 0 : return -1;
94 : : }
95 : :
96 [ # # ]: 0 : if (sb_v3_md_region_is_fixed(sb_reg->type)) {
97 [ # # ]: 0 : FTL_ERRLOG(dev, "Unsupported MD region type found\n");
98 : 0 : return -1;
99 : : }
100 : :
101 [ # # ]: 0 : if (sb_v3_md_region_is_nvc(sb_reg->type)) {
102 : 0 : reg_props = ftl_layout_tracker_bdev_insert_region(dev->nvc_layout_tracker, sb_reg->type,
103 : : sb_reg->version, sb_reg->blk_offs, sb_reg->blk_sz);
104 : : } else {
105 : 0 : reg_props = ftl_layout_tracker_bdev_insert_region(dev->base_layout_tracker, sb_reg->type,
106 : : sb_reg->version, sb_reg->blk_offs, sb_reg->blk_sz);
107 : : }
108 [ # # ]: 0 : if (!reg_props) {
109 [ # # ]: 0 : FTL_ERRLOG(dev, "Cannot upgrade SB MD layout - region type 0x%"PRIx32" v%"PRId32" " \
110 : : "offs 0x%"PRIx64" blks 0x%"PRIx64"\n",
111 : : sb_reg->type, sb_reg->version, sb_reg->blk_offs, sb_reg->blk_sz);
112 : : }
113 : :
114 : 0 : next_sb_reg:
115 [ # # ]: 0 : if (sb_reg->df_next == FTL_DF_OBJ_ID_INVALID) {
116 : 0 : break;
117 : : }
118 : :
119 [ # # ]: 0 : if (UINT64_MAX - (uintptr_t)sb <= sb_reg->df_next) {
120 [ # # ]: 0 : FTL_ERRLOG(dev, "Buffer overflow\n");
121 : 0 : return -EOVERFLOW;
122 : : }
123 : :
124 : 0 : sb_reg = ftl_df_get_obj_ptr(sb, sb_reg->df_next);
125 [ # # ]: 0 : if (ftl_superblock_v3_md_region_overflow(dev, sb_reg)) {
126 [ # # ]: 0 : FTL_ERRLOG(dev, "Buffer overflow\n");
127 : 0 : return -EOVERFLOW;
128 : : }
129 : : }
130 : :
131 : 0 : return 0;
132 : : }
133 : :
134 : : static int
135 : 0 : sb_v4_to_v5_upgrade(struct spdk_ftl_dev *dev, struct ftl_layout_upgrade_ctx *ctx)
136 : : {
137 : 0 : union ftl_superblock_ver *sb = (union ftl_superblock_ver *)dev->sb;
138 : :
139 [ # # ]: 0 : FTL_NOTICELOG(dev, "FTL superblock upgrade v4 to v5\n");
140 : :
141 : : /* Convert v3 MD layout */
142 [ # # ]: 0 : if (ftl_superblock_is_blob_area_empty(dev->sb)) {
143 [ # # ]: 0 : FTL_ERRLOG(dev, "SBv3 MD layout empty\n");
144 : 0 : return -1;
145 : : }
146 [ # # ]: 0 : if (sb_v3_md_layout_convert(dev)) {
147 [ # # ]: 0 : FTL_ERRLOG(dev, "SBv3 MD layout load failed\n");
148 : 0 : return -1;
149 : : }
150 : :
151 : : /* Bump up the version */
152 : 0 : sb->v5.header.version = FTL_SB_VERSION_5;
153 : 0 : sb->v5.blob_area_end = 0;
154 : :
155 : : /* Keep v5 layout empty */
156 [ # # ]: 0 : memset(sb->v5.nvc_dev_name, 0, sizeof(sb->v5.nvc_dev_name));
157 [ # # ]: 0 : memset(&sb->v5.md_layout_nvc, 0, sizeof(sb->v5.md_layout_nvc));
158 [ # # ]: 0 : memset(sb->v5.base_dev_name, 0, sizeof(sb->v5.base_dev_name));
159 [ # # ]: 0 : memset(&sb->v5.md_layout_base, 0, sizeof(sb->v5.md_layout_base));
160 [ # # ]: 0 : memset(&sb->v5.layout_params, 0, sizeof(sb->v5.layout_params));
161 : :
162 : 0 : return 0;
163 : : }
164 : :
165 : : struct ftl_region_upgrade_desc sb_upgrade_desc[] = {
166 : : [FTL_SB_VERSION_0] = {.verify = ftl_region_upgrade_disabled},
167 : : [FTL_SB_VERSION_1] = {.verify = ftl_region_upgrade_disabled},
168 : : [FTL_SB_VERSION_2] = {.verify = ftl_region_upgrade_disabled},
169 : : [FTL_SB_VERSION_3] = {.verify = ftl_region_upgrade_disabled},
170 : : [FTL_SB_VERSION_4] = {.verify = sb_v4_to_v5_verify, .upgrade = sb_v4_to_v5_upgrade, .new_version = FTL_SB_VERSION_5},
171 : : };
172 : :
173 : : SPDK_STATIC_ASSERT(SPDK_COUNTOF(sb_upgrade_desc) == FTL_SB_VERSION_CURRENT,
174 : : "Missing SB region upgrade descriptors");
|