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