1c1d7c514SDavid Sterba // SPDX-License-Identifier: GPL-2.0 2557ea5ddSQu Wenruo /* 3557ea5ddSQu Wenruo * Copyright (C) Qu Wenruo 2017. All rights reserved. 4557ea5ddSQu Wenruo */ 5557ea5ddSQu Wenruo 6557ea5ddSQu Wenruo /* 7557ea5ddSQu Wenruo * The module is used to catch unexpected/corrupted tree block data. 8557ea5ddSQu Wenruo * Such behavior can be caused either by a fuzzed image or bugs. 9557ea5ddSQu Wenruo * 10557ea5ddSQu Wenruo * The objective is to do leaf/node validation checks when tree block is read 11557ea5ddSQu Wenruo * from disk, and check *every* possible member, so other code won't 12557ea5ddSQu Wenruo * need to checking them again. 13557ea5ddSQu Wenruo * 14557ea5ddSQu Wenruo * Due to the potential and unwanted damage, every checker needs to be 15557ea5ddSQu Wenruo * carefully reviewed otherwise so it does not prevent mount of valid images. 16557ea5ddSQu Wenruo */ 17557ea5ddSQu Wenruo 1802529d7aSQu Wenruo #include <linux/types.h> 1902529d7aSQu Wenruo #include <linux/stddef.h> 2002529d7aSQu Wenruo #include <linux/error-injection.h> 21557ea5ddSQu Wenruo #include "ctree.h" 22557ea5ddSQu Wenruo #include "tree-checker.h" 23557ea5ddSQu Wenruo #include "disk-io.h" 24557ea5ddSQu Wenruo #include "compression.h" 25fce466eaSQu Wenruo #include "volumes.h" 26557ea5ddSQu Wenruo 27bba4f298SQu Wenruo /* 28bba4f298SQu Wenruo * Error message should follow the following format: 29bba4f298SQu Wenruo * corrupt <type>: <identifier>, <reason>[, <bad_value>] 30bba4f298SQu Wenruo * 31bba4f298SQu Wenruo * @type: leaf or node 32bba4f298SQu Wenruo * @identifier: the necessary info to locate the leaf/node. 3352042d8eSAndrea Gelmini * It's recommended to decode key.objecitd/offset if it's 34bba4f298SQu Wenruo * meaningful. 35bba4f298SQu Wenruo * @reason: describe the error 3652042d8eSAndrea Gelmini * @bad_value: optional, it's recommended to output bad value and its 37bba4f298SQu Wenruo * expected value (range). 38bba4f298SQu Wenruo * 39bba4f298SQu Wenruo * Since comma is used to separate the components, only space is allowed 40bba4f298SQu Wenruo * inside each component. 41bba4f298SQu Wenruo */ 42bba4f298SQu Wenruo 43bba4f298SQu Wenruo /* 44bba4f298SQu Wenruo * Append generic "corrupt leaf/node root=%llu block=%llu slot=%d: " to @fmt. 45bba4f298SQu Wenruo * Allows callers to customize the output. 46bba4f298SQu Wenruo */ 4786a6be3aSDavid Sterba __printf(3, 4) 48e67c718bSDavid Sterba __cold 4986a6be3aSDavid Sterba static void generic_err(const struct extent_buffer *eb, int slot, 50bba4f298SQu Wenruo const char *fmt, ...) 51bba4f298SQu Wenruo { 5286a6be3aSDavid Sterba const struct btrfs_fs_info *fs_info = eb->fs_info; 53bba4f298SQu Wenruo struct va_format vaf; 54bba4f298SQu Wenruo va_list args; 55bba4f298SQu Wenruo 56bba4f298SQu Wenruo va_start(args, fmt); 57bba4f298SQu Wenruo 58bba4f298SQu Wenruo vaf.fmt = fmt; 59bba4f298SQu Wenruo vaf.va = &args; 60bba4f298SQu Wenruo 612f659546SQu Wenruo btrfs_crit(fs_info, 62bba4f298SQu Wenruo "corrupt %s: root=%llu block=%llu slot=%d, %pV", 63bba4f298SQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 642f659546SQu Wenruo btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, &vaf); 65bba4f298SQu Wenruo va_end(args); 66bba4f298SQu Wenruo } 67bba4f298SQu Wenruo 688806d718SQu Wenruo /* 698806d718SQu Wenruo * Customized reporter for extent data item, since its key objectid and 708806d718SQu Wenruo * offset has its own meaning. 718806d718SQu Wenruo */ 721fd715ffSDavid Sterba __printf(3, 4) 73e67c718bSDavid Sterba __cold 741fd715ffSDavid Sterba static void file_extent_err(const struct extent_buffer *eb, int slot, 758806d718SQu Wenruo const char *fmt, ...) 768806d718SQu Wenruo { 771fd715ffSDavid Sterba const struct btrfs_fs_info *fs_info = eb->fs_info; 788806d718SQu Wenruo struct btrfs_key key; 798806d718SQu Wenruo struct va_format vaf; 808806d718SQu Wenruo va_list args; 818806d718SQu Wenruo 828806d718SQu Wenruo btrfs_item_key_to_cpu(eb, &key, slot); 838806d718SQu Wenruo va_start(args, fmt); 848806d718SQu Wenruo 858806d718SQu Wenruo vaf.fmt = fmt; 868806d718SQu Wenruo vaf.va = &args; 878806d718SQu Wenruo 882f659546SQu Wenruo btrfs_crit(fs_info, 898806d718SQu Wenruo "corrupt %s: root=%llu block=%llu slot=%d ino=%llu file_offset=%llu, %pV", 902f659546SQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 912f659546SQu Wenruo btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, 922f659546SQu Wenruo key.objectid, key.offset, &vaf); 938806d718SQu Wenruo va_end(args); 948806d718SQu Wenruo } 958806d718SQu Wenruo 968806d718SQu Wenruo /* 978806d718SQu Wenruo * Return 0 if the btrfs_file_extent_##name is aligned to @alignment 988806d718SQu Wenruo * Else return 1 998806d718SQu Wenruo */ 100033774dcSDavid Sterba #define CHECK_FE_ALIGNED(leaf, slot, fi, name, alignment) \ 1018806d718SQu Wenruo ({ \ 1028806d718SQu Wenruo if (!IS_ALIGNED(btrfs_file_extent_##name((leaf), (fi)), (alignment))) \ 1031fd715ffSDavid Sterba file_extent_err((leaf), (slot), \ 1048806d718SQu Wenruo "invalid %s for file extent, have %llu, should be aligned to %u", \ 1058806d718SQu Wenruo (#name), btrfs_file_extent_##name((leaf), (fi)), \ 1068806d718SQu Wenruo (alignment)); \ 1078806d718SQu Wenruo (!IS_ALIGNED(btrfs_file_extent_##name((leaf), (fi)), (alignment))); \ 1088806d718SQu Wenruo }) 1098806d718SQu Wenruo 1104e9845efSFilipe Manana static u64 file_extent_end(struct extent_buffer *leaf, 1114e9845efSFilipe Manana struct btrfs_key *key, 1124e9845efSFilipe Manana struct btrfs_file_extent_item *extent) 1134e9845efSFilipe Manana { 1144e9845efSFilipe Manana u64 end; 1154e9845efSFilipe Manana u64 len; 1164e9845efSFilipe Manana 1174e9845efSFilipe Manana if (btrfs_file_extent_type(leaf, extent) == BTRFS_FILE_EXTENT_INLINE) { 1184e9845efSFilipe Manana len = btrfs_file_extent_ram_bytes(leaf, extent); 1194e9845efSFilipe Manana end = ALIGN(key->offset + len, leaf->fs_info->sectorsize); 1204e9845efSFilipe Manana } else { 1214e9845efSFilipe Manana len = btrfs_file_extent_num_bytes(leaf, extent); 1224e9845efSFilipe Manana end = key->offset + len; 1234e9845efSFilipe Manana } 1244e9845efSFilipe Manana return end; 1254e9845efSFilipe Manana } 1264e9845efSFilipe Manana 127ae2a19d8SDavid Sterba static int check_extent_data_item(struct extent_buffer *leaf, 1284e9845efSFilipe Manana struct btrfs_key *key, int slot, 1294e9845efSFilipe Manana struct btrfs_key *prev_key) 130557ea5ddSQu Wenruo { 131ae2a19d8SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 132557ea5ddSQu Wenruo struct btrfs_file_extent_item *fi; 1332f659546SQu Wenruo u32 sectorsize = fs_info->sectorsize; 134557ea5ddSQu Wenruo u32 item_size = btrfs_item_size_nr(leaf, slot); 1354c094c33SQu Wenruo u64 extent_end; 136557ea5ddSQu Wenruo 137557ea5ddSQu Wenruo if (!IS_ALIGNED(key->offset, sectorsize)) { 1381fd715ffSDavid Sterba file_extent_err(leaf, slot, 1398806d718SQu Wenruo "unaligned file_offset for file extent, have %llu should be aligned to %u", 1408806d718SQu Wenruo key->offset, sectorsize); 141557ea5ddSQu Wenruo return -EUCLEAN; 142557ea5ddSQu Wenruo } 143557ea5ddSQu Wenruo 144c18679ebSQu Wenruo /* 145c18679ebSQu Wenruo * Previous key must have the same key->objectid (ino). 146c18679ebSQu Wenruo * It can be XATTR_ITEM, INODE_ITEM or just another EXTENT_DATA. 147c18679ebSQu Wenruo * But if objectids mismatch, it means we have a missing 148c18679ebSQu Wenruo * INODE_ITEM. 149c18679ebSQu Wenruo */ 150c18679ebSQu Wenruo if (slot > 0 && is_fstree(btrfs_header_owner(leaf)) && 151c18679ebSQu Wenruo prev_key->objectid != key->objectid) { 152c18679ebSQu Wenruo file_extent_err(leaf, slot, 153c18679ebSQu Wenruo "invalid previous key objectid, have %llu expect %llu", 154c18679ebSQu Wenruo prev_key->objectid, key->objectid); 155c18679ebSQu Wenruo return -EUCLEAN; 156c18679ebSQu Wenruo } 157c18679ebSQu Wenruo 158557ea5ddSQu Wenruo fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); 159557ea5ddSQu Wenruo 160557ea5ddSQu Wenruo if (btrfs_file_extent_type(leaf, fi) > BTRFS_FILE_EXTENT_TYPES) { 1611fd715ffSDavid Sterba file_extent_err(leaf, slot, 1628806d718SQu Wenruo "invalid type for file extent, have %u expect range [0, %u]", 1638806d718SQu Wenruo btrfs_file_extent_type(leaf, fi), 1648806d718SQu Wenruo BTRFS_FILE_EXTENT_TYPES); 165557ea5ddSQu Wenruo return -EUCLEAN; 166557ea5ddSQu Wenruo } 167557ea5ddSQu Wenruo 168557ea5ddSQu Wenruo /* 16952042d8eSAndrea Gelmini * Support for new compression/encryption must introduce incompat flag, 170557ea5ddSQu Wenruo * and must be caught in open_ctree(). 171557ea5ddSQu Wenruo */ 172557ea5ddSQu Wenruo if (btrfs_file_extent_compression(leaf, fi) > BTRFS_COMPRESS_TYPES) { 1731fd715ffSDavid Sterba file_extent_err(leaf, slot, 1748806d718SQu Wenruo "invalid compression for file extent, have %u expect range [0, %u]", 1758806d718SQu Wenruo btrfs_file_extent_compression(leaf, fi), 1768806d718SQu Wenruo BTRFS_COMPRESS_TYPES); 177557ea5ddSQu Wenruo return -EUCLEAN; 178557ea5ddSQu Wenruo } 179557ea5ddSQu Wenruo if (btrfs_file_extent_encryption(leaf, fi)) { 1801fd715ffSDavid Sterba file_extent_err(leaf, slot, 1818806d718SQu Wenruo "invalid encryption for file extent, have %u expect 0", 1828806d718SQu Wenruo btrfs_file_extent_encryption(leaf, fi)); 183557ea5ddSQu Wenruo return -EUCLEAN; 184557ea5ddSQu Wenruo } 185557ea5ddSQu Wenruo if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_INLINE) { 186557ea5ddSQu Wenruo /* Inline extent must have 0 as key offset */ 187557ea5ddSQu Wenruo if (key->offset) { 1881fd715ffSDavid Sterba file_extent_err(leaf, slot, 1898806d718SQu Wenruo "invalid file_offset for inline file extent, have %llu expect 0", 1908806d718SQu Wenruo key->offset); 191557ea5ddSQu Wenruo return -EUCLEAN; 192557ea5ddSQu Wenruo } 193557ea5ddSQu Wenruo 194557ea5ddSQu Wenruo /* Compressed inline extent has no on-disk size, skip it */ 195557ea5ddSQu Wenruo if (btrfs_file_extent_compression(leaf, fi) != 196557ea5ddSQu Wenruo BTRFS_COMPRESS_NONE) 197557ea5ddSQu Wenruo return 0; 198557ea5ddSQu Wenruo 199557ea5ddSQu Wenruo /* Uncompressed inline extent size must match item size */ 200557ea5ddSQu Wenruo if (item_size != BTRFS_FILE_EXTENT_INLINE_DATA_START + 201557ea5ddSQu Wenruo btrfs_file_extent_ram_bytes(leaf, fi)) { 2021fd715ffSDavid Sterba file_extent_err(leaf, slot, 2038806d718SQu Wenruo "invalid ram_bytes for uncompressed inline extent, have %u expect %llu", 2048806d718SQu Wenruo item_size, BTRFS_FILE_EXTENT_INLINE_DATA_START + 2058806d718SQu Wenruo btrfs_file_extent_ram_bytes(leaf, fi)); 206557ea5ddSQu Wenruo return -EUCLEAN; 207557ea5ddSQu Wenruo } 208557ea5ddSQu Wenruo return 0; 209557ea5ddSQu Wenruo } 210557ea5ddSQu Wenruo 211557ea5ddSQu Wenruo /* Regular or preallocated extent has fixed item size */ 212557ea5ddSQu Wenruo if (item_size != sizeof(*fi)) { 2131fd715ffSDavid Sterba file_extent_err(leaf, slot, 214709a95c3SArnd Bergmann "invalid item size for reg/prealloc file extent, have %u expect %zu", 2158806d718SQu Wenruo item_size, sizeof(*fi)); 216557ea5ddSQu Wenruo return -EUCLEAN; 217557ea5ddSQu Wenruo } 218033774dcSDavid Sterba if (CHECK_FE_ALIGNED(leaf, slot, fi, ram_bytes, sectorsize) || 219033774dcSDavid Sterba CHECK_FE_ALIGNED(leaf, slot, fi, disk_bytenr, sectorsize) || 220033774dcSDavid Sterba CHECK_FE_ALIGNED(leaf, slot, fi, disk_num_bytes, sectorsize) || 221033774dcSDavid Sterba CHECK_FE_ALIGNED(leaf, slot, fi, offset, sectorsize) || 222033774dcSDavid Sterba CHECK_FE_ALIGNED(leaf, slot, fi, num_bytes, sectorsize)) 223557ea5ddSQu Wenruo return -EUCLEAN; 2244e9845efSFilipe Manana 2254c094c33SQu Wenruo /* Catch extent end overflow */ 2264c094c33SQu Wenruo if (check_add_overflow(btrfs_file_extent_num_bytes(leaf, fi), 2274c094c33SQu Wenruo key->offset, &extent_end)) { 2284c094c33SQu Wenruo file_extent_err(leaf, slot, 2294c094c33SQu Wenruo "extent end overflow, have file offset %llu extent num bytes %llu", 2304c094c33SQu Wenruo key->offset, 2314c094c33SQu Wenruo btrfs_file_extent_num_bytes(leaf, fi)); 2324c094c33SQu Wenruo return -EUCLEAN; 2334c094c33SQu Wenruo } 2344c094c33SQu Wenruo 2354e9845efSFilipe Manana /* 2364e9845efSFilipe Manana * Check that no two consecutive file extent items, in the same leaf, 2374e9845efSFilipe Manana * present ranges that overlap each other. 2384e9845efSFilipe Manana */ 2394e9845efSFilipe Manana if (slot > 0 && 2404e9845efSFilipe Manana prev_key->objectid == key->objectid && 2414e9845efSFilipe Manana prev_key->type == BTRFS_EXTENT_DATA_KEY) { 2424e9845efSFilipe Manana struct btrfs_file_extent_item *prev_fi; 2434e9845efSFilipe Manana u64 prev_end; 2444e9845efSFilipe Manana 2454e9845efSFilipe Manana prev_fi = btrfs_item_ptr(leaf, slot - 1, 2464e9845efSFilipe Manana struct btrfs_file_extent_item); 2474e9845efSFilipe Manana prev_end = file_extent_end(leaf, prev_key, prev_fi); 2484e9845efSFilipe Manana if (prev_end > key->offset) { 2494e9845efSFilipe Manana file_extent_err(leaf, slot - 1, 2504e9845efSFilipe Manana "file extent end range (%llu) goes beyond start offset (%llu) of the next file extent", 2514e9845efSFilipe Manana prev_end, key->offset); 2524e9845efSFilipe Manana return -EUCLEAN; 2534e9845efSFilipe Manana } 2544e9845efSFilipe Manana } 2554e9845efSFilipe Manana 256557ea5ddSQu Wenruo return 0; 257557ea5ddSQu Wenruo } 258557ea5ddSQu Wenruo 25968128ce7SDavid Sterba static int check_csum_item(struct extent_buffer *leaf, struct btrfs_key *key, 2602f659546SQu Wenruo int slot) 261557ea5ddSQu Wenruo { 26268128ce7SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 2632f659546SQu Wenruo u32 sectorsize = fs_info->sectorsize; 2642f659546SQu Wenruo u32 csumsize = btrfs_super_csum_size(fs_info->super_copy); 265557ea5ddSQu Wenruo 266557ea5ddSQu Wenruo if (key->objectid != BTRFS_EXTENT_CSUM_OBJECTID) { 26786a6be3aSDavid Sterba generic_err(leaf, slot, 268d508c5f0SQu Wenruo "invalid key objectid for csum item, have %llu expect %llu", 269d508c5f0SQu Wenruo key->objectid, BTRFS_EXTENT_CSUM_OBJECTID); 270557ea5ddSQu Wenruo return -EUCLEAN; 271557ea5ddSQu Wenruo } 272557ea5ddSQu Wenruo if (!IS_ALIGNED(key->offset, sectorsize)) { 27386a6be3aSDavid Sterba generic_err(leaf, slot, 274d508c5f0SQu Wenruo "unaligned key offset for csum item, have %llu should be aligned to %u", 275d508c5f0SQu Wenruo key->offset, sectorsize); 276557ea5ddSQu Wenruo return -EUCLEAN; 277557ea5ddSQu Wenruo } 278557ea5ddSQu Wenruo if (!IS_ALIGNED(btrfs_item_size_nr(leaf, slot), csumsize)) { 27986a6be3aSDavid Sterba generic_err(leaf, slot, 280d508c5f0SQu Wenruo "unaligned item size for csum item, have %u should be aligned to %u", 281d508c5f0SQu Wenruo btrfs_item_size_nr(leaf, slot), csumsize); 282557ea5ddSQu Wenruo return -EUCLEAN; 283557ea5ddSQu Wenruo } 284557ea5ddSQu Wenruo return 0; 285557ea5ddSQu Wenruo } 286557ea5ddSQu Wenruo 287557ea5ddSQu Wenruo /* 288ad7b0368SQu Wenruo * Customized reported for dir_item, only important new info is key->objectid, 289ad7b0368SQu Wenruo * which represents inode number 290ad7b0368SQu Wenruo */ 291d98ced68SDavid Sterba __printf(3, 4) 292e67c718bSDavid Sterba __cold 293d98ced68SDavid Sterba static void dir_item_err(const struct extent_buffer *eb, int slot, 294ad7b0368SQu Wenruo const char *fmt, ...) 295ad7b0368SQu Wenruo { 296d98ced68SDavid Sterba const struct btrfs_fs_info *fs_info = eb->fs_info; 297ad7b0368SQu Wenruo struct btrfs_key key; 298ad7b0368SQu Wenruo struct va_format vaf; 299ad7b0368SQu Wenruo va_list args; 300ad7b0368SQu Wenruo 301ad7b0368SQu Wenruo btrfs_item_key_to_cpu(eb, &key, slot); 302ad7b0368SQu Wenruo va_start(args, fmt); 303ad7b0368SQu Wenruo 304ad7b0368SQu Wenruo vaf.fmt = fmt; 305ad7b0368SQu Wenruo vaf.va = &args; 306ad7b0368SQu Wenruo 3072f659546SQu Wenruo btrfs_crit(fs_info, 308ad7b0368SQu Wenruo "corrupt %s: root=%llu block=%llu slot=%d ino=%llu, %pV", 3092f659546SQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 3102f659546SQu Wenruo btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, 3112f659546SQu Wenruo key.objectid, &vaf); 312ad7b0368SQu Wenruo va_end(args); 313ad7b0368SQu Wenruo } 314ad7b0368SQu Wenruo 315ce4252c0SDavid Sterba static int check_dir_item(struct extent_buffer *leaf, 316c18679ebSQu Wenruo struct btrfs_key *key, struct btrfs_key *prev_key, 317c18679ebSQu Wenruo int slot) 318ad7b0368SQu Wenruo { 319ce4252c0SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 320ad7b0368SQu Wenruo struct btrfs_dir_item *di; 321ad7b0368SQu Wenruo u32 item_size = btrfs_item_size_nr(leaf, slot); 322ad7b0368SQu Wenruo u32 cur = 0; 323ad7b0368SQu Wenruo 324c18679ebSQu Wenruo /* Same check as in check_extent_data_item() */ 325c18679ebSQu Wenruo if (slot > 0 && is_fstree(btrfs_header_owner(leaf)) && 326c18679ebSQu Wenruo prev_key->objectid != key->objectid) { 327c18679ebSQu Wenruo dir_item_err(leaf, slot, 328c18679ebSQu Wenruo "invalid previous key objectid, have %llu expect %llu", 329c18679ebSQu Wenruo prev_key->objectid, key->objectid); 330c18679ebSQu Wenruo return -EUCLEAN; 331c18679ebSQu Wenruo } 332ad7b0368SQu Wenruo di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); 333ad7b0368SQu Wenruo while (cur < item_size) { 334ad7b0368SQu Wenruo u32 name_len; 335ad7b0368SQu Wenruo u32 data_len; 336ad7b0368SQu Wenruo u32 max_name_len; 337ad7b0368SQu Wenruo u32 total_size; 338ad7b0368SQu Wenruo u32 name_hash; 339ad7b0368SQu Wenruo u8 dir_type; 340ad7b0368SQu Wenruo 341ad7b0368SQu Wenruo /* header itself should not cross item boundary */ 342ad7b0368SQu Wenruo if (cur + sizeof(*di) > item_size) { 343d98ced68SDavid Sterba dir_item_err(leaf, slot, 3447cfad652SArnd Bergmann "dir item header crosses item boundary, have %zu boundary %u", 345ad7b0368SQu Wenruo cur + sizeof(*di), item_size); 346ad7b0368SQu Wenruo return -EUCLEAN; 347ad7b0368SQu Wenruo } 348ad7b0368SQu Wenruo 349ad7b0368SQu Wenruo /* dir type check */ 350ad7b0368SQu Wenruo dir_type = btrfs_dir_type(leaf, di); 351ad7b0368SQu Wenruo if (dir_type >= BTRFS_FT_MAX) { 352d98ced68SDavid Sterba dir_item_err(leaf, slot, 353ad7b0368SQu Wenruo "invalid dir item type, have %u expect [0, %u)", 354ad7b0368SQu Wenruo dir_type, BTRFS_FT_MAX); 355ad7b0368SQu Wenruo return -EUCLEAN; 356ad7b0368SQu Wenruo } 357ad7b0368SQu Wenruo 358ad7b0368SQu Wenruo if (key->type == BTRFS_XATTR_ITEM_KEY && 359ad7b0368SQu Wenruo dir_type != BTRFS_FT_XATTR) { 360d98ced68SDavid Sterba dir_item_err(leaf, slot, 361ad7b0368SQu Wenruo "invalid dir item type for XATTR key, have %u expect %u", 362ad7b0368SQu Wenruo dir_type, BTRFS_FT_XATTR); 363ad7b0368SQu Wenruo return -EUCLEAN; 364ad7b0368SQu Wenruo } 365ad7b0368SQu Wenruo if (dir_type == BTRFS_FT_XATTR && 366ad7b0368SQu Wenruo key->type != BTRFS_XATTR_ITEM_KEY) { 367d98ced68SDavid Sterba dir_item_err(leaf, slot, 368ad7b0368SQu Wenruo "xattr dir type found for non-XATTR key"); 369ad7b0368SQu Wenruo return -EUCLEAN; 370ad7b0368SQu Wenruo } 371ad7b0368SQu Wenruo if (dir_type == BTRFS_FT_XATTR) 372ad7b0368SQu Wenruo max_name_len = XATTR_NAME_MAX; 373ad7b0368SQu Wenruo else 374ad7b0368SQu Wenruo max_name_len = BTRFS_NAME_LEN; 375ad7b0368SQu Wenruo 376ad7b0368SQu Wenruo /* Name/data length check */ 377ad7b0368SQu Wenruo name_len = btrfs_dir_name_len(leaf, di); 378ad7b0368SQu Wenruo data_len = btrfs_dir_data_len(leaf, di); 379ad7b0368SQu Wenruo if (name_len > max_name_len) { 380d98ced68SDavid Sterba dir_item_err(leaf, slot, 381ad7b0368SQu Wenruo "dir item name len too long, have %u max %u", 382ad7b0368SQu Wenruo name_len, max_name_len); 383ad7b0368SQu Wenruo return -EUCLEAN; 384ad7b0368SQu Wenruo } 3852f659546SQu Wenruo if (name_len + data_len > BTRFS_MAX_XATTR_SIZE(fs_info)) { 386d98ced68SDavid Sterba dir_item_err(leaf, slot, 387ad7b0368SQu Wenruo "dir item name and data len too long, have %u max %u", 388ad7b0368SQu Wenruo name_len + data_len, 3892f659546SQu Wenruo BTRFS_MAX_XATTR_SIZE(fs_info)); 390ad7b0368SQu Wenruo return -EUCLEAN; 391ad7b0368SQu Wenruo } 392ad7b0368SQu Wenruo 393ad7b0368SQu Wenruo if (data_len && dir_type != BTRFS_FT_XATTR) { 394d98ced68SDavid Sterba dir_item_err(leaf, slot, 395ad7b0368SQu Wenruo "dir item with invalid data len, have %u expect 0", 396ad7b0368SQu Wenruo data_len); 397ad7b0368SQu Wenruo return -EUCLEAN; 398ad7b0368SQu Wenruo } 399ad7b0368SQu Wenruo 400ad7b0368SQu Wenruo total_size = sizeof(*di) + name_len + data_len; 401ad7b0368SQu Wenruo 402ad7b0368SQu Wenruo /* header and name/data should not cross item boundary */ 403ad7b0368SQu Wenruo if (cur + total_size > item_size) { 404d98ced68SDavid Sterba dir_item_err(leaf, slot, 405ad7b0368SQu Wenruo "dir item data crosses item boundary, have %u boundary %u", 406ad7b0368SQu Wenruo cur + total_size, item_size); 407ad7b0368SQu Wenruo return -EUCLEAN; 408ad7b0368SQu Wenruo } 409ad7b0368SQu Wenruo 410ad7b0368SQu Wenruo /* 411ad7b0368SQu Wenruo * Special check for XATTR/DIR_ITEM, as key->offset is name 412ad7b0368SQu Wenruo * hash, should match its name 413ad7b0368SQu Wenruo */ 414ad7b0368SQu Wenruo if (key->type == BTRFS_DIR_ITEM_KEY || 415ad7b0368SQu Wenruo key->type == BTRFS_XATTR_ITEM_KEY) { 416e2683fc9SDavid Sterba char namebuf[max(BTRFS_NAME_LEN, XATTR_NAME_MAX)]; 417e2683fc9SDavid Sterba 418ad7b0368SQu Wenruo read_extent_buffer(leaf, namebuf, 419ad7b0368SQu Wenruo (unsigned long)(di + 1), name_len); 420ad7b0368SQu Wenruo name_hash = btrfs_name_hash(namebuf, name_len); 421ad7b0368SQu Wenruo if (key->offset != name_hash) { 422d98ced68SDavid Sterba dir_item_err(leaf, slot, 423ad7b0368SQu Wenruo "name hash mismatch with key, have 0x%016x expect 0x%016llx", 424ad7b0368SQu Wenruo name_hash, key->offset); 425ad7b0368SQu Wenruo return -EUCLEAN; 426ad7b0368SQu Wenruo } 427ad7b0368SQu Wenruo } 428ad7b0368SQu Wenruo cur += total_size; 429ad7b0368SQu Wenruo di = (struct btrfs_dir_item *)((void *)di + total_size); 430ad7b0368SQu Wenruo } 431ad7b0368SQu Wenruo return 0; 432ad7b0368SQu Wenruo } 433ad7b0368SQu Wenruo 4344806bd88SDavid Sterba __printf(3, 4) 435fce466eaSQu Wenruo __cold 4364806bd88SDavid Sterba static void block_group_err(const struct extent_buffer *eb, int slot, 437fce466eaSQu Wenruo const char *fmt, ...) 438fce466eaSQu Wenruo { 4394806bd88SDavid Sterba const struct btrfs_fs_info *fs_info = eb->fs_info; 440fce466eaSQu Wenruo struct btrfs_key key; 441fce466eaSQu Wenruo struct va_format vaf; 442fce466eaSQu Wenruo va_list args; 443fce466eaSQu Wenruo 444fce466eaSQu Wenruo btrfs_item_key_to_cpu(eb, &key, slot); 445fce466eaSQu Wenruo va_start(args, fmt); 446fce466eaSQu Wenruo 447fce466eaSQu Wenruo vaf.fmt = fmt; 448fce466eaSQu Wenruo vaf.va = &args; 449fce466eaSQu Wenruo 450fce466eaSQu Wenruo btrfs_crit(fs_info, 451fce466eaSQu Wenruo "corrupt %s: root=%llu block=%llu slot=%d bg_start=%llu bg_len=%llu, %pV", 452fce466eaSQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 453fce466eaSQu Wenruo btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, 454fce466eaSQu Wenruo key.objectid, key.offset, &vaf); 455fce466eaSQu Wenruo va_end(args); 456fce466eaSQu Wenruo } 457fce466eaSQu Wenruo 458af60ce2bSDavid Sterba static int check_block_group_item(struct extent_buffer *leaf, 459fce466eaSQu Wenruo struct btrfs_key *key, int slot) 460fce466eaSQu Wenruo { 461fce466eaSQu Wenruo struct btrfs_block_group_item bgi; 462fce466eaSQu Wenruo u32 item_size = btrfs_item_size_nr(leaf, slot); 463fce466eaSQu Wenruo u64 flags; 464fce466eaSQu Wenruo u64 type; 465fce466eaSQu Wenruo 466fce466eaSQu Wenruo /* 467fce466eaSQu Wenruo * Here we don't really care about alignment since extent allocator can 46810950929SQu Wenruo * handle it. We care more about the size. 469fce466eaSQu Wenruo */ 47010950929SQu Wenruo if (key->offset == 0) { 4714806bd88SDavid Sterba block_group_err(leaf, slot, 47210950929SQu Wenruo "invalid block group size 0"); 473fce466eaSQu Wenruo return -EUCLEAN; 474fce466eaSQu Wenruo } 475fce466eaSQu Wenruo 476fce466eaSQu Wenruo if (item_size != sizeof(bgi)) { 4774806bd88SDavid Sterba block_group_err(leaf, slot, 478fce466eaSQu Wenruo "invalid item size, have %u expect %zu", 479fce466eaSQu Wenruo item_size, sizeof(bgi)); 480fce466eaSQu Wenruo return -EUCLEAN; 481fce466eaSQu Wenruo } 482fce466eaSQu Wenruo 483fce466eaSQu Wenruo read_extent_buffer(leaf, &bgi, btrfs_item_ptr_offset(leaf, slot), 484fce466eaSQu Wenruo sizeof(bgi)); 485fce466eaSQu Wenruo if (btrfs_block_group_chunk_objectid(&bgi) != 486fce466eaSQu Wenruo BTRFS_FIRST_CHUNK_TREE_OBJECTID) { 4874806bd88SDavid Sterba block_group_err(leaf, slot, 488fce466eaSQu Wenruo "invalid block group chunk objectid, have %llu expect %llu", 489fce466eaSQu Wenruo btrfs_block_group_chunk_objectid(&bgi), 490fce466eaSQu Wenruo BTRFS_FIRST_CHUNK_TREE_OBJECTID); 491fce466eaSQu Wenruo return -EUCLEAN; 492fce466eaSQu Wenruo } 493fce466eaSQu Wenruo 494fce466eaSQu Wenruo if (btrfs_block_group_used(&bgi) > key->offset) { 4954806bd88SDavid Sterba block_group_err(leaf, slot, 496fce466eaSQu Wenruo "invalid block group used, have %llu expect [0, %llu)", 497fce466eaSQu Wenruo btrfs_block_group_used(&bgi), key->offset); 498fce466eaSQu Wenruo return -EUCLEAN; 499fce466eaSQu Wenruo } 500fce466eaSQu Wenruo 501fce466eaSQu Wenruo flags = btrfs_block_group_flags(&bgi); 502fce466eaSQu Wenruo if (hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) > 1) { 5034806bd88SDavid Sterba block_group_err(leaf, slot, 504fce466eaSQu Wenruo "invalid profile flags, have 0x%llx (%lu bits set) expect no more than 1 bit set", 505fce466eaSQu Wenruo flags & BTRFS_BLOCK_GROUP_PROFILE_MASK, 506fce466eaSQu Wenruo hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK)); 507fce466eaSQu Wenruo return -EUCLEAN; 508fce466eaSQu Wenruo } 509fce466eaSQu Wenruo 510fce466eaSQu Wenruo type = flags & BTRFS_BLOCK_GROUP_TYPE_MASK; 511fce466eaSQu Wenruo if (type != BTRFS_BLOCK_GROUP_DATA && 512fce466eaSQu Wenruo type != BTRFS_BLOCK_GROUP_METADATA && 513fce466eaSQu Wenruo type != BTRFS_BLOCK_GROUP_SYSTEM && 514fce466eaSQu Wenruo type != (BTRFS_BLOCK_GROUP_METADATA | 515fce466eaSQu Wenruo BTRFS_BLOCK_GROUP_DATA)) { 5164806bd88SDavid Sterba block_group_err(leaf, slot, 517761333f2SShaokun Zhang "invalid type, have 0x%llx (%lu bits set) expect either 0x%llx, 0x%llx, 0x%llx or 0x%llx", 518fce466eaSQu Wenruo type, hweight64(type), 519fce466eaSQu Wenruo BTRFS_BLOCK_GROUP_DATA, BTRFS_BLOCK_GROUP_METADATA, 520fce466eaSQu Wenruo BTRFS_BLOCK_GROUP_SYSTEM, 521fce466eaSQu Wenruo BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA); 522fce466eaSQu Wenruo return -EUCLEAN; 523fce466eaSQu Wenruo } 524fce466eaSQu Wenruo return 0; 525fce466eaSQu Wenruo } 526fce466eaSQu Wenruo 527d001e4a3SDavid Sterba __printf(4, 5) 528f1140243SQu Wenruo __cold 529d001e4a3SDavid Sterba static void chunk_err(const struct extent_buffer *leaf, 530f1140243SQu Wenruo const struct btrfs_chunk *chunk, u64 logical, 531f1140243SQu Wenruo const char *fmt, ...) 532f1140243SQu Wenruo { 533d001e4a3SDavid Sterba const struct btrfs_fs_info *fs_info = leaf->fs_info; 534f1140243SQu Wenruo bool is_sb; 535f1140243SQu Wenruo struct va_format vaf; 536f1140243SQu Wenruo va_list args; 537f1140243SQu Wenruo int i; 538f1140243SQu Wenruo int slot = -1; 539f1140243SQu Wenruo 540f1140243SQu Wenruo /* Only superblock eb is able to have such small offset */ 541f1140243SQu Wenruo is_sb = (leaf->start == BTRFS_SUPER_INFO_OFFSET); 542f1140243SQu Wenruo 543f1140243SQu Wenruo if (!is_sb) { 544f1140243SQu Wenruo /* 545f1140243SQu Wenruo * Get the slot number by iterating through all slots, this 546f1140243SQu Wenruo * would provide better readability. 547f1140243SQu Wenruo */ 548f1140243SQu Wenruo for (i = 0; i < btrfs_header_nritems(leaf); i++) { 549f1140243SQu Wenruo if (btrfs_item_ptr_offset(leaf, i) == 550f1140243SQu Wenruo (unsigned long)chunk) { 551f1140243SQu Wenruo slot = i; 552f1140243SQu Wenruo break; 553f1140243SQu Wenruo } 554f1140243SQu Wenruo } 555f1140243SQu Wenruo } 556f1140243SQu Wenruo va_start(args, fmt); 557f1140243SQu Wenruo vaf.fmt = fmt; 558f1140243SQu Wenruo vaf.va = &args; 559f1140243SQu Wenruo 560f1140243SQu Wenruo if (is_sb) 561f1140243SQu Wenruo btrfs_crit(fs_info, 562f1140243SQu Wenruo "corrupt superblock syschunk array: chunk_start=%llu, %pV", 563f1140243SQu Wenruo logical, &vaf); 564f1140243SQu Wenruo else 565f1140243SQu Wenruo btrfs_crit(fs_info, 566f1140243SQu Wenruo "corrupt leaf: root=%llu block=%llu slot=%d chunk_start=%llu, %pV", 567f1140243SQu Wenruo BTRFS_CHUNK_TREE_OBJECTID, leaf->start, slot, 568f1140243SQu Wenruo logical, &vaf); 569f1140243SQu Wenruo va_end(args); 570f1140243SQu Wenruo } 571f1140243SQu Wenruo 572ad7b0368SQu Wenruo /* 57382fc28fbSQu Wenruo * The common chunk check which could also work on super block sys chunk array. 57482fc28fbSQu Wenruo * 575bf871c3bSQu Wenruo * Return -EUCLEAN if anything is corrupted. 57682fc28fbSQu Wenruo * Return 0 if everything is OK. 57782fc28fbSQu Wenruo */ 578ddaf1d5aSDavid Sterba int btrfs_check_chunk_valid(struct extent_buffer *leaf, 57982fc28fbSQu Wenruo struct btrfs_chunk *chunk, u64 logical) 58082fc28fbSQu Wenruo { 581ddaf1d5aSDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 58282fc28fbSQu Wenruo u64 length; 58382fc28fbSQu Wenruo u64 stripe_len; 58482fc28fbSQu Wenruo u16 num_stripes; 58582fc28fbSQu Wenruo u16 sub_stripes; 58682fc28fbSQu Wenruo u64 type; 58782fc28fbSQu Wenruo u64 features; 58882fc28fbSQu Wenruo bool mixed = false; 58982fc28fbSQu Wenruo 59082fc28fbSQu Wenruo length = btrfs_chunk_length(leaf, chunk); 59182fc28fbSQu Wenruo stripe_len = btrfs_chunk_stripe_len(leaf, chunk); 59282fc28fbSQu Wenruo num_stripes = btrfs_chunk_num_stripes(leaf, chunk); 59382fc28fbSQu Wenruo sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk); 59482fc28fbSQu Wenruo type = btrfs_chunk_type(leaf, chunk); 59582fc28fbSQu Wenruo 59682fc28fbSQu Wenruo if (!num_stripes) { 597d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 598f1140243SQu Wenruo "invalid chunk num_stripes, have %u", num_stripes); 599bf871c3bSQu Wenruo return -EUCLEAN; 60082fc28fbSQu Wenruo } 60182fc28fbSQu Wenruo if (!IS_ALIGNED(logical, fs_info->sectorsize)) { 602d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 603f1140243SQu Wenruo "invalid chunk logical, have %llu should aligned to %u", 604f1140243SQu Wenruo logical, fs_info->sectorsize); 605bf871c3bSQu Wenruo return -EUCLEAN; 60682fc28fbSQu Wenruo } 60782fc28fbSQu Wenruo if (btrfs_chunk_sector_size(leaf, chunk) != fs_info->sectorsize) { 608d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 609f1140243SQu Wenruo "invalid chunk sectorsize, have %u expect %u", 610f1140243SQu Wenruo btrfs_chunk_sector_size(leaf, chunk), 611f1140243SQu Wenruo fs_info->sectorsize); 612bf871c3bSQu Wenruo return -EUCLEAN; 61382fc28fbSQu Wenruo } 61482fc28fbSQu Wenruo if (!length || !IS_ALIGNED(length, fs_info->sectorsize)) { 615d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 616f1140243SQu Wenruo "invalid chunk length, have %llu", length); 617bf871c3bSQu Wenruo return -EUCLEAN; 61882fc28fbSQu Wenruo } 61982fc28fbSQu Wenruo if (!is_power_of_2(stripe_len) || stripe_len != BTRFS_STRIPE_LEN) { 620d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 621f1140243SQu Wenruo "invalid chunk stripe length: %llu", 62282fc28fbSQu Wenruo stripe_len); 623bf871c3bSQu Wenruo return -EUCLEAN; 62482fc28fbSQu Wenruo } 62582fc28fbSQu Wenruo if (~(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_PROFILE_MASK) & 62682fc28fbSQu Wenruo type) { 627d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 628f1140243SQu Wenruo "unrecognized chunk type: 0x%llx", 62982fc28fbSQu Wenruo ~(BTRFS_BLOCK_GROUP_TYPE_MASK | 63082fc28fbSQu Wenruo BTRFS_BLOCK_GROUP_PROFILE_MASK) & 63182fc28fbSQu Wenruo btrfs_chunk_type(leaf, chunk)); 632bf871c3bSQu Wenruo return -EUCLEAN; 63382fc28fbSQu Wenruo } 63482fc28fbSQu Wenruo 63580e46cf2SQu Wenruo if (!is_power_of_2(type & BTRFS_BLOCK_GROUP_PROFILE_MASK) && 63680e46cf2SQu Wenruo (type & BTRFS_BLOCK_GROUP_PROFILE_MASK) != 0) { 637d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 63880e46cf2SQu Wenruo "invalid chunk profile flag: 0x%llx, expect 0 or 1 bit set", 63980e46cf2SQu Wenruo type & BTRFS_BLOCK_GROUP_PROFILE_MASK); 64080e46cf2SQu Wenruo return -EUCLEAN; 64180e46cf2SQu Wenruo } 64282fc28fbSQu Wenruo if ((type & BTRFS_BLOCK_GROUP_TYPE_MASK) == 0) { 643d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 644f1140243SQu Wenruo "missing chunk type flag, have 0x%llx one bit must be set in 0x%llx", 645f1140243SQu Wenruo type, BTRFS_BLOCK_GROUP_TYPE_MASK); 646bf871c3bSQu Wenruo return -EUCLEAN; 64782fc28fbSQu Wenruo } 64882fc28fbSQu Wenruo 64982fc28fbSQu Wenruo if ((type & BTRFS_BLOCK_GROUP_SYSTEM) && 65082fc28fbSQu Wenruo (type & (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA))) { 651d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 652f1140243SQu Wenruo "system chunk with data or metadata type: 0x%llx", 653f1140243SQu Wenruo type); 654bf871c3bSQu Wenruo return -EUCLEAN; 65582fc28fbSQu Wenruo } 65682fc28fbSQu Wenruo 65782fc28fbSQu Wenruo features = btrfs_super_incompat_flags(fs_info->super_copy); 65882fc28fbSQu Wenruo if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) 65982fc28fbSQu Wenruo mixed = true; 66082fc28fbSQu Wenruo 66182fc28fbSQu Wenruo if (!mixed) { 66282fc28fbSQu Wenruo if ((type & BTRFS_BLOCK_GROUP_METADATA) && 66382fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_DATA)) { 664d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 66582fc28fbSQu Wenruo "mixed chunk type in non-mixed mode: 0x%llx", type); 666bf871c3bSQu Wenruo return -EUCLEAN; 66782fc28fbSQu Wenruo } 66882fc28fbSQu Wenruo } 66982fc28fbSQu Wenruo 67082fc28fbSQu Wenruo if ((type & BTRFS_BLOCK_GROUP_RAID10 && sub_stripes != 2) || 67182fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_RAID1 && num_stripes != 2) || 67282fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_RAID5 && num_stripes < 2) || 67382fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_RAID6 && num_stripes < 3) || 67482fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_DUP && num_stripes != 2) || 67582fc28fbSQu Wenruo ((type & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0 && num_stripes != 1)) { 676d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 67782fc28fbSQu Wenruo "invalid num_stripes:sub_stripes %u:%u for profile %llu", 67882fc28fbSQu Wenruo num_stripes, sub_stripes, 67982fc28fbSQu Wenruo type & BTRFS_BLOCK_GROUP_PROFILE_MASK); 680bf871c3bSQu Wenruo return -EUCLEAN; 68182fc28fbSQu Wenruo } 68282fc28fbSQu Wenruo 68382fc28fbSQu Wenruo return 0; 68482fc28fbSQu Wenruo } 68582fc28fbSQu Wenruo 6865617ed80SDavid Sterba __printf(3, 4) 687ab4ba2e1SQu Wenruo __cold 6885617ed80SDavid Sterba static void dev_item_err(const struct extent_buffer *eb, int slot, 689ab4ba2e1SQu Wenruo const char *fmt, ...) 690ab4ba2e1SQu Wenruo { 691ab4ba2e1SQu Wenruo struct btrfs_key key; 692ab4ba2e1SQu Wenruo struct va_format vaf; 693ab4ba2e1SQu Wenruo va_list args; 694ab4ba2e1SQu Wenruo 695ab4ba2e1SQu Wenruo btrfs_item_key_to_cpu(eb, &key, slot); 696ab4ba2e1SQu Wenruo va_start(args, fmt); 697ab4ba2e1SQu Wenruo 698ab4ba2e1SQu Wenruo vaf.fmt = fmt; 699ab4ba2e1SQu Wenruo vaf.va = &args; 700ab4ba2e1SQu Wenruo 7015617ed80SDavid Sterba btrfs_crit(eb->fs_info, 702ab4ba2e1SQu Wenruo "corrupt %s: root=%llu block=%llu slot=%d devid=%llu %pV", 703ab4ba2e1SQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 704ab4ba2e1SQu Wenruo btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, 705ab4ba2e1SQu Wenruo key.objectid, &vaf); 706ab4ba2e1SQu Wenruo va_end(args); 707ab4ba2e1SQu Wenruo } 708ab4ba2e1SQu Wenruo 709412a2312SDavid Sterba static int check_dev_item(struct extent_buffer *leaf, 710ab4ba2e1SQu Wenruo struct btrfs_key *key, int slot) 711ab4ba2e1SQu Wenruo { 712ab4ba2e1SQu Wenruo struct btrfs_dev_item *ditem; 713ab4ba2e1SQu Wenruo 714ab4ba2e1SQu Wenruo if (key->objectid != BTRFS_DEV_ITEMS_OBJECTID) { 7155617ed80SDavid Sterba dev_item_err(leaf, slot, 716ab4ba2e1SQu Wenruo "invalid objectid: has=%llu expect=%llu", 717ab4ba2e1SQu Wenruo key->objectid, BTRFS_DEV_ITEMS_OBJECTID); 718ab4ba2e1SQu Wenruo return -EUCLEAN; 719ab4ba2e1SQu Wenruo } 720ab4ba2e1SQu Wenruo ditem = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item); 721ab4ba2e1SQu Wenruo if (btrfs_device_id(leaf, ditem) != key->offset) { 7225617ed80SDavid Sterba dev_item_err(leaf, slot, 723ab4ba2e1SQu Wenruo "devid mismatch: key has=%llu item has=%llu", 724ab4ba2e1SQu Wenruo key->offset, btrfs_device_id(leaf, ditem)); 725ab4ba2e1SQu Wenruo return -EUCLEAN; 726ab4ba2e1SQu Wenruo } 727ab4ba2e1SQu Wenruo 728ab4ba2e1SQu Wenruo /* 729ab4ba2e1SQu Wenruo * For device total_bytes, we don't have reliable way to check it, as 730ab4ba2e1SQu Wenruo * it can be 0 for device removal. Device size check can only be done 731ab4ba2e1SQu Wenruo * by dev extents check. 732ab4ba2e1SQu Wenruo */ 733ab4ba2e1SQu Wenruo if (btrfs_device_bytes_used(leaf, ditem) > 734ab4ba2e1SQu Wenruo btrfs_device_total_bytes(leaf, ditem)) { 7355617ed80SDavid Sterba dev_item_err(leaf, slot, 736ab4ba2e1SQu Wenruo "invalid bytes used: have %llu expect [0, %llu]", 737ab4ba2e1SQu Wenruo btrfs_device_bytes_used(leaf, ditem), 738ab4ba2e1SQu Wenruo btrfs_device_total_bytes(leaf, ditem)); 739ab4ba2e1SQu Wenruo return -EUCLEAN; 740ab4ba2e1SQu Wenruo } 741ab4ba2e1SQu Wenruo /* 742ab4ba2e1SQu Wenruo * Remaining members like io_align/type/gen/dev_group aren't really 743ab4ba2e1SQu Wenruo * utilized. Skip them to make later usage of them easier. 744ab4ba2e1SQu Wenruo */ 745ab4ba2e1SQu Wenruo return 0; 746ab4ba2e1SQu Wenruo } 747ab4ba2e1SQu Wenruo 748496245caSQu Wenruo /* Inode item error output has the same format as dir_item_err() */ 749496245caSQu Wenruo #define inode_item_err(fs_info, eb, slot, fmt, ...) \ 750d98ced68SDavid Sterba dir_item_err(eb, slot, fmt, __VA_ARGS__) 751496245caSQu Wenruo 75239e57f49SDavid Sterba static int check_inode_item(struct extent_buffer *leaf, 753496245caSQu Wenruo struct btrfs_key *key, int slot) 754496245caSQu Wenruo { 75539e57f49SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 756496245caSQu Wenruo struct btrfs_inode_item *iitem; 757496245caSQu Wenruo u64 super_gen = btrfs_super_generation(fs_info->super_copy); 758496245caSQu Wenruo u32 valid_mask = (S_IFMT | S_ISUID | S_ISGID | S_ISVTX | 0777); 759496245caSQu Wenruo u32 mode; 760496245caSQu Wenruo 761496245caSQu Wenruo if ((key->objectid < BTRFS_FIRST_FREE_OBJECTID || 762496245caSQu Wenruo key->objectid > BTRFS_LAST_FREE_OBJECTID) && 763496245caSQu Wenruo key->objectid != BTRFS_ROOT_TREE_DIR_OBJECTID && 764496245caSQu Wenruo key->objectid != BTRFS_FREE_INO_OBJECTID) { 76586a6be3aSDavid Sterba generic_err(leaf, slot, 766496245caSQu Wenruo "invalid key objectid: has %llu expect %llu or [%llu, %llu] or %llu", 767496245caSQu Wenruo key->objectid, BTRFS_ROOT_TREE_DIR_OBJECTID, 768496245caSQu Wenruo BTRFS_FIRST_FREE_OBJECTID, 769496245caSQu Wenruo BTRFS_LAST_FREE_OBJECTID, 770496245caSQu Wenruo BTRFS_FREE_INO_OBJECTID); 771496245caSQu Wenruo return -EUCLEAN; 772496245caSQu Wenruo } 773496245caSQu Wenruo if (key->offset != 0) { 774496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 775496245caSQu Wenruo "invalid key offset: has %llu expect 0", 776496245caSQu Wenruo key->offset); 777496245caSQu Wenruo return -EUCLEAN; 778496245caSQu Wenruo } 779496245caSQu Wenruo iitem = btrfs_item_ptr(leaf, slot, struct btrfs_inode_item); 780496245caSQu Wenruo 781496245caSQu Wenruo /* Here we use super block generation + 1 to handle log tree */ 782496245caSQu Wenruo if (btrfs_inode_generation(leaf, iitem) > super_gen + 1) { 783496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 784496245caSQu Wenruo "invalid inode generation: has %llu expect (0, %llu]", 785496245caSQu Wenruo btrfs_inode_generation(leaf, iitem), 786496245caSQu Wenruo super_gen + 1); 787496245caSQu Wenruo return -EUCLEAN; 788496245caSQu Wenruo } 789496245caSQu Wenruo /* Note for ROOT_TREE_DIR_ITEM, mkfs could set its transid 0 */ 790496245caSQu Wenruo if (btrfs_inode_transid(leaf, iitem) > super_gen + 1) { 791496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 792496245caSQu Wenruo "invalid inode generation: has %llu expect [0, %llu]", 793496245caSQu Wenruo btrfs_inode_transid(leaf, iitem), super_gen + 1); 794496245caSQu Wenruo return -EUCLEAN; 795496245caSQu Wenruo } 796496245caSQu Wenruo 797496245caSQu Wenruo /* 798496245caSQu Wenruo * For size and nbytes it's better not to be too strict, as for dir 799496245caSQu Wenruo * item its size/nbytes can easily get wrong, but doesn't affect 800496245caSQu Wenruo * anything in the fs. So here we skip the check. 801496245caSQu Wenruo */ 802496245caSQu Wenruo mode = btrfs_inode_mode(leaf, iitem); 803496245caSQu Wenruo if (mode & ~valid_mask) { 804496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 805496245caSQu Wenruo "unknown mode bit detected: 0x%x", 806496245caSQu Wenruo mode & ~valid_mask); 807496245caSQu Wenruo return -EUCLEAN; 808496245caSQu Wenruo } 809496245caSQu Wenruo 810496245caSQu Wenruo /* 811496245caSQu Wenruo * S_IFMT is not bit mapped so we can't completely rely on is_power_of_2, 812496245caSQu Wenruo * but is_power_of_2() can save us from checking FIFO/CHR/DIR/REG. 813496245caSQu Wenruo * Only needs to check BLK, LNK and SOCKS 814496245caSQu Wenruo */ 815496245caSQu Wenruo if (!is_power_of_2(mode & S_IFMT)) { 816496245caSQu Wenruo if (!S_ISLNK(mode) && !S_ISBLK(mode) && !S_ISSOCK(mode)) { 817496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 818496245caSQu Wenruo "invalid mode: has 0%o expect valid S_IF* bit(s)", 819496245caSQu Wenruo mode & S_IFMT); 820496245caSQu Wenruo return -EUCLEAN; 821496245caSQu Wenruo } 822496245caSQu Wenruo } 823496245caSQu Wenruo if (S_ISDIR(mode) && btrfs_inode_nlink(leaf, iitem) > 1) { 824496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 825496245caSQu Wenruo "invalid nlink: has %u expect no more than 1 for dir", 826496245caSQu Wenruo btrfs_inode_nlink(leaf, iitem)); 827496245caSQu Wenruo return -EUCLEAN; 828496245caSQu Wenruo } 829496245caSQu Wenruo if (btrfs_inode_flags(leaf, iitem) & ~BTRFS_INODE_FLAG_MASK) { 830496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 831496245caSQu Wenruo "unknown flags detected: 0x%llx", 832496245caSQu Wenruo btrfs_inode_flags(leaf, iitem) & 833496245caSQu Wenruo ~BTRFS_INODE_FLAG_MASK); 834496245caSQu Wenruo return -EUCLEAN; 835496245caSQu Wenruo } 836496245caSQu Wenruo return 0; 837496245caSQu Wenruo } 838496245caSQu Wenruo 839259ee775SQu Wenruo static int check_root_item(struct extent_buffer *leaf, struct btrfs_key *key, 840259ee775SQu Wenruo int slot) 841259ee775SQu Wenruo { 842259ee775SQu Wenruo struct btrfs_fs_info *fs_info = leaf->fs_info; 843259ee775SQu Wenruo struct btrfs_root_item ri; 844259ee775SQu Wenruo const u64 valid_root_flags = BTRFS_ROOT_SUBVOL_RDONLY | 845259ee775SQu Wenruo BTRFS_ROOT_SUBVOL_DEAD; 846259ee775SQu Wenruo 847259ee775SQu Wenruo /* No such tree id */ 848259ee775SQu Wenruo if (key->objectid == 0) { 849259ee775SQu Wenruo generic_err(leaf, slot, "invalid root id 0"); 850259ee775SQu Wenruo return -EUCLEAN; 851259ee775SQu Wenruo } 852259ee775SQu Wenruo 853259ee775SQu Wenruo /* 854259ee775SQu Wenruo * Some older kernel may create ROOT_ITEM with non-zero offset, so here 855259ee775SQu Wenruo * we only check offset for reloc tree whose key->offset must be a 856259ee775SQu Wenruo * valid tree. 857259ee775SQu Wenruo */ 858259ee775SQu Wenruo if (key->objectid == BTRFS_TREE_RELOC_OBJECTID && key->offset == 0) { 859259ee775SQu Wenruo generic_err(leaf, slot, "invalid root id 0 for reloc tree"); 860259ee775SQu Wenruo return -EUCLEAN; 861259ee775SQu Wenruo } 862259ee775SQu Wenruo 863259ee775SQu Wenruo if (btrfs_item_size_nr(leaf, slot) != sizeof(ri)) { 864259ee775SQu Wenruo generic_err(leaf, slot, 865259ee775SQu Wenruo "invalid root item size, have %u expect %zu", 866259ee775SQu Wenruo btrfs_item_size_nr(leaf, slot), sizeof(ri)); 867259ee775SQu Wenruo } 868259ee775SQu Wenruo 869259ee775SQu Wenruo read_extent_buffer(leaf, &ri, btrfs_item_ptr_offset(leaf, slot), 870259ee775SQu Wenruo sizeof(ri)); 871259ee775SQu Wenruo 872259ee775SQu Wenruo /* Generation related */ 873259ee775SQu Wenruo if (btrfs_root_generation(&ri) > 874259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1) { 875259ee775SQu Wenruo generic_err(leaf, slot, 876259ee775SQu Wenruo "invalid root generation, have %llu expect (0, %llu]", 877259ee775SQu Wenruo btrfs_root_generation(&ri), 878259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1); 879259ee775SQu Wenruo return -EUCLEAN; 880259ee775SQu Wenruo } 881259ee775SQu Wenruo if (btrfs_root_generation_v2(&ri) > 882259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1) { 883259ee775SQu Wenruo generic_err(leaf, slot, 884259ee775SQu Wenruo "invalid root v2 generation, have %llu expect (0, %llu]", 885259ee775SQu Wenruo btrfs_root_generation_v2(&ri), 886259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1); 887259ee775SQu Wenruo return -EUCLEAN; 888259ee775SQu Wenruo } 889259ee775SQu Wenruo if (btrfs_root_last_snapshot(&ri) > 890259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1) { 891259ee775SQu Wenruo generic_err(leaf, slot, 892259ee775SQu Wenruo "invalid root last_snapshot, have %llu expect (0, %llu]", 893259ee775SQu Wenruo btrfs_root_last_snapshot(&ri), 894259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1); 895259ee775SQu Wenruo return -EUCLEAN; 896259ee775SQu Wenruo } 897259ee775SQu Wenruo 898259ee775SQu Wenruo /* Alignment and level check */ 899259ee775SQu Wenruo if (!IS_ALIGNED(btrfs_root_bytenr(&ri), fs_info->sectorsize)) { 900259ee775SQu Wenruo generic_err(leaf, slot, 901259ee775SQu Wenruo "invalid root bytenr, have %llu expect to be aligned to %u", 902259ee775SQu Wenruo btrfs_root_bytenr(&ri), fs_info->sectorsize); 903259ee775SQu Wenruo return -EUCLEAN; 904259ee775SQu Wenruo } 905259ee775SQu Wenruo if (btrfs_root_level(&ri) >= BTRFS_MAX_LEVEL) { 906259ee775SQu Wenruo generic_err(leaf, slot, 907259ee775SQu Wenruo "invalid root level, have %u expect [0, %u]", 908259ee775SQu Wenruo btrfs_root_level(&ri), BTRFS_MAX_LEVEL - 1); 909259ee775SQu Wenruo return -EUCLEAN; 910259ee775SQu Wenruo } 911259ee775SQu Wenruo if (ri.drop_level >= BTRFS_MAX_LEVEL) { 912259ee775SQu Wenruo generic_err(leaf, slot, 913259ee775SQu Wenruo "invalid root level, have %u expect [0, %u]", 914259ee775SQu Wenruo ri.drop_level, BTRFS_MAX_LEVEL - 1); 915259ee775SQu Wenruo return -EUCLEAN; 916259ee775SQu Wenruo } 917259ee775SQu Wenruo 918259ee775SQu Wenruo /* Flags check */ 919259ee775SQu Wenruo if (btrfs_root_flags(&ri) & ~valid_root_flags) { 920259ee775SQu Wenruo generic_err(leaf, slot, 921259ee775SQu Wenruo "invalid root flags, have 0x%llx expect mask 0x%llx", 922259ee775SQu Wenruo btrfs_root_flags(&ri), valid_root_flags); 923259ee775SQu Wenruo return -EUCLEAN; 924259ee775SQu Wenruo } 925259ee775SQu Wenruo return 0; 926259ee775SQu Wenruo } 927259ee775SQu Wenruo 928f82d1c7cSQu Wenruo __printf(3,4) 929f82d1c7cSQu Wenruo __cold 930f82d1c7cSQu Wenruo static void extent_err(const struct extent_buffer *eb, int slot, 931f82d1c7cSQu Wenruo const char *fmt, ...) 932f82d1c7cSQu Wenruo { 933f82d1c7cSQu Wenruo struct btrfs_key key; 934f82d1c7cSQu Wenruo struct va_format vaf; 935f82d1c7cSQu Wenruo va_list args; 936f82d1c7cSQu Wenruo u64 bytenr; 937f82d1c7cSQu Wenruo u64 len; 938f82d1c7cSQu Wenruo 939f82d1c7cSQu Wenruo btrfs_item_key_to_cpu(eb, &key, slot); 940f82d1c7cSQu Wenruo bytenr = key.objectid; 941e2406a6fSQu Wenruo if (key.type == BTRFS_METADATA_ITEM_KEY || 942e2406a6fSQu Wenruo key.type == BTRFS_TREE_BLOCK_REF_KEY || 943e2406a6fSQu Wenruo key.type == BTRFS_SHARED_BLOCK_REF_KEY) 944f82d1c7cSQu Wenruo len = eb->fs_info->nodesize; 945f82d1c7cSQu Wenruo else 946f82d1c7cSQu Wenruo len = key.offset; 947f82d1c7cSQu Wenruo va_start(args, fmt); 948f82d1c7cSQu Wenruo 949f82d1c7cSQu Wenruo vaf.fmt = fmt; 950f82d1c7cSQu Wenruo vaf.va = &args; 951f82d1c7cSQu Wenruo 952f82d1c7cSQu Wenruo btrfs_crit(eb->fs_info, 953f82d1c7cSQu Wenruo "corrupt %s: block=%llu slot=%d extent bytenr=%llu len=%llu %pV", 954f82d1c7cSQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 955f82d1c7cSQu Wenruo eb->start, slot, bytenr, len, &vaf); 956f82d1c7cSQu Wenruo va_end(args); 957f82d1c7cSQu Wenruo } 958f82d1c7cSQu Wenruo 959f82d1c7cSQu Wenruo static int check_extent_item(struct extent_buffer *leaf, 960f82d1c7cSQu Wenruo struct btrfs_key *key, int slot) 961f82d1c7cSQu Wenruo { 962f82d1c7cSQu Wenruo struct btrfs_fs_info *fs_info = leaf->fs_info; 963f82d1c7cSQu Wenruo struct btrfs_extent_item *ei; 964f82d1c7cSQu Wenruo bool is_tree_block = false; 965f82d1c7cSQu Wenruo unsigned long ptr; /* Current pointer inside inline refs */ 966f82d1c7cSQu Wenruo unsigned long end; /* Extent item end */ 967f82d1c7cSQu Wenruo const u32 item_size = btrfs_item_size_nr(leaf, slot); 968f82d1c7cSQu Wenruo u64 flags; 969f82d1c7cSQu Wenruo u64 generation; 970f82d1c7cSQu Wenruo u64 total_refs; /* Total refs in btrfs_extent_item */ 971f82d1c7cSQu Wenruo u64 inline_refs = 0; /* found total inline refs */ 972f82d1c7cSQu Wenruo 973f82d1c7cSQu Wenruo if (key->type == BTRFS_METADATA_ITEM_KEY && 974f82d1c7cSQu Wenruo !btrfs_fs_incompat(fs_info, SKINNY_METADATA)) { 975f82d1c7cSQu Wenruo generic_err(leaf, slot, 976f82d1c7cSQu Wenruo "invalid key type, METADATA_ITEM type invalid when SKINNY_METADATA feature disabled"); 977f82d1c7cSQu Wenruo return -EUCLEAN; 978f82d1c7cSQu Wenruo } 979f82d1c7cSQu Wenruo /* key->objectid is the bytenr for both key types */ 980f82d1c7cSQu Wenruo if (!IS_ALIGNED(key->objectid, fs_info->sectorsize)) { 981f82d1c7cSQu Wenruo generic_err(leaf, slot, 982f82d1c7cSQu Wenruo "invalid key objectid, have %llu expect to be aligned to %u", 983f82d1c7cSQu Wenruo key->objectid, fs_info->sectorsize); 984f82d1c7cSQu Wenruo return -EUCLEAN; 985f82d1c7cSQu Wenruo } 986f82d1c7cSQu Wenruo 987f82d1c7cSQu Wenruo /* key->offset is tree level for METADATA_ITEM_KEY */ 988f82d1c7cSQu Wenruo if (key->type == BTRFS_METADATA_ITEM_KEY && 989f82d1c7cSQu Wenruo key->offset >= BTRFS_MAX_LEVEL) { 990f82d1c7cSQu Wenruo extent_err(leaf, slot, 991f82d1c7cSQu Wenruo "invalid tree level, have %llu expect [0, %u]", 992f82d1c7cSQu Wenruo key->offset, BTRFS_MAX_LEVEL - 1); 993f82d1c7cSQu Wenruo return -EUCLEAN; 994f82d1c7cSQu Wenruo } 995f82d1c7cSQu Wenruo 996f82d1c7cSQu Wenruo /* 997f82d1c7cSQu Wenruo * EXTENT/METADATA_ITEM consists of: 998f82d1c7cSQu Wenruo * 1) One btrfs_extent_item 999f82d1c7cSQu Wenruo * Records the total refs, type and generation of the extent. 1000f82d1c7cSQu Wenruo * 1001f82d1c7cSQu Wenruo * 2) One btrfs_tree_block_info (for EXTENT_ITEM and tree backref only) 1002f82d1c7cSQu Wenruo * Records the first key and level of the tree block. 1003f82d1c7cSQu Wenruo * 1004f82d1c7cSQu Wenruo * 2) Zero or more btrfs_extent_inline_ref(s) 1005f82d1c7cSQu Wenruo * Each inline ref has one btrfs_extent_inline_ref shows: 1006f82d1c7cSQu Wenruo * 2.1) The ref type, one of the 4 1007f82d1c7cSQu Wenruo * TREE_BLOCK_REF Tree block only 1008f82d1c7cSQu Wenruo * SHARED_BLOCK_REF Tree block only 1009f82d1c7cSQu Wenruo * EXTENT_DATA_REF Data only 1010f82d1c7cSQu Wenruo * SHARED_DATA_REF Data only 1011f82d1c7cSQu Wenruo * 2.2) Ref type specific data 1012f82d1c7cSQu Wenruo * Either using btrfs_extent_inline_ref::offset, or specific 1013f82d1c7cSQu Wenruo * data structure. 1014f82d1c7cSQu Wenruo */ 1015f82d1c7cSQu Wenruo if (item_size < sizeof(*ei)) { 1016f82d1c7cSQu Wenruo extent_err(leaf, slot, 1017f82d1c7cSQu Wenruo "invalid item size, have %u expect [%zu, %u)", 1018f82d1c7cSQu Wenruo item_size, sizeof(*ei), 1019f82d1c7cSQu Wenruo BTRFS_LEAF_DATA_SIZE(fs_info)); 1020f82d1c7cSQu Wenruo return -EUCLEAN; 1021f82d1c7cSQu Wenruo } 1022f82d1c7cSQu Wenruo end = item_size + btrfs_item_ptr_offset(leaf, slot); 1023f82d1c7cSQu Wenruo 1024f82d1c7cSQu Wenruo /* Checks against extent_item */ 1025f82d1c7cSQu Wenruo ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item); 1026f82d1c7cSQu Wenruo flags = btrfs_extent_flags(leaf, ei); 1027f82d1c7cSQu Wenruo total_refs = btrfs_extent_refs(leaf, ei); 1028f82d1c7cSQu Wenruo generation = btrfs_extent_generation(leaf, ei); 1029f82d1c7cSQu Wenruo if (generation > btrfs_super_generation(fs_info->super_copy) + 1) { 1030f82d1c7cSQu Wenruo extent_err(leaf, slot, 1031f82d1c7cSQu Wenruo "invalid generation, have %llu expect (0, %llu]", 1032f82d1c7cSQu Wenruo generation, 1033f82d1c7cSQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1); 1034f82d1c7cSQu Wenruo return -EUCLEAN; 1035f82d1c7cSQu Wenruo } 1036f82d1c7cSQu Wenruo if (!is_power_of_2(flags & (BTRFS_EXTENT_FLAG_DATA | 1037f82d1c7cSQu Wenruo BTRFS_EXTENT_FLAG_TREE_BLOCK))) { 1038f82d1c7cSQu Wenruo extent_err(leaf, slot, 1039f82d1c7cSQu Wenruo "invalid extent flag, have 0x%llx expect 1 bit set in 0x%llx", 1040f82d1c7cSQu Wenruo flags, BTRFS_EXTENT_FLAG_DATA | 1041f82d1c7cSQu Wenruo BTRFS_EXTENT_FLAG_TREE_BLOCK); 1042f82d1c7cSQu Wenruo return -EUCLEAN; 1043f82d1c7cSQu Wenruo } 1044f82d1c7cSQu Wenruo is_tree_block = !!(flags & BTRFS_EXTENT_FLAG_TREE_BLOCK); 1045f82d1c7cSQu Wenruo if (is_tree_block) { 1046f82d1c7cSQu Wenruo if (key->type == BTRFS_EXTENT_ITEM_KEY && 1047f82d1c7cSQu Wenruo key->offset != fs_info->nodesize) { 1048f82d1c7cSQu Wenruo extent_err(leaf, slot, 1049f82d1c7cSQu Wenruo "invalid extent length, have %llu expect %u", 1050f82d1c7cSQu Wenruo key->offset, fs_info->nodesize); 1051f82d1c7cSQu Wenruo return -EUCLEAN; 1052f82d1c7cSQu Wenruo } 1053f82d1c7cSQu Wenruo } else { 1054f82d1c7cSQu Wenruo if (key->type != BTRFS_EXTENT_ITEM_KEY) { 1055f82d1c7cSQu Wenruo extent_err(leaf, slot, 1056f82d1c7cSQu Wenruo "invalid key type, have %u expect %u for data backref", 1057f82d1c7cSQu Wenruo key->type, BTRFS_EXTENT_ITEM_KEY); 1058f82d1c7cSQu Wenruo return -EUCLEAN; 1059f82d1c7cSQu Wenruo } 1060f82d1c7cSQu Wenruo if (!IS_ALIGNED(key->offset, fs_info->sectorsize)) { 1061f82d1c7cSQu Wenruo extent_err(leaf, slot, 1062f82d1c7cSQu Wenruo "invalid extent length, have %llu expect aligned to %u", 1063f82d1c7cSQu Wenruo key->offset, fs_info->sectorsize); 1064f82d1c7cSQu Wenruo return -EUCLEAN; 1065f82d1c7cSQu Wenruo } 1066f82d1c7cSQu Wenruo } 1067f82d1c7cSQu Wenruo ptr = (unsigned long)(struct btrfs_extent_item *)(ei + 1); 1068f82d1c7cSQu Wenruo 1069f82d1c7cSQu Wenruo /* Check the special case of btrfs_tree_block_info */ 1070f82d1c7cSQu Wenruo if (is_tree_block && key->type != BTRFS_METADATA_ITEM_KEY) { 1071f82d1c7cSQu Wenruo struct btrfs_tree_block_info *info; 1072f82d1c7cSQu Wenruo 1073f82d1c7cSQu Wenruo info = (struct btrfs_tree_block_info *)ptr; 1074f82d1c7cSQu Wenruo if (btrfs_tree_block_level(leaf, info) >= BTRFS_MAX_LEVEL) { 1075f82d1c7cSQu Wenruo extent_err(leaf, slot, 1076f82d1c7cSQu Wenruo "invalid tree block info level, have %u expect [0, %u]", 1077f82d1c7cSQu Wenruo btrfs_tree_block_level(leaf, info), 1078f82d1c7cSQu Wenruo BTRFS_MAX_LEVEL - 1); 1079f82d1c7cSQu Wenruo return -EUCLEAN; 1080f82d1c7cSQu Wenruo } 1081f82d1c7cSQu Wenruo ptr = (unsigned long)(struct btrfs_tree_block_info *)(info + 1); 1082f82d1c7cSQu Wenruo } 1083f82d1c7cSQu Wenruo 1084f82d1c7cSQu Wenruo /* Check inline refs */ 1085f82d1c7cSQu Wenruo while (ptr < end) { 1086f82d1c7cSQu Wenruo struct btrfs_extent_inline_ref *iref; 1087f82d1c7cSQu Wenruo struct btrfs_extent_data_ref *dref; 1088f82d1c7cSQu Wenruo struct btrfs_shared_data_ref *sref; 1089f82d1c7cSQu Wenruo u64 dref_offset; 1090f82d1c7cSQu Wenruo u64 inline_offset; 1091f82d1c7cSQu Wenruo u8 inline_type; 1092f82d1c7cSQu Wenruo 1093f82d1c7cSQu Wenruo if (ptr + sizeof(*iref) > end) { 1094f82d1c7cSQu Wenruo extent_err(leaf, slot, 1095f82d1c7cSQu Wenruo "inline ref item overflows extent item, ptr %lu iref size %zu end %lu", 1096f82d1c7cSQu Wenruo ptr, sizeof(*iref), end); 1097f82d1c7cSQu Wenruo return -EUCLEAN; 1098f82d1c7cSQu Wenruo } 1099f82d1c7cSQu Wenruo iref = (struct btrfs_extent_inline_ref *)ptr; 1100f82d1c7cSQu Wenruo inline_type = btrfs_extent_inline_ref_type(leaf, iref); 1101f82d1c7cSQu Wenruo inline_offset = btrfs_extent_inline_ref_offset(leaf, iref); 1102f82d1c7cSQu Wenruo if (ptr + btrfs_extent_inline_ref_size(inline_type) > end) { 1103f82d1c7cSQu Wenruo extent_err(leaf, slot, 1104f82d1c7cSQu Wenruo "inline ref item overflows extent item, ptr %lu iref size %u end %lu", 1105f82d1c7cSQu Wenruo ptr, inline_type, end); 1106f82d1c7cSQu Wenruo return -EUCLEAN; 1107f82d1c7cSQu Wenruo } 1108f82d1c7cSQu Wenruo 1109f82d1c7cSQu Wenruo switch (inline_type) { 1110f82d1c7cSQu Wenruo /* inline_offset is subvolid of the owner, no need to check */ 1111f82d1c7cSQu Wenruo case BTRFS_TREE_BLOCK_REF_KEY: 1112f82d1c7cSQu Wenruo inline_refs++; 1113f82d1c7cSQu Wenruo break; 1114f82d1c7cSQu Wenruo /* Contains parent bytenr */ 1115f82d1c7cSQu Wenruo case BTRFS_SHARED_BLOCK_REF_KEY: 1116f82d1c7cSQu Wenruo if (!IS_ALIGNED(inline_offset, fs_info->sectorsize)) { 1117f82d1c7cSQu Wenruo extent_err(leaf, slot, 1118f82d1c7cSQu Wenruo "invalid tree parent bytenr, have %llu expect aligned to %u", 1119f82d1c7cSQu Wenruo inline_offset, fs_info->sectorsize); 1120f82d1c7cSQu Wenruo return -EUCLEAN; 1121f82d1c7cSQu Wenruo } 1122f82d1c7cSQu Wenruo inline_refs++; 1123f82d1c7cSQu Wenruo break; 1124f82d1c7cSQu Wenruo /* 1125f82d1c7cSQu Wenruo * Contains owner subvolid, owner key objectid, adjusted offset. 1126f82d1c7cSQu Wenruo * The only obvious corruption can happen in that offset. 1127f82d1c7cSQu Wenruo */ 1128f82d1c7cSQu Wenruo case BTRFS_EXTENT_DATA_REF_KEY: 1129f82d1c7cSQu Wenruo dref = (struct btrfs_extent_data_ref *)(&iref->offset); 1130f82d1c7cSQu Wenruo dref_offset = btrfs_extent_data_ref_offset(leaf, dref); 1131f82d1c7cSQu Wenruo if (!IS_ALIGNED(dref_offset, fs_info->sectorsize)) { 1132f82d1c7cSQu Wenruo extent_err(leaf, slot, 1133f82d1c7cSQu Wenruo "invalid data ref offset, have %llu expect aligned to %u", 1134f82d1c7cSQu Wenruo dref_offset, fs_info->sectorsize); 1135f82d1c7cSQu Wenruo return -EUCLEAN; 1136f82d1c7cSQu Wenruo } 1137f82d1c7cSQu Wenruo inline_refs += btrfs_extent_data_ref_count(leaf, dref); 1138f82d1c7cSQu Wenruo break; 1139f82d1c7cSQu Wenruo /* Contains parent bytenr and ref count */ 1140f82d1c7cSQu Wenruo case BTRFS_SHARED_DATA_REF_KEY: 1141f82d1c7cSQu Wenruo sref = (struct btrfs_shared_data_ref *)(iref + 1); 1142f82d1c7cSQu Wenruo if (!IS_ALIGNED(inline_offset, fs_info->sectorsize)) { 1143f82d1c7cSQu Wenruo extent_err(leaf, slot, 1144f82d1c7cSQu Wenruo "invalid data parent bytenr, have %llu expect aligned to %u", 1145f82d1c7cSQu Wenruo inline_offset, fs_info->sectorsize); 1146f82d1c7cSQu Wenruo return -EUCLEAN; 1147f82d1c7cSQu Wenruo } 1148f82d1c7cSQu Wenruo inline_refs += btrfs_shared_data_ref_count(leaf, sref); 1149f82d1c7cSQu Wenruo break; 1150f82d1c7cSQu Wenruo default: 1151f82d1c7cSQu Wenruo extent_err(leaf, slot, "unknown inline ref type: %u", 1152f82d1c7cSQu Wenruo inline_type); 1153f82d1c7cSQu Wenruo return -EUCLEAN; 1154f82d1c7cSQu Wenruo } 1155f82d1c7cSQu Wenruo ptr += btrfs_extent_inline_ref_size(inline_type); 1156f82d1c7cSQu Wenruo } 1157f82d1c7cSQu Wenruo /* No padding is allowed */ 1158f82d1c7cSQu Wenruo if (ptr != end) { 1159f82d1c7cSQu Wenruo extent_err(leaf, slot, 1160f82d1c7cSQu Wenruo "invalid extent item size, padding bytes found"); 1161f82d1c7cSQu Wenruo return -EUCLEAN; 1162f82d1c7cSQu Wenruo } 1163f82d1c7cSQu Wenruo 1164f82d1c7cSQu Wenruo /* Finally, check the inline refs against total refs */ 1165f82d1c7cSQu Wenruo if (inline_refs > total_refs) { 1166f82d1c7cSQu Wenruo extent_err(leaf, slot, 1167f82d1c7cSQu Wenruo "invalid extent refs, have %llu expect >= inline %llu", 1168f82d1c7cSQu Wenruo total_refs, inline_refs); 1169f82d1c7cSQu Wenruo return -EUCLEAN; 1170f82d1c7cSQu Wenruo } 1171f82d1c7cSQu Wenruo return 0; 1172f82d1c7cSQu Wenruo } 1173f82d1c7cSQu Wenruo 1174e2406a6fSQu Wenruo static int check_simple_keyed_refs(struct extent_buffer *leaf, 1175e2406a6fSQu Wenruo struct btrfs_key *key, int slot) 1176e2406a6fSQu Wenruo { 1177e2406a6fSQu Wenruo u32 expect_item_size = 0; 1178e2406a6fSQu Wenruo 1179e2406a6fSQu Wenruo if (key->type == BTRFS_SHARED_DATA_REF_KEY) 1180e2406a6fSQu Wenruo expect_item_size = sizeof(struct btrfs_shared_data_ref); 1181e2406a6fSQu Wenruo 1182e2406a6fSQu Wenruo if (btrfs_item_size_nr(leaf, slot) != expect_item_size) { 1183e2406a6fSQu Wenruo generic_err(leaf, slot, 1184e2406a6fSQu Wenruo "invalid item size, have %u expect %u for key type %u", 1185e2406a6fSQu Wenruo btrfs_item_size_nr(leaf, slot), 1186e2406a6fSQu Wenruo expect_item_size, key->type); 1187e2406a6fSQu Wenruo return -EUCLEAN; 1188e2406a6fSQu Wenruo } 1189e2406a6fSQu Wenruo if (!IS_ALIGNED(key->objectid, leaf->fs_info->sectorsize)) { 1190e2406a6fSQu Wenruo generic_err(leaf, slot, 1191e2406a6fSQu Wenruo "invalid key objectid for shared block ref, have %llu expect aligned to %u", 1192e2406a6fSQu Wenruo key->objectid, leaf->fs_info->sectorsize); 1193e2406a6fSQu Wenruo return -EUCLEAN; 1194e2406a6fSQu Wenruo } 1195e2406a6fSQu Wenruo if (key->type != BTRFS_TREE_BLOCK_REF_KEY && 1196e2406a6fSQu Wenruo !IS_ALIGNED(key->offset, leaf->fs_info->sectorsize)) { 1197e2406a6fSQu Wenruo extent_err(leaf, slot, 1198e2406a6fSQu Wenruo "invalid tree parent bytenr, have %llu expect aligned to %u", 1199e2406a6fSQu Wenruo key->offset, leaf->fs_info->sectorsize); 1200e2406a6fSQu Wenruo return -EUCLEAN; 1201e2406a6fSQu Wenruo } 1202e2406a6fSQu Wenruo return 0; 1203e2406a6fSQu Wenruo } 1204e2406a6fSQu Wenruo 12050785a9aaSQu Wenruo static int check_extent_data_ref(struct extent_buffer *leaf, 12060785a9aaSQu Wenruo struct btrfs_key *key, int slot) 12070785a9aaSQu Wenruo { 12080785a9aaSQu Wenruo struct btrfs_extent_data_ref *dref; 12090785a9aaSQu Wenruo unsigned long ptr = btrfs_item_ptr_offset(leaf, slot); 12100785a9aaSQu Wenruo const unsigned long end = ptr + btrfs_item_size_nr(leaf, slot); 12110785a9aaSQu Wenruo 12120785a9aaSQu Wenruo if (btrfs_item_size_nr(leaf, slot) % sizeof(*dref) != 0) { 12130785a9aaSQu Wenruo generic_err(leaf, slot, 12140785a9aaSQu Wenruo "invalid item size, have %u expect aligned to %zu for key type %u", 12150785a9aaSQu Wenruo btrfs_item_size_nr(leaf, slot), 12160785a9aaSQu Wenruo sizeof(*dref), key->type); 12170785a9aaSQu Wenruo } 12180785a9aaSQu Wenruo if (!IS_ALIGNED(key->objectid, leaf->fs_info->sectorsize)) { 12190785a9aaSQu Wenruo generic_err(leaf, slot, 12200785a9aaSQu Wenruo "invalid key objectid for shared block ref, have %llu expect aligned to %u", 12210785a9aaSQu Wenruo key->objectid, leaf->fs_info->sectorsize); 12220785a9aaSQu Wenruo return -EUCLEAN; 12230785a9aaSQu Wenruo } 12240785a9aaSQu Wenruo for (; ptr < end; ptr += sizeof(*dref)) { 12250785a9aaSQu Wenruo u64 root_objectid; 12260785a9aaSQu Wenruo u64 owner; 12270785a9aaSQu Wenruo u64 offset; 12280785a9aaSQu Wenruo u64 hash; 12290785a9aaSQu Wenruo 12300785a9aaSQu Wenruo dref = (struct btrfs_extent_data_ref *)ptr; 12310785a9aaSQu Wenruo root_objectid = btrfs_extent_data_ref_root(leaf, dref); 12320785a9aaSQu Wenruo owner = btrfs_extent_data_ref_objectid(leaf, dref); 12330785a9aaSQu Wenruo offset = btrfs_extent_data_ref_offset(leaf, dref); 12340785a9aaSQu Wenruo hash = hash_extent_data_ref(root_objectid, owner, offset); 12350785a9aaSQu Wenruo if (hash != key->offset) { 12360785a9aaSQu Wenruo extent_err(leaf, slot, 12370785a9aaSQu Wenruo "invalid extent data ref hash, item has 0x%016llx key has 0x%016llx", 12380785a9aaSQu Wenruo hash, key->offset); 12390785a9aaSQu Wenruo return -EUCLEAN; 12400785a9aaSQu Wenruo } 12410785a9aaSQu Wenruo if (!IS_ALIGNED(offset, leaf->fs_info->sectorsize)) { 12420785a9aaSQu Wenruo extent_err(leaf, slot, 12430785a9aaSQu Wenruo "invalid extent data backref offset, have %llu expect aligned to %u", 12440785a9aaSQu Wenruo offset, leaf->fs_info->sectorsize); 12450785a9aaSQu Wenruo } 12460785a9aaSQu Wenruo } 12470785a9aaSQu Wenruo return 0; 12480785a9aaSQu Wenruo } 12490785a9aaSQu Wenruo 1250*71bf92a9SQu Wenruo #define inode_ref_err(fs_info, eb, slot, fmt, args...) \ 1251*71bf92a9SQu Wenruo inode_item_err(fs_info, eb, slot, fmt, ##args) 1252*71bf92a9SQu Wenruo static int check_inode_ref(struct extent_buffer *leaf, 1253*71bf92a9SQu Wenruo struct btrfs_key *key, struct btrfs_key *prev_key, 1254*71bf92a9SQu Wenruo int slot) 1255*71bf92a9SQu Wenruo { 1256*71bf92a9SQu Wenruo struct btrfs_inode_ref *iref; 1257*71bf92a9SQu Wenruo unsigned long ptr; 1258*71bf92a9SQu Wenruo unsigned long end; 1259*71bf92a9SQu Wenruo 1260*71bf92a9SQu Wenruo /* namelen can't be 0, so item_size == sizeof() is also invalid */ 1261*71bf92a9SQu Wenruo if (btrfs_item_size_nr(leaf, slot) <= sizeof(*iref)) { 1262*71bf92a9SQu Wenruo inode_ref_err(fs_info, leaf, slot, 1263*71bf92a9SQu Wenruo "invalid item size, have %u expect (%zu, %u)", 1264*71bf92a9SQu Wenruo btrfs_item_size_nr(leaf, slot), 1265*71bf92a9SQu Wenruo sizeof(*iref), BTRFS_LEAF_DATA_SIZE(leaf->fs_info)); 1266*71bf92a9SQu Wenruo return -EUCLEAN; 1267*71bf92a9SQu Wenruo } 1268*71bf92a9SQu Wenruo 1269*71bf92a9SQu Wenruo ptr = btrfs_item_ptr_offset(leaf, slot); 1270*71bf92a9SQu Wenruo end = ptr + btrfs_item_size_nr(leaf, slot); 1271*71bf92a9SQu Wenruo while (ptr < end) { 1272*71bf92a9SQu Wenruo u16 namelen; 1273*71bf92a9SQu Wenruo 1274*71bf92a9SQu Wenruo if (ptr + sizeof(iref) > end) { 1275*71bf92a9SQu Wenruo inode_ref_err(fs_info, leaf, slot, 1276*71bf92a9SQu Wenruo "inode ref overflow, ptr %lu end %lu inode_ref_size %zu", 1277*71bf92a9SQu Wenruo ptr, end, sizeof(iref)); 1278*71bf92a9SQu Wenruo return -EUCLEAN; 1279*71bf92a9SQu Wenruo } 1280*71bf92a9SQu Wenruo 1281*71bf92a9SQu Wenruo iref = (struct btrfs_inode_ref *)ptr; 1282*71bf92a9SQu Wenruo namelen = btrfs_inode_ref_name_len(leaf, iref); 1283*71bf92a9SQu Wenruo if (ptr + sizeof(*iref) + namelen > end) { 1284*71bf92a9SQu Wenruo inode_ref_err(fs_info, leaf, slot, 1285*71bf92a9SQu Wenruo "inode ref overflow, ptr %lu end %lu namelen %u", 1286*71bf92a9SQu Wenruo ptr, end, namelen); 1287*71bf92a9SQu Wenruo return -EUCLEAN; 1288*71bf92a9SQu Wenruo } 1289*71bf92a9SQu Wenruo 1290*71bf92a9SQu Wenruo /* 1291*71bf92a9SQu Wenruo * NOTE: In theory we should record all found index numbers 1292*71bf92a9SQu Wenruo * to find any duplicated indexes, but that will be too time 1293*71bf92a9SQu Wenruo * consuming for inodes with too many hard links. 1294*71bf92a9SQu Wenruo */ 1295*71bf92a9SQu Wenruo ptr += sizeof(*iref) + namelen; 1296*71bf92a9SQu Wenruo } 1297*71bf92a9SQu Wenruo return 0; 1298*71bf92a9SQu Wenruo } 1299*71bf92a9SQu Wenruo 130082fc28fbSQu Wenruo /* 1301557ea5ddSQu Wenruo * Common point to switch the item-specific validation. 1302557ea5ddSQu Wenruo */ 13030076bc89SDavid Sterba static int check_leaf_item(struct extent_buffer *leaf, 13044e9845efSFilipe Manana struct btrfs_key *key, int slot, 13054e9845efSFilipe Manana struct btrfs_key *prev_key) 1306557ea5ddSQu Wenruo { 1307557ea5ddSQu Wenruo int ret = 0; 1308075cb3c7SQu Wenruo struct btrfs_chunk *chunk; 1309557ea5ddSQu Wenruo 1310557ea5ddSQu Wenruo switch (key->type) { 1311557ea5ddSQu Wenruo case BTRFS_EXTENT_DATA_KEY: 13124e9845efSFilipe Manana ret = check_extent_data_item(leaf, key, slot, prev_key); 1313557ea5ddSQu Wenruo break; 1314557ea5ddSQu Wenruo case BTRFS_EXTENT_CSUM_KEY: 131568128ce7SDavid Sterba ret = check_csum_item(leaf, key, slot); 1316557ea5ddSQu Wenruo break; 1317ad7b0368SQu Wenruo case BTRFS_DIR_ITEM_KEY: 1318ad7b0368SQu Wenruo case BTRFS_DIR_INDEX_KEY: 1319ad7b0368SQu Wenruo case BTRFS_XATTR_ITEM_KEY: 1320c18679ebSQu Wenruo ret = check_dir_item(leaf, key, prev_key, slot); 1321ad7b0368SQu Wenruo break; 1322*71bf92a9SQu Wenruo case BTRFS_INODE_REF_KEY: 1323*71bf92a9SQu Wenruo ret = check_inode_ref(leaf, key, prev_key, slot); 1324*71bf92a9SQu Wenruo break; 1325fce466eaSQu Wenruo case BTRFS_BLOCK_GROUP_ITEM_KEY: 1326af60ce2bSDavid Sterba ret = check_block_group_item(leaf, key, slot); 1327fce466eaSQu Wenruo break; 1328075cb3c7SQu Wenruo case BTRFS_CHUNK_ITEM_KEY: 1329075cb3c7SQu Wenruo chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); 1330ddaf1d5aSDavid Sterba ret = btrfs_check_chunk_valid(leaf, chunk, key->offset); 1331075cb3c7SQu Wenruo break; 1332ab4ba2e1SQu Wenruo case BTRFS_DEV_ITEM_KEY: 1333412a2312SDavid Sterba ret = check_dev_item(leaf, key, slot); 1334ab4ba2e1SQu Wenruo break; 1335496245caSQu Wenruo case BTRFS_INODE_ITEM_KEY: 133639e57f49SDavid Sterba ret = check_inode_item(leaf, key, slot); 1337496245caSQu Wenruo break; 1338259ee775SQu Wenruo case BTRFS_ROOT_ITEM_KEY: 1339259ee775SQu Wenruo ret = check_root_item(leaf, key, slot); 1340259ee775SQu Wenruo break; 1341f82d1c7cSQu Wenruo case BTRFS_EXTENT_ITEM_KEY: 1342f82d1c7cSQu Wenruo case BTRFS_METADATA_ITEM_KEY: 1343f82d1c7cSQu Wenruo ret = check_extent_item(leaf, key, slot); 1344f82d1c7cSQu Wenruo break; 1345e2406a6fSQu Wenruo case BTRFS_TREE_BLOCK_REF_KEY: 1346e2406a6fSQu Wenruo case BTRFS_SHARED_DATA_REF_KEY: 1347e2406a6fSQu Wenruo case BTRFS_SHARED_BLOCK_REF_KEY: 1348e2406a6fSQu Wenruo ret = check_simple_keyed_refs(leaf, key, slot); 1349e2406a6fSQu Wenruo break; 13500785a9aaSQu Wenruo case BTRFS_EXTENT_DATA_REF_KEY: 13510785a9aaSQu Wenruo ret = check_extent_data_ref(leaf, key, slot); 13520785a9aaSQu Wenruo break; 1353557ea5ddSQu Wenruo } 1354557ea5ddSQu Wenruo return ret; 1355557ea5ddSQu Wenruo } 1356557ea5ddSQu Wenruo 1357e2ccd361SDavid Sterba static int check_leaf(struct extent_buffer *leaf, bool check_item_data) 1358557ea5ddSQu Wenruo { 1359e2ccd361SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 1360557ea5ddSQu Wenruo /* No valid key type is 0, so all key should be larger than this key */ 1361557ea5ddSQu Wenruo struct btrfs_key prev_key = {0, 0, 0}; 1362557ea5ddSQu Wenruo struct btrfs_key key; 1363557ea5ddSQu Wenruo u32 nritems = btrfs_header_nritems(leaf); 1364557ea5ddSQu Wenruo int slot; 1365557ea5ddSQu Wenruo 1366f556faa4SQu Wenruo if (btrfs_header_level(leaf) != 0) { 136786a6be3aSDavid Sterba generic_err(leaf, 0, 1368f556faa4SQu Wenruo "invalid level for leaf, have %d expect 0", 1369f556faa4SQu Wenruo btrfs_header_level(leaf)); 1370f556faa4SQu Wenruo return -EUCLEAN; 1371f556faa4SQu Wenruo } 1372f556faa4SQu Wenruo 1373557ea5ddSQu Wenruo /* 1374557ea5ddSQu Wenruo * Extent buffers from a relocation tree have a owner field that 1375557ea5ddSQu Wenruo * corresponds to the subvolume tree they are based on. So just from an 1376557ea5ddSQu Wenruo * extent buffer alone we can not find out what is the id of the 1377557ea5ddSQu Wenruo * corresponding subvolume tree, so we can not figure out if the extent 1378557ea5ddSQu Wenruo * buffer corresponds to the root of the relocation tree or not. So 1379557ea5ddSQu Wenruo * skip this check for relocation trees. 1380557ea5ddSQu Wenruo */ 1381557ea5ddSQu Wenruo if (nritems == 0 && !btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_RELOC)) { 1382ba480dd4SQu Wenruo u64 owner = btrfs_header_owner(leaf); 1383557ea5ddSQu Wenruo 1384ba480dd4SQu Wenruo /* These trees must never be empty */ 1385ba480dd4SQu Wenruo if (owner == BTRFS_ROOT_TREE_OBJECTID || 1386ba480dd4SQu Wenruo owner == BTRFS_CHUNK_TREE_OBJECTID || 1387ba480dd4SQu Wenruo owner == BTRFS_EXTENT_TREE_OBJECTID || 1388ba480dd4SQu Wenruo owner == BTRFS_DEV_TREE_OBJECTID || 1389ba480dd4SQu Wenruo owner == BTRFS_FS_TREE_OBJECTID || 1390ba480dd4SQu Wenruo owner == BTRFS_DATA_RELOC_TREE_OBJECTID) { 139186a6be3aSDavid Sterba generic_err(leaf, 0, 1392ba480dd4SQu Wenruo "invalid root, root %llu must never be empty", 1393ba480dd4SQu Wenruo owner); 1394ba480dd4SQu Wenruo return -EUCLEAN; 1395ba480dd4SQu Wenruo } 139662fdaa52SQu Wenruo /* Unknown tree */ 139762fdaa52SQu Wenruo if (owner == 0) { 139862fdaa52SQu Wenruo generic_err(leaf, 0, 139962fdaa52SQu Wenruo "invalid owner, root 0 is not defined"); 140062fdaa52SQu Wenruo return -EUCLEAN; 140162fdaa52SQu Wenruo } 1402557ea5ddSQu Wenruo return 0; 1403557ea5ddSQu Wenruo } 1404557ea5ddSQu Wenruo 1405557ea5ddSQu Wenruo if (nritems == 0) 1406557ea5ddSQu Wenruo return 0; 1407557ea5ddSQu Wenruo 1408557ea5ddSQu Wenruo /* 1409557ea5ddSQu Wenruo * Check the following things to make sure this is a good leaf, and 1410557ea5ddSQu Wenruo * leaf users won't need to bother with similar sanity checks: 1411557ea5ddSQu Wenruo * 1412557ea5ddSQu Wenruo * 1) key ordering 1413557ea5ddSQu Wenruo * 2) item offset and size 1414557ea5ddSQu Wenruo * No overlap, no hole, all inside the leaf. 1415557ea5ddSQu Wenruo * 3) item content 1416557ea5ddSQu Wenruo * If possible, do comprehensive sanity check. 1417557ea5ddSQu Wenruo * NOTE: All checks must only rely on the item data itself. 1418557ea5ddSQu Wenruo */ 1419557ea5ddSQu Wenruo for (slot = 0; slot < nritems; slot++) { 1420557ea5ddSQu Wenruo u32 item_end_expected; 1421557ea5ddSQu Wenruo int ret; 1422557ea5ddSQu Wenruo 1423557ea5ddSQu Wenruo btrfs_item_key_to_cpu(leaf, &key, slot); 1424557ea5ddSQu Wenruo 1425557ea5ddSQu Wenruo /* Make sure the keys are in the right order */ 1426557ea5ddSQu Wenruo if (btrfs_comp_cpu_keys(&prev_key, &key) >= 0) { 142786a6be3aSDavid Sterba generic_err(leaf, slot, 1428478d01b3SQu Wenruo "bad key order, prev (%llu %u %llu) current (%llu %u %llu)", 1429478d01b3SQu Wenruo prev_key.objectid, prev_key.type, 1430478d01b3SQu Wenruo prev_key.offset, key.objectid, key.type, 1431478d01b3SQu Wenruo key.offset); 1432557ea5ddSQu Wenruo return -EUCLEAN; 1433557ea5ddSQu Wenruo } 1434557ea5ddSQu Wenruo 1435557ea5ddSQu Wenruo /* 1436557ea5ddSQu Wenruo * Make sure the offset and ends are right, remember that the 1437557ea5ddSQu Wenruo * item data starts at the end of the leaf and grows towards the 1438557ea5ddSQu Wenruo * front. 1439557ea5ddSQu Wenruo */ 1440557ea5ddSQu Wenruo if (slot == 0) 1441557ea5ddSQu Wenruo item_end_expected = BTRFS_LEAF_DATA_SIZE(fs_info); 1442557ea5ddSQu Wenruo else 1443557ea5ddSQu Wenruo item_end_expected = btrfs_item_offset_nr(leaf, 1444557ea5ddSQu Wenruo slot - 1); 1445557ea5ddSQu Wenruo if (btrfs_item_end_nr(leaf, slot) != item_end_expected) { 144686a6be3aSDavid Sterba generic_err(leaf, slot, 1447478d01b3SQu Wenruo "unexpected item end, have %u expect %u", 1448478d01b3SQu Wenruo btrfs_item_end_nr(leaf, slot), 1449478d01b3SQu Wenruo item_end_expected); 1450557ea5ddSQu Wenruo return -EUCLEAN; 1451557ea5ddSQu Wenruo } 1452557ea5ddSQu Wenruo 1453557ea5ddSQu Wenruo /* 1454557ea5ddSQu Wenruo * Check to make sure that we don't point outside of the leaf, 1455557ea5ddSQu Wenruo * just in case all the items are consistent to each other, but 1456557ea5ddSQu Wenruo * all point outside of the leaf. 1457557ea5ddSQu Wenruo */ 1458557ea5ddSQu Wenruo if (btrfs_item_end_nr(leaf, slot) > 1459557ea5ddSQu Wenruo BTRFS_LEAF_DATA_SIZE(fs_info)) { 146086a6be3aSDavid Sterba generic_err(leaf, slot, 1461478d01b3SQu Wenruo "slot end outside of leaf, have %u expect range [0, %u]", 1462478d01b3SQu Wenruo btrfs_item_end_nr(leaf, slot), 1463478d01b3SQu Wenruo BTRFS_LEAF_DATA_SIZE(fs_info)); 1464557ea5ddSQu Wenruo return -EUCLEAN; 1465557ea5ddSQu Wenruo } 1466557ea5ddSQu Wenruo 1467557ea5ddSQu Wenruo /* Also check if the item pointer overlaps with btrfs item. */ 1468557ea5ddSQu Wenruo if (btrfs_item_nr_offset(slot) + sizeof(struct btrfs_item) > 1469557ea5ddSQu Wenruo btrfs_item_ptr_offset(leaf, slot)) { 147086a6be3aSDavid Sterba generic_err(leaf, slot, 1471478d01b3SQu Wenruo "slot overlaps with its data, item end %lu data start %lu", 1472478d01b3SQu Wenruo btrfs_item_nr_offset(slot) + 1473478d01b3SQu Wenruo sizeof(struct btrfs_item), 1474478d01b3SQu Wenruo btrfs_item_ptr_offset(leaf, slot)); 1475557ea5ddSQu Wenruo return -EUCLEAN; 1476557ea5ddSQu Wenruo } 1477557ea5ddSQu Wenruo 147869fc6cbbSQu Wenruo if (check_item_data) { 147969fc6cbbSQu Wenruo /* 148069fc6cbbSQu Wenruo * Check if the item size and content meet other 148169fc6cbbSQu Wenruo * criteria 148269fc6cbbSQu Wenruo */ 14834e9845efSFilipe Manana ret = check_leaf_item(leaf, &key, slot, &prev_key); 1484557ea5ddSQu Wenruo if (ret < 0) 1485557ea5ddSQu Wenruo return ret; 148669fc6cbbSQu Wenruo } 1487557ea5ddSQu Wenruo 1488557ea5ddSQu Wenruo prev_key.objectid = key.objectid; 1489557ea5ddSQu Wenruo prev_key.type = key.type; 1490557ea5ddSQu Wenruo prev_key.offset = key.offset; 1491557ea5ddSQu Wenruo } 1492557ea5ddSQu Wenruo 1493557ea5ddSQu Wenruo return 0; 1494557ea5ddSQu Wenruo } 1495557ea5ddSQu Wenruo 14961c4360eeSDavid Sterba int btrfs_check_leaf_full(struct extent_buffer *leaf) 149769fc6cbbSQu Wenruo { 1498e2ccd361SDavid Sterba return check_leaf(leaf, true); 149969fc6cbbSQu Wenruo } 150002529d7aSQu Wenruo ALLOW_ERROR_INJECTION(btrfs_check_leaf_full, ERRNO); 150169fc6cbbSQu Wenruo 1502cfdaad5eSDavid Sterba int btrfs_check_leaf_relaxed(struct extent_buffer *leaf) 15032f659546SQu Wenruo { 1504e2ccd361SDavid Sterba return check_leaf(leaf, false); 15052f659546SQu Wenruo } 15062f659546SQu Wenruo 1507813fd1dcSDavid Sterba int btrfs_check_node(struct extent_buffer *node) 1508557ea5ddSQu Wenruo { 1509813fd1dcSDavid Sterba struct btrfs_fs_info *fs_info = node->fs_info; 1510557ea5ddSQu Wenruo unsigned long nr = btrfs_header_nritems(node); 1511557ea5ddSQu Wenruo struct btrfs_key key, next_key; 1512557ea5ddSQu Wenruo int slot; 1513f556faa4SQu Wenruo int level = btrfs_header_level(node); 1514557ea5ddSQu Wenruo u64 bytenr; 1515557ea5ddSQu Wenruo int ret = 0; 1516557ea5ddSQu Wenruo 1517f556faa4SQu Wenruo if (level <= 0 || level >= BTRFS_MAX_LEVEL) { 151886a6be3aSDavid Sterba generic_err(node, 0, 1519f556faa4SQu Wenruo "invalid level for node, have %d expect [1, %d]", 1520f556faa4SQu Wenruo level, BTRFS_MAX_LEVEL - 1); 1521f556faa4SQu Wenruo return -EUCLEAN; 1522f556faa4SQu Wenruo } 15232f659546SQu Wenruo if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(fs_info)) { 15242f659546SQu Wenruo btrfs_crit(fs_info, 1525bba4f298SQu Wenruo "corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%u]", 15262f659546SQu Wenruo btrfs_header_owner(node), node->start, 1527bba4f298SQu Wenruo nr == 0 ? "small" : "large", nr, 15282f659546SQu Wenruo BTRFS_NODEPTRS_PER_BLOCK(fs_info)); 1529bba4f298SQu Wenruo return -EUCLEAN; 1530557ea5ddSQu Wenruo } 1531557ea5ddSQu Wenruo 1532557ea5ddSQu Wenruo for (slot = 0; slot < nr - 1; slot++) { 1533557ea5ddSQu Wenruo bytenr = btrfs_node_blockptr(node, slot); 1534557ea5ddSQu Wenruo btrfs_node_key_to_cpu(node, &key, slot); 1535557ea5ddSQu Wenruo btrfs_node_key_to_cpu(node, &next_key, slot + 1); 1536557ea5ddSQu Wenruo 1537557ea5ddSQu Wenruo if (!bytenr) { 153886a6be3aSDavid Sterba generic_err(node, slot, 1539bba4f298SQu Wenruo "invalid NULL node pointer"); 1540bba4f298SQu Wenruo ret = -EUCLEAN; 1541bba4f298SQu Wenruo goto out; 1542bba4f298SQu Wenruo } 15432f659546SQu Wenruo if (!IS_ALIGNED(bytenr, fs_info->sectorsize)) { 154486a6be3aSDavid Sterba generic_err(node, slot, 1545bba4f298SQu Wenruo "unaligned pointer, have %llu should be aligned to %u", 15462f659546SQu Wenruo bytenr, fs_info->sectorsize); 1547bba4f298SQu Wenruo ret = -EUCLEAN; 1548557ea5ddSQu Wenruo goto out; 1549557ea5ddSQu Wenruo } 1550557ea5ddSQu Wenruo 1551557ea5ddSQu Wenruo if (btrfs_comp_cpu_keys(&key, &next_key) >= 0) { 155286a6be3aSDavid Sterba generic_err(node, slot, 1553bba4f298SQu Wenruo "bad key order, current (%llu %u %llu) next (%llu %u %llu)", 1554bba4f298SQu Wenruo key.objectid, key.type, key.offset, 1555bba4f298SQu Wenruo next_key.objectid, next_key.type, 1556bba4f298SQu Wenruo next_key.offset); 1557bba4f298SQu Wenruo ret = -EUCLEAN; 1558557ea5ddSQu Wenruo goto out; 1559557ea5ddSQu Wenruo } 1560557ea5ddSQu Wenruo } 1561557ea5ddSQu Wenruo out: 1562557ea5ddSQu Wenruo return ret; 1563557ea5ddSQu Wenruo } 156402529d7aSQu Wenruo ALLOW_ERROR_INJECTION(btrfs_check_node, ERRNO); 1565