xref: /linux/fs/btrfs/fs.c (revision c36461825469a9ceee2346a2e89286c522525da7)
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. */
20 u16 btrfs_csum_type_size(u16 type)
21 {
22 	return btrfs_csums[type].size;
23 }
24 
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 
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 
39 size_t __attribute_const__ btrfs_get_num_csums(void)
40 {
41 	return ARRAY_SIZE(btrfs_csums);
42 }
43 
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 
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 
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 
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  * We support the following block sizes for all systems:
131  *
132  * - 4K
133  *   This is the most common block size. For PAGE SIZE > 4K cases the subpage
134  *   mode is used.
135  *
136  * - PAGE_SIZE
137  *   The straightforward block size to support.
138  *
139  * And extra support for the following block sizes based on the kernel config:
140  *
141  * - MIN_BLOCKSIZE
142  *   This is either 4K (regular builds) or 2K (debug builds)
143  *   This allows testing subpage routines on x86_64.
144  */
145 bool __attribute_const__ btrfs_supported_blocksize(u32 blocksize)
146 {
147 	/* @blocksize should be validated first. */
148 	ASSERT(is_power_of_2(blocksize) && blocksize >= BTRFS_MIN_BLOCKSIZE &&
149 	       blocksize <= BTRFS_MAX_BLOCKSIZE);
150 
151 	if (blocksize == PAGE_SIZE || blocksize == SZ_4K || blocksize == BTRFS_MIN_BLOCKSIZE)
152 		return true;
153 #ifdef CONFIG_BTRFS_EXPERIMENTAL
154 	/*
155 	 * For bs > ps support it's done by specifying a minimal folio order
156 	 * for filemap, thus implying large data folios.
157 	 * For HIGHMEM systems, we can not always access the content of a (large)
158 	 * folio in one go, but go through them page by page.
159 	 *
160 	 * A lot of features don't implement a proper PAGE sized loop for large
161 	 * folios, this includes:
162 	 *
163 	 * - compression
164 	 * - verity
165 	 * - encoded write
166 	 *
167 	 * Considering HIGHMEM is such a pain to deal with and it's going
168 	 * to be deprecated eventually, just reject HIGHMEM && bs > ps cases.
169 	 *
170 	 * Finally, for bs > ps cases, we need to set the minimal folio order,
171 	 * which requires transparent hugepage.
172 	 */
173 	if (blocksize > PAGE_SIZE) {
174 		if (IS_ENABLED(CONFIG_HIGHMEM))
175 			return false;
176 
177 		if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
178 			return false;
179 	}
180 	return true;
181 #endif
182 	return false;
183 }
184 
185 /*
186  * Start exclusive operation @type, return true on success.
187  */
188 bool btrfs_exclop_start(struct btrfs_fs_info *fs_info,
189 			enum btrfs_exclusive_operation type)
190 {
191 	bool ret = false;
192 
193 	spin_lock(&fs_info->super_lock);
194 	if (fs_info->exclusive_operation == BTRFS_EXCLOP_NONE) {
195 		fs_info->exclusive_operation = type;
196 		ret = true;
197 	}
198 	spin_unlock(&fs_info->super_lock);
199 
200 	return ret;
201 }
202 
203 /*
204  * Conditionally allow to enter the exclusive operation in case it's compatible
205  * with the running one.  This must be paired with btrfs_exclop_start_unlock()
206  * and btrfs_exclop_finish().
207  *
208  * Compatibility:
209  * - the same type is already running
210  * - when trying to add a device and balance has been paused
211  * - not BTRFS_EXCLOP_NONE - this is intentionally incompatible and the caller
212  *   must check the condition first that would allow none -> @type
213  */
214 bool btrfs_exclop_start_try_lock(struct btrfs_fs_info *fs_info,
215 				 enum btrfs_exclusive_operation type)
216 {
217 	spin_lock(&fs_info->super_lock);
218 	if (fs_info->exclusive_operation == type ||
219 	    (fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE_PAUSED &&
220 	     type == BTRFS_EXCLOP_DEV_ADD))
221 		return true;
222 
223 	spin_unlock(&fs_info->super_lock);
224 	return false;
225 }
226 
227 void btrfs_exclop_start_unlock(struct btrfs_fs_info *fs_info)
228 {
229 	spin_unlock(&fs_info->super_lock);
230 }
231 
232 void btrfs_exclop_finish(struct btrfs_fs_info *fs_info)
233 {
234 	spin_lock(&fs_info->super_lock);
235 	WRITE_ONCE(fs_info->exclusive_operation, BTRFS_EXCLOP_NONE);
236 	spin_unlock(&fs_info->super_lock);
237 	sysfs_notify(&fs_info->fs_devices->fsid_kobj, NULL, "exclusive_operation");
238 }
239 
240 void btrfs_exclop_balance(struct btrfs_fs_info *fs_info,
241 			  enum btrfs_exclusive_operation op)
242 {
243 	switch (op) {
244 	case BTRFS_EXCLOP_BALANCE_PAUSED:
245 		spin_lock(&fs_info->super_lock);
246 		ASSERT(fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE ||
247 		       fs_info->exclusive_operation == BTRFS_EXCLOP_DEV_ADD ||
248 		       fs_info->exclusive_operation == BTRFS_EXCLOP_NONE ||
249 		       fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE_PAUSED);
250 		fs_info->exclusive_operation = BTRFS_EXCLOP_BALANCE_PAUSED;
251 		spin_unlock(&fs_info->super_lock);
252 		break;
253 	case BTRFS_EXCLOP_BALANCE:
254 		spin_lock(&fs_info->super_lock);
255 		ASSERT(fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE_PAUSED);
256 		fs_info->exclusive_operation = BTRFS_EXCLOP_BALANCE;
257 		spin_unlock(&fs_info->super_lock);
258 		break;
259 	default:
260 		btrfs_warn(fs_info,
261 			"invalid exclop balance operation %d requested", op);
262 	}
263 }
264 
265 void __btrfs_set_fs_incompat(struct btrfs_fs_info *fs_info, u64 flag,
266 			     const char *name)
267 {
268 	struct btrfs_super_block *disk_super;
269 	u64 features;
270 
271 	disk_super = fs_info->super_copy;
272 	features = btrfs_super_incompat_flags(disk_super);
273 	if (!(features & flag)) {
274 		spin_lock(&fs_info->super_lock);
275 		features = btrfs_super_incompat_flags(disk_super);
276 		if (!(features & flag)) {
277 			features |= flag;
278 			btrfs_set_super_incompat_flags(disk_super, features);
279 			btrfs_info(fs_info,
280 				"setting incompat feature flag for %s (0x%llx)",
281 				name, flag);
282 		}
283 		spin_unlock(&fs_info->super_lock);
284 		set_bit(BTRFS_FS_FEATURE_CHANGED, &fs_info->flags);
285 	}
286 }
287 
288 void __btrfs_clear_fs_incompat(struct btrfs_fs_info *fs_info, u64 flag,
289 			       const char *name)
290 {
291 	struct btrfs_super_block *disk_super;
292 	u64 features;
293 
294 	disk_super = fs_info->super_copy;
295 	features = btrfs_super_incompat_flags(disk_super);
296 	if (features & flag) {
297 		spin_lock(&fs_info->super_lock);
298 		features = btrfs_super_incompat_flags(disk_super);
299 		if (features & flag) {
300 			features &= ~flag;
301 			btrfs_set_super_incompat_flags(disk_super, features);
302 			btrfs_info(fs_info,
303 				"clearing incompat feature flag for %s (0x%llx)",
304 				name, flag);
305 		}
306 		spin_unlock(&fs_info->super_lock);
307 		set_bit(BTRFS_FS_FEATURE_CHANGED, &fs_info->flags);
308 	}
309 }
310 
311 void __btrfs_set_fs_compat_ro(struct btrfs_fs_info *fs_info, u64 flag,
312 			      const char *name)
313 {
314 	struct btrfs_super_block *disk_super;
315 	u64 features;
316 
317 	disk_super = fs_info->super_copy;
318 	features = btrfs_super_compat_ro_flags(disk_super);
319 	if (!(features & flag)) {
320 		spin_lock(&fs_info->super_lock);
321 		features = btrfs_super_compat_ro_flags(disk_super);
322 		if (!(features & flag)) {
323 			features |= flag;
324 			btrfs_set_super_compat_ro_flags(disk_super, features);
325 			btrfs_info(fs_info,
326 				"setting compat-ro feature flag for %s (0x%llx)",
327 				name, flag);
328 		}
329 		spin_unlock(&fs_info->super_lock);
330 		set_bit(BTRFS_FS_FEATURE_CHANGED, &fs_info->flags);
331 	}
332 }
333 
334 void __btrfs_clear_fs_compat_ro(struct btrfs_fs_info *fs_info, u64 flag,
335 				const char *name)
336 {
337 	struct btrfs_super_block *disk_super;
338 	u64 features;
339 
340 	disk_super = fs_info->super_copy;
341 	features = btrfs_super_compat_ro_flags(disk_super);
342 	if (features & flag) {
343 		spin_lock(&fs_info->super_lock);
344 		features = btrfs_super_compat_ro_flags(disk_super);
345 		if (features & flag) {
346 			features &= ~flag;
347 			btrfs_set_super_compat_ro_flags(disk_super, features);
348 			btrfs_info(fs_info,
349 				"clearing compat-ro feature flag for %s (0x%llx)",
350 				name, flag);
351 		}
352 		spin_unlock(&fs_info->super_lock);
353 		set_bit(BTRFS_FS_FEATURE_CHANGED, &fs_info->flags);
354 	}
355 }
356