blob: edebf741fd2d57861c00b8cff9093fa1902bc4c8 [file] [log] [blame]
Qu Wenruo565a4142020-06-24 18:02:48 +02001// SPDX-License-Identifier: GPL-2.0+
2#include <common.h>
3#include <fs_internal.h>
Qu Wenruo4aebb992020-06-24 18:02:49 +02004#include <uuid.h>
5#include <memalign.h>
6#include "kernel-shared/btrfs_tree.h"
Qu Wenruo565a4142020-06-24 18:02:48 +02007#include "disk-io.h"
Qu Wenruo4aebb992020-06-24 18:02:49 +02008#include "ctree.h"
9#include "btrfs.h"
Qu Wenruo565a4142020-06-24 18:02:48 +020010#include "crypto/hash.h"
11
12int btrfs_csum_data(u16 csum_type, const u8 *data, u8 *out, size_t len)
13{
14 memset(out, 0, BTRFS_CSUM_SIZE);
15
16 switch (csum_type) {
17 case BTRFS_CSUM_TYPE_CRC32:
18 return hash_crc32c(data, len, out);
19 case BTRFS_CSUM_TYPE_XXHASH:
20 return hash_xxhash(data, len, out);
21 case BTRFS_CSUM_TYPE_SHA256:
22 return hash_sha256(data, len, out);
23 default:
24 printf("Unknown csum type %d\n", csum_type);
25 return -EINVAL;
26 }
27}
Qu Wenruo4aebb992020-06-24 18:02:49 +020028
29/*
30 * Check if the super is valid:
31 * - nodesize/sectorsize - minimum, maximum, alignment
32 * - tree block starts - alignment
33 * - number of devices - something sane
34 * - sys array size - maximum
35 */
36static int btrfs_check_super(struct btrfs_super_block *sb)
37{
38 u8 result[BTRFS_CSUM_SIZE];
39 u16 csum_type;
40 int csum_size;
41 u8 *metadata_uuid;
42
43 if (btrfs_super_magic(sb) != BTRFS_MAGIC)
44 return -EIO;
45
46 csum_type = btrfs_super_csum_type(sb);
47 if (csum_type >= btrfs_super_num_csums()) {
48 error("unsupported checksum algorithm %u", csum_type);
49 return -EIO;
50 }
51 csum_size = btrfs_super_csum_size(sb);
52
53 btrfs_csum_data(csum_type, (u8 *)sb + BTRFS_CSUM_SIZE,
54 result, BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
55
56 if (memcmp(result, sb->csum, csum_size)) {
57 error("superblock checksum mismatch");
58 return -EIO;
59 }
60 if (btrfs_super_root_level(sb) >= BTRFS_MAX_LEVEL) {
61 error("tree_root level too big: %d >= %d",
62 btrfs_super_root_level(sb), BTRFS_MAX_LEVEL);
63 goto error_out;
64 }
65 if (btrfs_super_chunk_root_level(sb) >= BTRFS_MAX_LEVEL) {
66 error("chunk_root level too big: %d >= %d",
67 btrfs_super_chunk_root_level(sb), BTRFS_MAX_LEVEL);
68 goto error_out;
69 }
70 if (btrfs_super_log_root_level(sb) >= BTRFS_MAX_LEVEL) {
71 error("log_root level too big: %d >= %d",
72 btrfs_super_log_root_level(sb), BTRFS_MAX_LEVEL);
73 goto error_out;
74 }
75
76 if (!IS_ALIGNED(btrfs_super_root(sb), 4096)) {
77 error("tree_root block unaligned: %llu", btrfs_super_root(sb));
78 goto error_out;
79 }
80 if (!IS_ALIGNED(btrfs_super_chunk_root(sb), 4096)) {
81 error("chunk_root block unaligned: %llu",
82 btrfs_super_chunk_root(sb));
83 goto error_out;
84 }
85 if (!IS_ALIGNED(btrfs_super_log_root(sb), 4096)) {
86 error("log_root block unaligned: %llu",
87 btrfs_super_log_root(sb));
88 goto error_out;
89 }
90 if (btrfs_super_nodesize(sb) < 4096) {
91 error("nodesize too small: %u < 4096",
92 btrfs_super_nodesize(sb));
93 goto error_out;
94 }
95 if (!IS_ALIGNED(btrfs_super_nodesize(sb), 4096)) {
96 error("nodesize unaligned: %u", btrfs_super_nodesize(sb));
97 goto error_out;
98 }
99 if (btrfs_super_sectorsize(sb) < 4096) {
100 error("sectorsize too small: %u < 4096",
101 btrfs_super_sectorsize(sb));
102 goto error_out;
103 }
104 if (!IS_ALIGNED(btrfs_super_sectorsize(sb), 4096)) {
105 error("sectorsize unaligned: %u", btrfs_super_sectorsize(sb));
106 goto error_out;
107 }
108 if (btrfs_super_total_bytes(sb) == 0) {
109 error("invalid total_bytes 0");
110 goto error_out;
111 }
112 if (btrfs_super_bytes_used(sb) < 6 * btrfs_super_nodesize(sb)) {
113 error("invalid bytes_used %llu", btrfs_super_bytes_used(sb));
114 goto error_out;
115 }
116 if ((btrfs_super_stripesize(sb) != 4096)
117 && (btrfs_super_stripesize(sb) != btrfs_super_sectorsize(sb))) {
118 error("invalid stripesize %u", btrfs_super_stripesize(sb));
119 goto error_out;
120 }
121
122 if (btrfs_super_incompat_flags(sb) & BTRFS_FEATURE_INCOMPAT_METADATA_UUID)
123 metadata_uuid = sb->metadata_uuid;
124 else
125 metadata_uuid = sb->fsid;
126
127 if (memcmp(metadata_uuid, sb->dev_item.fsid, BTRFS_FSID_SIZE) != 0) {
128 char fsid[BTRFS_UUID_UNPARSED_SIZE];
129 char dev_fsid[BTRFS_UUID_UNPARSED_SIZE];
130
131 uuid_unparse(sb->metadata_uuid, fsid);
132 uuid_unparse(sb->dev_item.fsid, dev_fsid);
133 error("dev_item UUID does not match fsid: %s != %s",
134 dev_fsid, fsid);
135 goto error_out;
136 }
137
138 /*
139 * Hint to catch really bogus numbers, bitflips or so
140 */
141 if (btrfs_super_num_devices(sb) > (1UL << 31)) {
142 error("suspicious number of devices: %llu",
143 btrfs_super_num_devices(sb));
144 }
145
146 if (btrfs_super_num_devices(sb) == 0) {
147 error("number of devices is 0");
148 goto error_out;
149 }
150
151 /*
152 * Obvious sys_chunk_array corruptions, it must hold at least one key
153 * and one chunk
154 */
155 if (btrfs_super_sys_array_size(sb) > BTRFS_SYSTEM_CHUNK_ARRAY_SIZE) {
156 error("system chunk array too big %u > %u",
157 btrfs_super_sys_array_size(sb),
158 BTRFS_SYSTEM_CHUNK_ARRAY_SIZE);
159 goto error_out;
160 }
161 if (btrfs_super_sys_array_size(sb) < sizeof(struct btrfs_disk_key)
162 + sizeof(struct btrfs_chunk)) {
163 error("system chunk array too small %u < %zu",
164 btrfs_super_sys_array_size(sb),
165 sizeof(struct btrfs_disk_key) +
166 sizeof(struct btrfs_chunk));
167 goto error_out;
168 }
169
170 return 0;
171
172error_out:
173 error("superblock checksum matches but it has invalid members");
174 return -EIO;
175}
176
177/*
178 * btrfs_read_dev_super - read a valid primary superblock from a block device
179 * @desc,@part: file descriptor of the device
180 * @sb: buffer where the superblock is going to be read in
181 *
182 * Unlike the btrfs-progs/kernel version, here we ony care about the first
183 * super block, thus it's much simpler.
184 */
185int btrfs_read_dev_super(struct blk_desc *desc, struct disk_partition *part,
186 struct btrfs_super_block *sb)
187{
188 char tmp[BTRFS_SUPER_INFO_SIZE];
189 struct btrfs_super_block *buf = (struct btrfs_super_block *)tmp;
190 int ret;
191
192 ret = __btrfs_devread(desc, part, tmp, BTRFS_SUPER_INFO_SIZE,
193 BTRFS_SUPER_INFO_OFFSET);
194 if (ret < BTRFS_SUPER_INFO_SIZE)
195 return -EIO;
196
197 if (btrfs_super_bytenr(buf) != BTRFS_SUPER_INFO_OFFSET)
198 return -EIO;
199
200 if (btrfs_check_super(buf))
201 return -EIO;
202
203 memcpy(sb, buf, BTRFS_SUPER_INFO_SIZE);
204 return 0;
205}
206
207int btrfs_read_superblock(void)
208{
209 ALLOC_CACHE_ALIGN_BUFFER(char, raw_sb, BTRFS_SUPER_INFO_SIZE);
210 struct btrfs_super_block *sb = (struct btrfs_super_block *) raw_sb;
211 int ret;
212
213
214 btrfs_info.sb.generation = 0;
215
216 ret = btrfs_read_dev_super(btrfs_blk_desc, btrfs_part_info, sb);
217 if (ret < 0) {
218 pr_debug("%s: No valid BTRFS superblock found!\n", __func__);
219 return ret;
220 }
221 btrfs_super_block_to_cpu(sb);
222 memcpy(&btrfs_info.sb, sb, sizeof(*sb));
223
224 if (btrfs_info.sb.num_devices != 1) {
225 printf("%s: Unsupported number of devices (%lli). This driver "
226 "only supports filesystem on one device.\n", __func__,
227 btrfs_info.sb.num_devices);
228 return -1;
229 }
230
231 pr_debug("Chosen superblock with generation = %llu\n",
232 btrfs_info.sb.generation);
233
234 return 0;
235}