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 if (IS_ENABLED(CONFIG_HIGHMEM) && blocksize > PAGE_SIZE) 171 return false; 172 return true; 173 #endif 174 return false; 175 } 176 177 /* 178 * Start exclusive operation @type, return true on success. 179 */ 180 bool btrfs_exclop_start(struct btrfs_fs_info *fs_info, 181 enum btrfs_exclusive_operation type) 182 { 183 bool ret = false; 184 185 spin_lock(&fs_info->super_lock); 186 if (fs_info->exclusive_operation == BTRFS_EXCLOP_NONE) { 187 fs_info->exclusive_operation = type; 188 ret = true; 189 } 190 spin_unlock(&fs_info->super_lock); 191 192 return ret; 193 } 194 195 /* 196 * Conditionally allow to enter the exclusive operation in case it's compatible 197 * with the running one. This must be paired with btrfs_exclop_start_unlock() 198 * and btrfs_exclop_finish(). 199 * 200 * Compatibility: 201 * - the same type is already running 202 * - when trying to add a device and balance has been paused 203 * - not BTRFS_EXCLOP_NONE - this is intentionally incompatible and the caller 204 * must check the condition first that would allow none -> @type 205 */ 206 bool btrfs_exclop_start_try_lock(struct btrfs_fs_info *fs_info, 207 enum btrfs_exclusive_operation type) 208 { 209 spin_lock(&fs_info->super_lock); 210 if (fs_info->exclusive_operation == type || 211 (fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE_PAUSED && 212 type == BTRFS_EXCLOP_DEV_ADD)) 213 return true; 214 215 spin_unlock(&fs_info->super_lock); 216 return false; 217 } 218 219 void btrfs_exclop_start_unlock(struct btrfs_fs_info *fs_info) 220 { 221 spin_unlock(&fs_info->super_lock); 222 } 223 224 void btrfs_exclop_finish(struct btrfs_fs_info *fs_info) 225 { 226 spin_lock(&fs_info->super_lock); 227 WRITE_ONCE(fs_info->exclusive_operation, BTRFS_EXCLOP_NONE); 228 spin_unlock(&fs_info->super_lock); 229 sysfs_notify(&fs_info->fs_devices->fsid_kobj, NULL, "exclusive_operation"); 230 } 231 232 void btrfs_exclop_balance(struct btrfs_fs_info *fs_info, 233 enum btrfs_exclusive_operation op) 234 { 235 switch (op) { 236 case BTRFS_EXCLOP_BALANCE_PAUSED: 237 spin_lock(&fs_info->super_lock); 238 ASSERT(fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE || 239 fs_info->exclusive_operation == BTRFS_EXCLOP_DEV_ADD || 240 fs_info->exclusive_operation == BTRFS_EXCLOP_NONE || 241 fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE_PAUSED); 242 fs_info->exclusive_operation = BTRFS_EXCLOP_BALANCE_PAUSED; 243 spin_unlock(&fs_info->super_lock); 244 break; 245 case BTRFS_EXCLOP_BALANCE: 246 spin_lock(&fs_info->super_lock); 247 ASSERT(fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE_PAUSED); 248 fs_info->exclusive_operation = BTRFS_EXCLOP_BALANCE; 249 spin_unlock(&fs_info->super_lock); 250 break; 251 default: 252 btrfs_warn(fs_info, 253 "invalid exclop balance operation %d requested", op); 254 } 255 } 256 257 void __btrfs_set_fs_incompat(struct btrfs_fs_info *fs_info, u64 flag, 258 const char *name) 259 { 260 struct btrfs_super_block *disk_super; 261 u64 features; 262 263 disk_super = fs_info->super_copy; 264 features = btrfs_super_incompat_flags(disk_super); 265 if (!(features & flag)) { 266 spin_lock(&fs_info->super_lock); 267 features = btrfs_super_incompat_flags(disk_super); 268 if (!(features & flag)) { 269 features |= flag; 270 btrfs_set_super_incompat_flags(disk_super, features); 271 btrfs_info(fs_info, 272 "setting incompat feature flag for %s (0x%llx)", 273 name, flag); 274 } 275 spin_unlock(&fs_info->super_lock); 276 set_bit(BTRFS_FS_FEATURE_CHANGED, &fs_info->flags); 277 } 278 } 279 280 void __btrfs_clear_fs_incompat(struct btrfs_fs_info *fs_info, u64 flag, 281 const char *name) 282 { 283 struct btrfs_super_block *disk_super; 284 u64 features; 285 286 disk_super = fs_info->super_copy; 287 features = btrfs_super_incompat_flags(disk_super); 288 if (features & flag) { 289 spin_lock(&fs_info->super_lock); 290 features = btrfs_super_incompat_flags(disk_super); 291 if (features & flag) { 292 features &= ~flag; 293 btrfs_set_super_incompat_flags(disk_super, features); 294 btrfs_info(fs_info, 295 "clearing incompat feature flag for %s (0x%llx)", 296 name, flag); 297 } 298 spin_unlock(&fs_info->super_lock); 299 set_bit(BTRFS_FS_FEATURE_CHANGED, &fs_info->flags); 300 } 301 } 302 303 void __btrfs_set_fs_compat_ro(struct btrfs_fs_info *fs_info, u64 flag, 304 const char *name) 305 { 306 struct btrfs_super_block *disk_super; 307 u64 features; 308 309 disk_super = fs_info->super_copy; 310 features = btrfs_super_compat_ro_flags(disk_super); 311 if (!(features & flag)) { 312 spin_lock(&fs_info->super_lock); 313 features = btrfs_super_compat_ro_flags(disk_super); 314 if (!(features & flag)) { 315 features |= flag; 316 btrfs_set_super_compat_ro_flags(disk_super, features); 317 btrfs_info(fs_info, 318 "setting compat-ro feature flag for %s (0x%llx)", 319 name, flag); 320 } 321 spin_unlock(&fs_info->super_lock); 322 set_bit(BTRFS_FS_FEATURE_CHANGED, &fs_info->flags); 323 } 324 } 325 326 void __btrfs_clear_fs_compat_ro(struct btrfs_fs_info *fs_info, u64 flag, 327 const char *name) 328 { 329 struct btrfs_super_block *disk_super; 330 u64 features; 331 332 disk_super = fs_info->super_copy; 333 features = btrfs_super_compat_ro_flags(disk_super); 334 if (features & flag) { 335 spin_lock(&fs_info->super_lock); 336 features = btrfs_super_compat_ro_flags(disk_super); 337 if (features & flag) { 338 features &= ~flag; 339 btrfs_set_super_compat_ro_flags(disk_super, features); 340 btrfs_info(fs_info, 341 "clearing compat-ro feature flag for %s (0x%llx)", 342 name, flag); 343 } 344 spin_unlock(&fs_info->super_lock); 345 set_bit(BTRFS_FS_FEATURE_CHANGED, &fs_info->flags); 346 } 347 } 348