1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <linux/crc32.h>
4 #include "messages.h"
5 #include "fs.h"
6 #include "accessors.h"
7 #include "volumes.h"
8
9 static const struct btrfs_csums {
10 u16 size;
11 const char name[10];
12 } btrfs_csums[] = {
13 [BTRFS_CSUM_TYPE_CRC32] = { .size = 4, .name = "crc32c" },
14 [BTRFS_CSUM_TYPE_XXHASH] = { .size = 8, .name = "xxhash64" },
15 [BTRFS_CSUM_TYPE_SHA256] = { .size = 32, .name = "sha256" },
16 [BTRFS_CSUM_TYPE_BLAKE2] = { .size = 32, .name = "blake2b" },
17 };
18
19 /* This exists for btrfs-progs usages. */
btrfs_csum_type_size(u16 type)20 u16 btrfs_csum_type_size(u16 type)
21 {
22 return btrfs_csums[type].size;
23 }
24
btrfs_super_csum_size(const struct btrfs_super_block * s)25 int btrfs_super_csum_size(const struct btrfs_super_block *s)
26 {
27 u16 t = btrfs_super_csum_type(s);
28
29 /* csum type is validated at mount time. */
30 return btrfs_csum_type_size(t);
31 }
32
btrfs_super_csum_name(u16 csum_type)33 const char *btrfs_super_csum_name(u16 csum_type)
34 {
35 /* csum type is validated at mount time. */
36 return btrfs_csums[csum_type].name;
37 }
38
btrfs_get_num_csums(void)39 size_t __attribute_const__ btrfs_get_num_csums(void)
40 {
41 return ARRAY_SIZE(btrfs_csums);
42 }
43
btrfs_csum(u16 csum_type,const u8 * data,size_t len,u8 * out)44 void btrfs_csum(u16 csum_type, const u8 *data, size_t len, u8 *out)
45 {
46 switch (csum_type) {
47 case BTRFS_CSUM_TYPE_CRC32:
48 put_unaligned_le32(~crc32c(~0, data, len), out);
49 break;
50 case BTRFS_CSUM_TYPE_XXHASH:
51 put_unaligned_le64(xxh64(data, len, 0), out);
52 break;
53 case BTRFS_CSUM_TYPE_SHA256:
54 sha256(data, len, out);
55 break;
56 case BTRFS_CSUM_TYPE_BLAKE2:
57 blake2b(NULL, 0, data, len, out, 32);
58 break;
59 default:
60 /* Checksum type is validated at mount time. */
61 BUG();
62 }
63 }
64
btrfs_csum_init(struct btrfs_csum_ctx * ctx,u16 csum_type)65 void btrfs_csum_init(struct btrfs_csum_ctx *ctx, u16 csum_type)
66 {
67 ctx->csum_type = csum_type;
68 switch (ctx->csum_type) {
69 case BTRFS_CSUM_TYPE_CRC32:
70 ctx->crc32 = ~0;
71 break;
72 case BTRFS_CSUM_TYPE_XXHASH:
73 xxh64_reset(&ctx->xxh64, 0);
74 break;
75 case BTRFS_CSUM_TYPE_SHA256:
76 sha256_init(&ctx->sha256);
77 break;
78 case BTRFS_CSUM_TYPE_BLAKE2:
79 blake2b_init(&ctx->blake2b, 32);
80 break;
81 default:
82 /* Checksume type is validated at mount time. */
83 BUG();
84 }
85 }
86
btrfs_csum_update(struct btrfs_csum_ctx * ctx,const u8 * data,size_t len)87 void btrfs_csum_update(struct btrfs_csum_ctx *ctx, const u8 *data, size_t len)
88 {
89 switch (ctx->csum_type) {
90 case BTRFS_CSUM_TYPE_CRC32:
91 ctx->crc32 = crc32c(ctx->crc32, data, len);
92 break;
93 case BTRFS_CSUM_TYPE_XXHASH:
94 xxh64_update(&ctx->xxh64, data, len);
95 break;
96 case BTRFS_CSUM_TYPE_SHA256:
97 sha256_update(&ctx->sha256, data, len);
98 break;
99 case BTRFS_CSUM_TYPE_BLAKE2:
100 blake2b_update(&ctx->blake2b, data, len);
101 break;
102 default:
103 /* Checksum type is validated at mount time. */
104 BUG();
105 }
106 }
107
btrfs_csum_final(struct btrfs_csum_ctx * ctx,u8 * out)108 void btrfs_csum_final(struct btrfs_csum_ctx *ctx, u8 *out)
109 {
110 switch (ctx->csum_type) {
111 case BTRFS_CSUM_TYPE_CRC32:
112 put_unaligned_le32(~ctx->crc32, out);
113 break;
114 case BTRFS_CSUM_TYPE_XXHASH:
115 put_unaligned_le64(xxh64_digest(&ctx->xxh64), out);
116 break;
117 case BTRFS_CSUM_TYPE_SHA256:
118 sha256_final(&ctx->sha256, out);
119 break;
120 case BTRFS_CSUM_TYPE_BLAKE2:
121 blake2b_final(&ctx->blake2b, out);
122 break;
123 default:
124 /* Checksum type is validated at mount time. */
125 BUG();
126 }
127 }
128
129 /*
130 * For regular builds, any block size <= page size is supported.
131 * For experimental builds, any block size between BTRFS_MIN_BLOCKSIZE
132 * and BTRFS_MAX_BLOCKSIZE (inclusive) is supported.
133 */
btrfs_supported_blocksize(u32 blocksize)134 bool __attribute_const__ btrfs_supported_blocksize(u32 blocksize)
135 {
136 /* @blocksize should be validated first. */
137 ASSERT(is_power_of_2(blocksize) && blocksize >= BTRFS_MIN_BLOCKSIZE &&
138 blocksize <= BTRFS_MAX_BLOCKSIZE);
139
140 if (blocksize <= PAGE_SIZE)
141 return true;
142 #ifdef CONFIG_BTRFS_EXPERIMENTAL
143 /*
144 * For bs > ps support it's done by specifying a minimal folio order
145 * for filemap, thus implying large data folios.
146 * For HIGHMEM systems, we can not always access the content of a (large)
147 * folio in one go, but go through them page by page.
148 *
149 * A lot of features don't implement a proper PAGE sized loop for large
150 * folios, this includes:
151 *
152 * - compression
153 * - verity
154 * - encoded write
155 *
156 * Considering HIGHMEM is such a pain to deal with and it's going
157 * to be deprecated eventually, just reject HIGHMEM && bs > ps cases.
158 *
159 * Finally, for bs > ps cases, we need to set the minimal folio order,
160 * which requires transparent hugepage.
161 */
162 if (blocksize > PAGE_SIZE) {
163 if (IS_ENABLED(CONFIG_HIGHMEM))
164 return false;
165
166 if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
167 return false;
168 }
169 return true;
170 #endif
171 return false;
172 }
173
174 /*
175 * Start exclusive operation @type, return true on success.
176 */
btrfs_exclop_start(struct btrfs_fs_info * fs_info,enum btrfs_exclusive_operation type)177 bool btrfs_exclop_start(struct btrfs_fs_info *fs_info,
178 enum btrfs_exclusive_operation type)
179 {
180 bool ret = false;
181
182 spin_lock(&fs_info->super_lock);
183 if (fs_info->exclusive_operation == BTRFS_EXCLOP_NONE) {
184 fs_info->exclusive_operation = type;
185 ret = true;
186 }
187 spin_unlock(&fs_info->super_lock);
188
189 return ret;
190 }
191
192 /*
193 * Conditionally allow to enter the exclusive operation in case it's compatible
194 * with the running one. This must be paired with btrfs_exclop_start_unlock()
195 * and btrfs_exclop_finish().
196 *
197 * Compatibility:
198 * - the same type is already running
199 * - when trying to add a device and balance has been paused
200 * - not BTRFS_EXCLOP_NONE - this is intentionally incompatible and the caller
201 * must check the condition first that would allow none -> @type
202 */
btrfs_exclop_start_try_lock(struct btrfs_fs_info * fs_info,enum btrfs_exclusive_operation type)203 bool btrfs_exclop_start_try_lock(struct btrfs_fs_info *fs_info,
204 enum btrfs_exclusive_operation type)
205 {
206 spin_lock(&fs_info->super_lock);
207 if (fs_info->exclusive_operation == type ||
208 (fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE_PAUSED &&
209 type == BTRFS_EXCLOP_DEV_ADD))
210 return true;
211
212 spin_unlock(&fs_info->super_lock);
213 return false;
214 }
215
btrfs_exclop_start_unlock(struct btrfs_fs_info * fs_info)216 void btrfs_exclop_start_unlock(struct btrfs_fs_info *fs_info)
217 {
218 spin_unlock(&fs_info->super_lock);
219 }
220
btrfs_exclop_finish(struct btrfs_fs_info * fs_info)221 void btrfs_exclop_finish(struct btrfs_fs_info *fs_info)
222 {
223 spin_lock(&fs_info->super_lock);
224 WRITE_ONCE(fs_info->exclusive_operation, BTRFS_EXCLOP_NONE);
225 spin_unlock(&fs_info->super_lock);
226 sysfs_notify(&fs_info->fs_devices->fsid_kobj, NULL, "exclusive_operation");
227 }
228
btrfs_exclop_balance(struct btrfs_fs_info * fs_info,enum btrfs_exclusive_operation op)229 void btrfs_exclop_balance(struct btrfs_fs_info *fs_info,
230 enum btrfs_exclusive_operation op)
231 {
232 switch (op) {
233 case BTRFS_EXCLOP_BALANCE_PAUSED:
234 spin_lock(&fs_info->super_lock);
235 ASSERT(fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE ||
236 fs_info->exclusive_operation == BTRFS_EXCLOP_DEV_ADD ||
237 fs_info->exclusive_operation == BTRFS_EXCLOP_NONE ||
238 fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE_PAUSED);
239 fs_info->exclusive_operation = BTRFS_EXCLOP_BALANCE_PAUSED;
240 spin_unlock(&fs_info->super_lock);
241 break;
242 case BTRFS_EXCLOP_BALANCE:
243 spin_lock(&fs_info->super_lock);
244 ASSERT(fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE_PAUSED);
245 fs_info->exclusive_operation = BTRFS_EXCLOP_BALANCE;
246 spin_unlock(&fs_info->super_lock);
247 break;
248 default:
249 btrfs_warn(fs_info,
250 "invalid exclop balance operation %d requested", op);
251 }
252 }
253
__btrfs_set_fs_incompat(struct btrfs_fs_info * fs_info,u64 flag,const char * name)254 void __btrfs_set_fs_incompat(struct btrfs_fs_info *fs_info, u64 flag,
255 const char *name)
256 {
257 struct btrfs_super_block *disk_super;
258 u64 features;
259
260 disk_super = fs_info->super_copy;
261 features = btrfs_super_incompat_flags(disk_super);
262 if (!(features & flag)) {
263 spin_lock(&fs_info->super_lock);
264 features = btrfs_super_incompat_flags(disk_super);
265 if (!(features & flag)) {
266 features |= flag;
267 btrfs_set_super_incompat_flags(disk_super, features);
268 btrfs_info(fs_info,
269 "setting incompat feature flag for %s (0x%llx)",
270 name, flag);
271 }
272 spin_unlock(&fs_info->super_lock);
273 set_bit(BTRFS_FS_FEATURE_CHANGED, &fs_info->flags);
274 }
275 }
276
__btrfs_clear_fs_incompat(struct btrfs_fs_info * fs_info,u64 flag,const char * name)277 void __btrfs_clear_fs_incompat(struct btrfs_fs_info *fs_info, u64 flag,
278 const char *name)
279 {
280 struct btrfs_super_block *disk_super;
281 u64 features;
282
283 disk_super = fs_info->super_copy;
284 features = btrfs_super_incompat_flags(disk_super);
285 if (features & flag) {
286 spin_lock(&fs_info->super_lock);
287 features = btrfs_super_incompat_flags(disk_super);
288 if (features & flag) {
289 features &= ~flag;
290 btrfs_set_super_incompat_flags(disk_super, features);
291 btrfs_info(fs_info,
292 "clearing incompat feature flag for %s (0x%llx)",
293 name, flag);
294 }
295 spin_unlock(&fs_info->super_lock);
296 set_bit(BTRFS_FS_FEATURE_CHANGED, &fs_info->flags);
297 }
298 }
299
__btrfs_set_fs_compat_ro(struct btrfs_fs_info * fs_info,u64 flag,const char * name)300 void __btrfs_set_fs_compat_ro(struct btrfs_fs_info *fs_info, u64 flag,
301 const char *name)
302 {
303 struct btrfs_super_block *disk_super;
304 u64 features;
305
306 disk_super = fs_info->super_copy;
307 features = btrfs_super_compat_ro_flags(disk_super);
308 if (!(features & flag)) {
309 spin_lock(&fs_info->super_lock);
310 features = btrfs_super_compat_ro_flags(disk_super);
311 if (!(features & flag)) {
312 features |= flag;
313 btrfs_set_super_compat_ro_flags(disk_super, features);
314 btrfs_info(fs_info,
315 "setting compat-ro feature flag for %s (0x%llx)",
316 name, flag);
317 }
318 spin_unlock(&fs_info->super_lock);
319 set_bit(BTRFS_FS_FEATURE_CHANGED, &fs_info->flags);
320 }
321 }
322
__btrfs_clear_fs_compat_ro(struct btrfs_fs_info * fs_info,u64 flag,const char * name)323 void __btrfs_clear_fs_compat_ro(struct btrfs_fs_info *fs_info, u64 flag,
324 const char *name)
325 {
326 struct btrfs_super_block *disk_super;
327 u64 features;
328
329 disk_super = fs_info->super_copy;
330 features = btrfs_super_compat_ro_flags(disk_super);
331 if (features & flag) {
332 spin_lock(&fs_info->super_lock);
333 features = btrfs_super_compat_ro_flags(disk_super);
334 if (features & flag) {
335 features &= ~flag;
336 btrfs_set_super_compat_ro_flags(disk_super, features);
337 btrfs_info(fs_info,
338 "clearing compat-ro feature flag for %s (0x%llx)",
339 name, flag);
340 }
341 spin_unlock(&fs_info->super_lock);
342 set_bit(BTRFS_FS_FEATURE_CHANGED, &fs_info->flags);
343 }
344 }
345