xref: /spdk/lib/ftl/ftl_sb.c (revision b02581a89058ebaebe03bd0e16e3b58adfe406c1)
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_sb.h"
8 #include "ftl_core.h"
9 #include "ftl_layout.h"
10 #include "upgrade/ftl_sb_upgrade.h"
11 #include "upgrade/ftl_sb_v3.h"
12 #include "upgrade/ftl_sb_v5.h"
13 
14 static bool ftl_superblock_v2_check_magic(union ftl_superblock_ver *sb_ver);
15 
16 struct sb_ops {
17 	bool (*check_magic)(union ftl_superblock_ver *sb_ver);
18 
19 	bool (*blob_is_empty)(union ftl_superblock_ver *sb_ver);
20 	bool (*blob_validate)(struct spdk_ftl_dev *dev);
21 	int (*blob_store)(struct spdk_ftl_dev *dev);
22 	int (*blob_load)(struct spdk_ftl_dev *dev);
23 
24 	int (*upgrade_region)(struct spdk_ftl_dev *dev, struct ftl_layout_region *reg,
25 			      uint32_t new_version);
26 
27 	int (*layout_apply)(struct spdk_ftl_dev *dev);
28 	void (*layout_dump)(struct spdk_ftl_dev *dev);
29 };
30 
31 static struct sb_ops *
32 sb_get_ops(uint64_t version)
33 {
34 	static struct sb_ops ops[] = {
35 		[FTL_SB_VERSION_0] = {
36 			.check_magic = ftl_superblock_v2_check_magic,
37 		},
38 		[FTL_SB_VERSION_1] = {
39 			.check_magic = ftl_superblock_v2_check_magic,
40 		},
41 		[FTL_SB_VERSION_2] = {
42 			.check_magic = ftl_superblock_v2_check_magic,
43 		},
44 		[FTL_SB_VERSION_3] = {
45 			.check_magic = ftl_superblock_v3_check_magic,
46 			.blob_is_empty = ftl_superblock_v3_md_layout_is_empty,
47 			.blob_load = ftl_superblock_v3_md_layout_load_all,
48 			.layout_dump = ftl_superblock_v3_md_layout_dump,
49 		},
50 		[FTL_SB_VERSION_4] = {
51 			.check_magic = ftl_superblock_v3_check_magic,
52 			.blob_is_empty = ftl_superblock_v3_md_layout_is_empty,
53 			.blob_load = ftl_superblock_v3_md_layout_load_all,
54 			.layout_dump = ftl_superblock_v3_md_layout_dump,
55 		},
56 		[FTL_SB_VERSION_5] = {
57 			.check_magic = ftl_superblock_v3_check_magic,
58 			.blob_is_empty = ftl_superblock_v5_is_blob_area_empty,
59 			.blob_validate = ftl_superblock_v5_validate_blob_area,
60 			.blob_store = ftl_superblock_v5_store_blob_area,
61 			.blob_load = ftl_superblock_v5_load_blob_area,
62 			.upgrade_region = ftl_superblock_v5_md_layout_upgrade_region,
63 			.layout_apply = ftl_superblock_v5_md_layout_apply,
64 			.layout_dump = ftl_superblock_v5_md_layout_dump,
65 		},
66 	};
67 
68 	if (version >= SPDK_COUNTOF(ops)) {
69 		return NULL;
70 	}
71 
72 	return &ops[version];
73 }
74 
75 static bool
76 ftl_superblock_v2_check_magic(union ftl_superblock_ver *sb_ver)
77 {
78 	return sb_ver->header.magic == FTL_SUPERBLOCK_MAGIC_V2;
79 }
80 
81 bool
82 ftl_superblock_check_magic(struct ftl_superblock *sb)
83 {
84 	union ftl_superblock_ver *sb_ver = (union ftl_superblock_ver *)sb;
85 	struct sb_ops *ops = sb_get_ops(sb_ver->header.version);
86 
87 	if (!ops || !ops->check_magic) {
88 		ftl_abort();
89 		return false;
90 	}
91 	return ops->check_magic(sb_ver);
92 }
93 
94 bool
95 ftl_superblock_is_blob_area_empty(struct ftl_superblock *sb)
96 {
97 	union ftl_superblock_ver *sb_ver = (union ftl_superblock_ver *)sb;
98 	struct sb_ops *ops = sb_get_ops(sb_ver->header.version);
99 
100 	if (!ops || !ops->blob_is_empty) {
101 		ftl_abort();
102 		return false;
103 	}
104 	return ops->blob_is_empty(sb_ver);
105 }
106 
107 bool
108 ftl_superblock_validate_blob_area(struct spdk_ftl_dev *dev)
109 {
110 	struct sb_ops *ops = sb_get_ops(dev->sb->header.version);
111 
112 	if (!ops || !ops->blob_validate) {
113 		return true;
114 	}
115 	return ops->blob_validate(dev);
116 }
117 
118 int
119 ftl_superblock_store_blob_area(struct spdk_ftl_dev *dev)
120 {
121 	struct sb_ops *ops = sb_get_ops(dev->sb->header.version);
122 
123 	if (!ops || !ops->blob_store) {
124 		ftl_abort();
125 		return -1;
126 	}
127 	return ops->blob_store(dev);
128 }
129 
130 int
131 ftl_superblock_load_blob_area(struct spdk_ftl_dev *dev)
132 {
133 	struct sb_ops *ops = sb_get_ops(dev->sb->header.version);
134 
135 	if (!ops || !ops->blob_load) {
136 		ftl_abort();
137 		return -1;
138 	}
139 	return ops->blob_load(dev);
140 }
141 
142 int
143 ftl_superblock_md_layout_upgrade_region(struct spdk_ftl_dev *dev,
144 					struct ftl_layout_region *reg, uint32_t new_version)
145 {
146 	struct sb_ops *ops = sb_get_ops(dev->sb->header.version);
147 
148 	if (!ops || !ops->upgrade_region) {
149 		ftl_abort();
150 		return -1;
151 	}
152 	return ops->upgrade_region(dev, reg, new_version);
153 }
154 
155 int
156 ftl_superblock_md_layout_apply(struct spdk_ftl_dev *dev)
157 {
158 	struct sb_ops *ops = sb_get_ops(dev->sb->header.version);
159 
160 	if (!ops || !ops->layout_apply) {
161 		return 0;
162 	}
163 	return ops->layout_apply(dev);
164 }
165 
166 void
167 ftl_superblock_md_layout_dump(struct spdk_ftl_dev *dev)
168 {
169 	struct sb_ops *ops = sb_get_ops(dev->sb->header.version);
170 
171 	if (!ops || !ops->layout_dump) {
172 		ftl_abort();
173 		return;
174 	}
175 	return ops->layout_dump(dev);
176 }
177