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" 26*c1499166SDavid Sterba #include "misc.h" 27557ea5ddSQu Wenruo 28bba4f298SQu Wenruo /* 29bba4f298SQu Wenruo * Error message should follow the following format: 30bba4f298SQu Wenruo * corrupt <type>: <identifier>, <reason>[, <bad_value>] 31bba4f298SQu Wenruo * 32bba4f298SQu Wenruo * @type: leaf or node 33bba4f298SQu Wenruo * @identifier: the necessary info to locate the leaf/node. 3452042d8eSAndrea Gelmini * It's recommended to decode key.objecitd/offset if it's 35bba4f298SQu Wenruo * meaningful. 36bba4f298SQu Wenruo * @reason: describe the error 3752042d8eSAndrea Gelmini * @bad_value: optional, it's recommended to output bad value and its 38bba4f298SQu Wenruo * expected value (range). 39bba4f298SQu Wenruo * 40bba4f298SQu Wenruo * Since comma is used to separate the components, only space is allowed 41bba4f298SQu Wenruo * inside each component. 42bba4f298SQu Wenruo */ 43bba4f298SQu Wenruo 44bba4f298SQu Wenruo /* 45bba4f298SQu Wenruo * Append generic "corrupt leaf/node root=%llu block=%llu slot=%d: " to @fmt. 46bba4f298SQu Wenruo * Allows callers to customize the output. 47bba4f298SQu Wenruo */ 4886a6be3aSDavid Sterba __printf(3, 4) 49e67c718bSDavid Sterba __cold 5086a6be3aSDavid Sterba static void generic_err(const struct extent_buffer *eb, int slot, 51bba4f298SQu Wenruo const char *fmt, ...) 52bba4f298SQu Wenruo { 5386a6be3aSDavid Sterba const struct btrfs_fs_info *fs_info = eb->fs_info; 54bba4f298SQu Wenruo struct va_format vaf; 55bba4f298SQu Wenruo va_list args; 56bba4f298SQu Wenruo 57bba4f298SQu Wenruo va_start(args, fmt); 58bba4f298SQu Wenruo 59bba4f298SQu Wenruo vaf.fmt = fmt; 60bba4f298SQu Wenruo vaf.va = &args; 61bba4f298SQu Wenruo 622f659546SQu Wenruo btrfs_crit(fs_info, 63bba4f298SQu Wenruo "corrupt %s: root=%llu block=%llu slot=%d, %pV", 64bba4f298SQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 652f659546SQu Wenruo btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, &vaf); 66bba4f298SQu Wenruo va_end(args); 67bba4f298SQu Wenruo } 68bba4f298SQu Wenruo 698806d718SQu Wenruo /* 708806d718SQu Wenruo * Customized reporter for extent data item, since its key objectid and 718806d718SQu Wenruo * offset has its own meaning. 728806d718SQu Wenruo */ 731fd715ffSDavid Sterba __printf(3, 4) 74e67c718bSDavid Sterba __cold 751fd715ffSDavid Sterba static void file_extent_err(const struct extent_buffer *eb, int slot, 768806d718SQu Wenruo const char *fmt, ...) 778806d718SQu Wenruo { 781fd715ffSDavid Sterba const struct btrfs_fs_info *fs_info = eb->fs_info; 798806d718SQu Wenruo struct btrfs_key key; 808806d718SQu Wenruo struct va_format vaf; 818806d718SQu Wenruo va_list args; 828806d718SQu Wenruo 838806d718SQu Wenruo btrfs_item_key_to_cpu(eb, &key, slot); 848806d718SQu Wenruo va_start(args, fmt); 858806d718SQu Wenruo 868806d718SQu Wenruo vaf.fmt = fmt; 878806d718SQu Wenruo vaf.va = &args; 888806d718SQu Wenruo 892f659546SQu Wenruo btrfs_crit(fs_info, 908806d718SQu Wenruo "corrupt %s: root=%llu block=%llu slot=%d ino=%llu file_offset=%llu, %pV", 912f659546SQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 922f659546SQu Wenruo btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, 932f659546SQu Wenruo key.objectid, key.offset, &vaf); 948806d718SQu Wenruo va_end(args); 958806d718SQu Wenruo } 968806d718SQu Wenruo 978806d718SQu Wenruo /* 988806d718SQu Wenruo * Return 0 if the btrfs_file_extent_##name is aligned to @alignment 998806d718SQu Wenruo * Else return 1 1008806d718SQu Wenruo */ 101033774dcSDavid Sterba #define CHECK_FE_ALIGNED(leaf, slot, fi, name, alignment) \ 1028806d718SQu Wenruo ({ \ 1038806d718SQu Wenruo if (!IS_ALIGNED(btrfs_file_extent_##name((leaf), (fi)), (alignment))) \ 1041fd715ffSDavid Sterba file_extent_err((leaf), (slot), \ 1058806d718SQu Wenruo "invalid %s for file extent, have %llu, should be aligned to %u", \ 1068806d718SQu Wenruo (#name), btrfs_file_extent_##name((leaf), (fi)), \ 1078806d718SQu Wenruo (alignment)); \ 1088806d718SQu Wenruo (!IS_ALIGNED(btrfs_file_extent_##name((leaf), (fi)), (alignment))); \ 1098806d718SQu Wenruo }) 1108806d718SQu Wenruo 1114e9845efSFilipe Manana static u64 file_extent_end(struct extent_buffer *leaf, 1124e9845efSFilipe Manana struct btrfs_key *key, 1134e9845efSFilipe Manana struct btrfs_file_extent_item *extent) 1144e9845efSFilipe Manana { 1154e9845efSFilipe Manana u64 end; 1164e9845efSFilipe Manana u64 len; 1174e9845efSFilipe Manana 1184e9845efSFilipe Manana if (btrfs_file_extent_type(leaf, extent) == BTRFS_FILE_EXTENT_INLINE) { 1194e9845efSFilipe Manana len = btrfs_file_extent_ram_bytes(leaf, extent); 1204e9845efSFilipe Manana end = ALIGN(key->offset + len, leaf->fs_info->sectorsize); 1214e9845efSFilipe Manana } else { 1224e9845efSFilipe Manana len = btrfs_file_extent_num_bytes(leaf, extent); 1234e9845efSFilipe Manana end = key->offset + len; 1244e9845efSFilipe Manana } 1254e9845efSFilipe Manana return end; 1264e9845efSFilipe Manana } 1274e9845efSFilipe Manana 128ae2a19d8SDavid Sterba static int check_extent_data_item(struct extent_buffer *leaf, 1294e9845efSFilipe Manana struct btrfs_key *key, int slot, 1304e9845efSFilipe Manana struct btrfs_key *prev_key) 131557ea5ddSQu Wenruo { 132ae2a19d8SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 133557ea5ddSQu Wenruo struct btrfs_file_extent_item *fi; 1342f659546SQu Wenruo u32 sectorsize = fs_info->sectorsize; 135557ea5ddSQu Wenruo u32 item_size = btrfs_item_size_nr(leaf, slot); 1364c094c33SQu Wenruo u64 extent_end; 137557ea5ddSQu Wenruo 138557ea5ddSQu Wenruo if (!IS_ALIGNED(key->offset, sectorsize)) { 1391fd715ffSDavid Sterba file_extent_err(leaf, slot, 1408806d718SQu Wenruo "unaligned file_offset for file extent, have %llu should be aligned to %u", 1418806d718SQu Wenruo key->offset, sectorsize); 142557ea5ddSQu Wenruo return -EUCLEAN; 143557ea5ddSQu Wenruo } 144557ea5ddSQu Wenruo 145c18679ebSQu Wenruo /* 146c18679ebSQu Wenruo * Previous key must have the same key->objectid (ino). 147c18679ebSQu Wenruo * It can be XATTR_ITEM, INODE_ITEM or just another EXTENT_DATA. 148c18679ebSQu Wenruo * But if objectids mismatch, it means we have a missing 149c18679ebSQu Wenruo * INODE_ITEM. 150c18679ebSQu Wenruo */ 151c18679ebSQu Wenruo if (slot > 0 && is_fstree(btrfs_header_owner(leaf)) && 152c18679ebSQu Wenruo prev_key->objectid != key->objectid) { 153c18679ebSQu Wenruo file_extent_err(leaf, slot, 154c18679ebSQu Wenruo "invalid previous key objectid, have %llu expect %llu", 155c18679ebSQu Wenruo prev_key->objectid, key->objectid); 156c18679ebSQu Wenruo return -EUCLEAN; 157c18679ebSQu Wenruo } 158c18679ebSQu Wenruo 159557ea5ddSQu Wenruo fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); 160557ea5ddSQu Wenruo 161557ea5ddSQu Wenruo if (btrfs_file_extent_type(leaf, fi) > BTRFS_FILE_EXTENT_TYPES) { 1621fd715ffSDavid Sterba file_extent_err(leaf, slot, 1638806d718SQu Wenruo "invalid type for file extent, have %u expect range [0, %u]", 1648806d718SQu Wenruo btrfs_file_extent_type(leaf, fi), 1658806d718SQu Wenruo BTRFS_FILE_EXTENT_TYPES); 166557ea5ddSQu Wenruo return -EUCLEAN; 167557ea5ddSQu Wenruo } 168557ea5ddSQu Wenruo 169557ea5ddSQu Wenruo /* 17052042d8eSAndrea Gelmini * Support for new compression/encryption must introduce incompat flag, 171557ea5ddSQu Wenruo * and must be caught in open_ctree(). 172557ea5ddSQu Wenruo */ 173557ea5ddSQu Wenruo if (btrfs_file_extent_compression(leaf, fi) > BTRFS_COMPRESS_TYPES) { 1741fd715ffSDavid Sterba file_extent_err(leaf, slot, 1758806d718SQu Wenruo "invalid compression for file extent, have %u expect range [0, %u]", 1768806d718SQu Wenruo btrfs_file_extent_compression(leaf, fi), 1778806d718SQu Wenruo BTRFS_COMPRESS_TYPES); 178557ea5ddSQu Wenruo return -EUCLEAN; 179557ea5ddSQu Wenruo } 180557ea5ddSQu Wenruo if (btrfs_file_extent_encryption(leaf, fi)) { 1811fd715ffSDavid Sterba file_extent_err(leaf, slot, 1828806d718SQu Wenruo "invalid encryption for file extent, have %u expect 0", 1838806d718SQu Wenruo btrfs_file_extent_encryption(leaf, fi)); 184557ea5ddSQu Wenruo return -EUCLEAN; 185557ea5ddSQu Wenruo } 186557ea5ddSQu Wenruo if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_INLINE) { 187557ea5ddSQu Wenruo /* Inline extent must have 0 as key offset */ 188557ea5ddSQu Wenruo if (key->offset) { 1891fd715ffSDavid Sterba file_extent_err(leaf, slot, 1908806d718SQu Wenruo "invalid file_offset for inline file extent, have %llu expect 0", 1918806d718SQu Wenruo key->offset); 192557ea5ddSQu Wenruo return -EUCLEAN; 193557ea5ddSQu Wenruo } 194557ea5ddSQu Wenruo 195557ea5ddSQu Wenruo /* Compressed inline extent has no on-disk size, skip it */ 196557ea5ddSQu Wenruo if (btrfs_file_extent_compression(leaf, fi) != 197557ea5ddSQu Wenruo BTRFS_COMPRESS_NONE) 198557ea5ddSQu Wenruo return 0; 199557ea5ddSQu Wenruo 200557ea5ddSQu Wenruo /* Uncompressed inline extent size must match item size */ 201557ea5ddSQu Wenruo if (item_size != BTRFS_FILE_EXTENT_INLINE_DATA_START + 202557ea5ddSQu Wenruo btrfs_file_extent_ram_bytes(leaf, fi)) { 2031fd715ffSDavid Sterba file_extent_err(leaf, slot, 2048806d718SQu Wenruo "invalid ram_bytes for uncompressed inline extent, have %u expect %llu", 2058806d718SQu Wenruo item_size, BTRFS_FILE_EXTENT_INLINE_DATA_START + 2068806d718SQu Wenruo btrfs_file_extent_ram_bytes(leaf, fi)); 207557ea5ddSQu Wenruo return -EUCLEAN; 208557ea5ddSQu Wenruo } 209557ea5ddSQu Wenruo return 0; 210557ea5ddSQu Wenruo } 211557ea5ddSQu Wenruo 212557ea5ddSQu Wenruo /* Regular or preallocated extent has fixed item size */ 213557ea5ddSQu Wenruo if (item_size != sizeof(*fi)) { 2141fd715ffSDavid Sterba file_extent_err(leaf, slot, 215709a95c3SArnd Bergmann "invalid item size for reg/prealloc file extent, have %u expect %zu", 2168806d718SQu Wenruo item_size, sizeof(*fi)); 217557ea5ddSQu Wenruo return -EUCLEAN; 218557ea5ddSQu Wenruo } 219033774dcSDavid Sterba if (CHECK_FE_ALIGNED(leaf, slot, fi, ram_bytes, sectorsize) || 220033774dcSDavid Sterba CHECK_FE_ALIGNED(leaf, slot, fi, disk_bytenr, sectorsize) || 221033774dcSDavid Sterba CHECK_FE_ALIGNED(leaf, slot, fi, disk_num_bytes, sectorsize) || 222033774dcSDavid Sterba CHECK_FE_ALIGNED(leaf, slot, fi, offset, sectorsize) || 223033774dcSDavid Sterba CHECK_FE_ALIGNED(leaf, slot, fi, num_bytes, sectorsize)) 224557ea5ddSQu Wenruo return -EUCLEAN; 2254e9845efSFilipe Manana 2264c094c33SQu Wenruo /* Catch extent end overflow */ 2274c094c33SQu Wenruo if (check_add_overflow(btrfs_file_extent_num_bytes(leaf, fi), 2284c094c33SQu Wenruo key->offset, &extent_end)) { 2294c094c33SQu Wenruo file_extent_err(leaf, slot, 2304c094c33SQu Wenruo "extent end overflow, have file offset %llu extent num bytes %llu", 2314c094c33SQu Wenruo key->offset, 2324c094c33SQu Wenruo btrfs_file_extent_num_bytes(leaf, fi)); 2334c094c33SQu Wenruo return -EUCLEAN; 2344c094c33SQu Wenruo } 2354c094c33SQu Wenruo 2364e9845efSFilipe Manana /* 2374e9845efSFilipe Manana * Check that no two consecutive file extent items, in the same leaf, 2384e9845efSFilipe Manana * present ranges that overlap each other. 2394e9845efSFilipe Manana */ 2404e9845efSFilipe Manana if (slot > 0 && 2414e9845efSFilipe Manana prev_key->objectid == key->objectid && 2424e9845efSFilipe Manana prev_key->type == BTRFS_EXTENT_DATA_KEY) { 2434e9845efSFilipe Manana struct btrfs_file_extent_item *prev_fi; 2444e9845efSFilipe Manana u64 prev_end; 2454e9845efSFilipe Manana 2464e9845efSFilipe Manana prev_fi = btrfs_item_ptr(leaf, slot - 1, 2474e9845efSFilipe Manana struct btrfs_file_extent_item); 2484e9845efSFilipe Manana prev_end = file_extent_end(leaf, prev_key, prev_fi); 2494e9845efSFilipe Manana if (prev_end > key->offset) { 2504e9845efSFilipe Manana file_extent_err(leaf, slot - 1, 2514e9845efSFilipe Manana "file extent end range (%llu) goes beyond start offset (%llu) of the next file extent", 2524e9845efSFilipe Manana prev_end, key->offset); 2534e9845efSFilipe Manana return -EUCLEAN; 2544e9845efSFilipe Manana } 2554e9845efSFilipe Manana } 2564e9845efSFilipe Manana 257557ea5ddSQu Wenruo return 0; 258557ea5ddSQu Wenruo } 259557ea5ddSQu Wenruo 26068128ce7SDavid Sterba static int check_csum_item(struct extent_buffer *leaf, struct btrfs_key *key, 2612f659546SQu Wenruo int slot) 262557ea5ddSQu Wenruo { 26368128ce7SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 2642f659546SQu Wenruo u32 sectorsize = fs_info->sectorsize; 2652f659546SQu Wenruo u32 csumsize = btrfs_super_csum_size(fs_info->super_copy); 266557ea5ddSQu Wenruo 267557ea5ddSQu Wenruo if (key->objectid != BTRFS_EXTENT_CSUM_OBJECTID) { 26886a6be3aSDavid Sterba generic_err(leaf, slot, 269d508c5f0SQu Wenruo "invalid key objectid for csum item, have %llu expect %llu", 270d508c5f0SQu Wenruo key->objectid, BTRFS_EXTENT_CSUM_OBJECTID); 271557ea5ddSQu Wenruo return -EUCLEAN; 272557ea5ddSQu Wenruo } 273557ea5ddSQu Wenruo if (!IS_ALIGNED(key->offset, sectorsize)) { 27486a6be3aSDavid Sterba generic_err(leaf, slot, 275d508c5f0SQu Wenruo "unaligned key offset for csum item, have %llu should be aligned to %u", 276d508c5f0SQu Wenruo key->offset, sectorsize); 277557ea5ddSQu Wenruo return -EUCLEAN; 278557ea5ddSQu Wenruo } 279557ea5ddSQu Wenruo if (!IS_ALIGNED(btrfs_item_size_nr(leaf, slot), csumsize)) { 28086a6be3aSDavid Sterba generic_err(leaf, slot, 281d508c5f0SQu Wenruo "unaligned item size for csum item, have %u should be aligned to %u", 282d508c5f0SQu Wenruo btrfs_item_size_nr(leaf, slot), csumsize); 283557ea5ddSQu Wenruo return -EUCLEAN; 284557ea5ddSQu Wenruo } 285557ea5ddSQu Wenruo return 0; 286557ea5ddSQu Wenruo } 287557ea5ddSQu Wenruo 288557ea5ddSQu Wenruo /* 289ad7b0368SQu Wenruo * Customized reported for dir_item, only important new info is key->objectid, 290ad7b0368SQu Wenruo * which represents inode number 291ad7b0368SQu Wenruo */ 292d98ced68SDavid Sterba __printf(3, 4) 293e67c718bSDavid Sterba __cold 294d98ced68SDavid Sterba static void dir_item_err(const struct extent_buffer *eb, int slot, 295ad7b0368SQu Wenruo const char *fmt, ...) 296ad7b0368SQu Wenruo { 297d98ced68SDavid Sterba const struct btrfs_fs_info *fs_info = eb->fs_info; 298ad7b0368SQu Wenruo struct btrfs_key key; 299ad7b0368SQu Wenruo struct va_format vaf; 300ad7b0368SQu Wenruo va_list args; 301ad7b0368SQu Wenruo 302ad7b0368SQu Wenruo btrfs_item_key_to_cpu(eb, &key, slot); 303ad7b0368SQu Wenruo va_start(args, fmt); 304ad7b0368SQu Wenruo 305ad7b0368SQu Wenruo vaf.fmt = fmt; 306ad7b0368SQu Wenruo vaf.va = &args; 307ad7b0368SQu Wenruo 3082f659546SQu Wenruo btrfs_crit(fs_info, 309ad7b0368SQu Wenruo "corrupt %s: root=%llu block=%llu slot=%d ino=%llu, %pV", 3102f659546SQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 3112f659546SQu Wenruo btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, 3122f659546SQu Wenruo key.objectid, &vaf); 313ad7b0368SQu Wenruo va_end(args); 314ad7b0368SQu Wenruo } 315ad7b0368SQu Wenruo 316ce4252c0SDavid Sterba static int check_dir_item(struct extent_buffer *leaf, 317c18679ebSQu Wenruo struct btrfs_key *key, struct btrfs_key *prev_key, 318c18679ebSQu Wenruo int slot) 319ad7b0368SQu Wenruo { 320ce4252c0SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 321ad7b0368SQu Wenruo struct btrfs_dir_item *di; 322ad7b0368SQu Wenruo u32 item_size = btrfs_item_size_nr(leaf, slot); 323ad7b0368SQu Wenruo u32 cur = 0; 324ad7b0368SQu Wenruo 325c18679ebSQu Wenruo /* Same check as in check_extent_data_item() */ 326c18679ebSQu Wenruo if (slot > 0 && is_fstree(btrfs_header_owner(leaf)) && 327c18679ebSQu Wenruo prev_key->objectid != key->objectid) { 328c18679ebSQu Wenruo dir_item_err(leaf, slot, 329c18679ebSQu Wenruo "invalid previous key objectid, have %llu expect %llu", 330c18679ebSQu Wenruo prev_key->objectid, key->objectid); 331c18679ebSQu Wenruo return -EUCLEAN; 332c18679ebSQu Wenruo } 333ad7b0368SQu Wenruo di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); 334ad7b0368SQu Wenruo while (cur < item_size) { 335ad7b0368SQu Wenruo u32 name_len; 336ad7b0368SQu Wenruo u32 data_len; 337ad7b0368SQu Wenruo u32 max_name_len; 338ad7b0368SQu Wenruo u32 total_size; 339ad7b0368SQu Wenruo u32 name_hash; 340ad7b0368SQu Wenruo u8 dir_type; 341ad7b0368SQu Wenruo 342ad7b0368SQu Wenruo /* header itself should not cross item boundary */ 343ad7b0368SQu Wenruo if (cur + sizeof(*di) > item_size) { 344d98ced68SDavid Sterba dir_item_err(leaf, slot, 3457cfad652SArnd Bergmann "dir item header crosses item boundary, have %zu boundary %u", 346ad7b0368SQu Wenruo cur + sizeof(*di), item_size); 347ad7b0368SQu Wenruo return -EUCLEAN; 348ad7b0368SQu Wenruo } 349ad7b0368SQu Wenruo 350ad7b0368SQu Wenruo /* dir type check */ 351ad7b0368SQu Wenruo dir_type = btrfs_dir_type(leaf, di); 352ad7b0368SQu Wenruo if (dir_type >= BTRFS_FT_MAX) { 353d98ced68SDavid Sterba dir_item_err(leaf, slot, 354ad7b0368SQu Wenruo "invalid dir item type, have %u expect [0, %u)", 355ad7b0368SQu Wenruo dir_type, BTRFS_FT_MAX); 356ad7b0368SQu Wenruo return -EUCLEAN; 357ad7b0368SQu Wenruo } 358ad7b0368SQu Wenruo 359ad7b0368SQu Wenruo if (key->type == BTRFS_XATTR_ITEM_KEY && 360ad7b0368SQu Wenruo dir_type != BTRFS_FT_XATTR) { 361d98ced68SDavid Sterba dir_item_err(leaf, slot, 362ad7b0368SQu Wenruo "invalid dir item type for XATTR key, have %u expect %u", 363ad7b0368SQu Wenruo dir_type, BTRFS_FT_XATTR); 364ad7b0368SQu Wenruo return -EUCLEAN; 365ad7b0368SQu Wenruo } 366ad7b0368SQu Wenruo if (dir_type == BTRFS_FT_XATTR && 367ad7b0368SQu Wenruo key->type != BTRFS_XATTR_ITEM_KEY) { 368d98ced68SDavid Sterba dir_item_err(leaf, slot, 369ad7b0368SQu Wenruo "xattr dir type found for non-XATTR key"); 370ad7b0368SQu Wenruo return -EUCLEAN; 371ad7b0368SQu Wenruo } 372ad7b0368SQu Wenruo if (dir_type == BTRFS_FT_XATTR) 373ad7b0368SQu Wenruo max_name_len = XATTR_NAME_MAX; 374ad7b0368SQu Wenruo else 375ad7b0368SQu Wenruo max_name_len = BTRFS_NAME_LEN; 376ad7b0368SQu Wenruo 377ad7b0368SQu Wenruo /* Name/data length check */ 378ad7b0368SQu Wenruo name_len = btrfs_dir_name_len(leaf, di); 379ad7b0368SQu Wenruo data_len = btrfs_dir_data_len(leaf, di); 380ad7b0368SQu Wenruo if (name_len > max_name_len) { 381d98ced68SDavid Sterba dir_item_err(leaf, slot, 382ad7b0368SQu Wenruo "dir item name len too long, have %u max %u", 383ad7b0368SQu Wenruo name_len, max_name_len); 384ad7b0368SQu Wenruo return -EUCLEAN; 385ad7b0368SQu Wenruo } 3862f659546SQu Wenruo if (name_len + data_len > BTRFS_MAX_XATTR_SIZE(fs_info)) { 387d98ced68SDavid Sterba dir_item_err(leaf, slot, 388ad7b0368SQu Wenruo "dir item name and data len too long, have %u max %u", 389ad7b0368SQu Wenruo name_len + data_len, 3902f659546SQu Wenruo BTRFS_MAX_XATTR_SIZE(fs_info)); 391ad7b0368SQu Wenruo return -EUCLEAN; 392ad7b0368SQu Wenruo } 393ad7b0368SQu Wenruo 394ad7b0368SQu Wenruo if (data_len && dir_type != BTRFS_FT_XATTR) { 395d98ced68SDavid Sterba dir_item_err(leaf, slot, 396ad7b0368SQu Wenruo "dir item with invalid data len, have %u expect 0", 397ad7b0368SQu Wenruo data_len); 398ad7b0368SQu Wenruo return -EUCLEAN; 399ad7b0368SQu Wenruo } 400ad7b0368SQu Wenruo 401ad7b0368SQu Wenruo total_size = sizeof(*di) + name_len + data_len; 402ad7b0368SQu Wenruo 403ad7b0368SQu Wenruo /* header and name/data should not cross item boundary */ 404ad7b0368SQu Wenruo if (cur + total_size > item_size) { 405d98ced68SDavid Sterba dir_item_err(leaf, slot, 406ad7b0368SQu Wenruo "dir item data crosses item boundary, have %u boundary %u", 407ad7b0368SQu Wenruo cur + total_size, item_size); 408ad7b0368SQu Wenruo return -EUCLEAN; 409ad7b0368SQu Wenruo } 410ad7b0368SQu Wenruo 411ad7b0368SQu Wenruo /* 412ad7b0368SQu Wenruo * Special check for XATTR/DIR_ITEM, as key->offset is name 413ad7b0368SQu Wenruo * hash, should match its name 414ad7b0368SQu Wenruo */ 415ad7b0368SQu Wenruo if (key->type == BTRFS_DIR_ITEM_KEY || 416ad7b0368SQu Wenruo key->type == BTRFS_XATTR_ITEM_KEY) { 417e2683fc9SDavid Sterba char namebuf[max(BTRFS_NAME_LEN, XATTR_NAME_MAX)]; 418e2683fc9SDavid Sterba 419ad7b0368SQu Wenruo read_extent_buffer(leaf, namebuf, 420ad7b0368SQu Wenruo (unsigned long)(di + 1), name_len); 421ad7b0368SQu Wenruo name_hash = btrfs_name_hash(namebuf, name_len); 422ad7b0368SQu Wenruo if (key->offset != name_hash) { 423d98ced68SDavid Sterba dir_item_err(leaf, slot, 424ad7b0368SQu Wenruo "name hash mismatch with key, have 0x%016x expect 0x%016llx", 425ad7b0368SQu Wenruo name_hash, key->offset); 426ad7b0368SQu Wenruo return -EUCLEAN; 427ad7b0368SQu Wenruo } 428ad7b0368SQu Wenruo } 429ad7b0368SQu Wenruo cur += total_size; 430ad7b0368SQu Wenruo di = (struct btrfs_dir_item *)((void *)di + total_size); 431ad7b0368SQu Wenruo } 432ad7b0368SQu Wenruo return 0; 433ad7b0368SQu Wenruo } 434ad7b0368SQu Wenruo 4354806bd88SDavid Sterba __printf(3, 4) 436fce466eaSQu Wenruo __cold 4374806bd88SDavid Sterba static void block_group_err(const struct extent_buffer *eb, int slot, 438fce466eaSQu Wenruo const char *fmt, ...) 439fce466eaSQu Wenruo { 4404806bd88SDavid Sterba const struct btrfs_fs_info *fs_info = eb->fs_info; 441fce466eaSQu Wenruo struct btrfs_key key; 442fce466eaSQu Wenruo struct va_format vaf; 443fce466eaSQu Wenruo va_list args; 444fce466eaSQu Wenruo 445fce466eaSQu Wenruo btrfs_item_key_to_cpu(eb, &key, slot); 446fce466eaSQu Wenruo va_start(args, fmt); 447fce466eaSQu Wenruo 448fce466eaSQu Wenruo vaf.fmt = fmt; 449fce466eaSQu Wenruo vaf.va = &args; 450fce466eaSQu Wenruo 451fce466eaSQu Wenruo btrfs_crit(fs_info, 452fce466eaSQu Wenruo "corrupt %s: root=%llu block=%llu slot=%d bg_start=%llu bg_len=%llu, %pV", 453fce466eaSQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 454fce466eaSQu Wenruo btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, 455fce466eaSQu Wenruo key.objectid, key.offset, &vaf); 456fce466eaSQu Wenruo va_end(args); 457fce466eaSQu Wenruo } 458fce466eaSQu Wenruo 459af60ce2bSDavid Sterba static int check_block_group_item(struct extent_buffer *leaf, 460fce466eaSQu Wenruo struct btrfs_key *key, int slot) 461fce466eaSQu Wenruo { 462fce466eaSQu Wenruo struct btrfs_block_group_item bgi; 463fce466eaSQu Wenruo u32 item_size = btrfs_item_size_nr(leaf, slot); 464fce466eaSQu Wenruo u64 flags; 465fce466eaSQu Wenruo u64 type; 466fce466eaSQu Wenruo 467fce466eaSQu Wenruo /* 468fce466eaSQu Wenruo * Here we don't really care about alignment since extent allocator can 46910950929SQu Wenruo * handle it. We care more about the size. 470fce466eaSQu Wenruo */ 47110950929SQu Wenruo if (key->offset == 0) { 4724806bd88SDavid Sterba block_group_err(leaf, slot, 47310950929SQu Wenruo "invalid block group size 0"); 474fce466eaSQu Wenruo return -EUCLEAN; 475fce466eaSQu Wenruo } 476fce466eaSQu Wenruo 477fce466eaSQu Wenruo if (item_size != sizeof(bgi)) { 4784806bd88SDavid Sterba block_group_err(leaf, slot, 479fce466eaSQu Wenruo "invalid item size, have %u expect %zu", 480fce466eaSQu Wenruo item_size, sizeof(bgi)); 481fce466eaSQu Wenruo return -EUCLEAN; 482fce466eaSQu Wenruo } 483fce466eaSQu Wenruo 484fce466eaSQu Wenruo read_extent_buffer(leaf, &bgi, btrfs_item_ptr_offset(leaf, slot), 485fce466eaSQu Wenruo sizeof(bgi)); 486fce466eaSQu Wenruo if (btrfs_block_group_chunk_objectid(&bgi) != 487fce466eaSQu Wenruo BTRFS_FIRST_CHUNK_TREE_OBJECTID) { 4884806bd88SDavid Sterba block_group_err(leaf, slot, 489fce466eaSQu Wenruo "invalid block group chunk objectid, have %llu expect %llu", 490fce466eaSQu Wenruo btrfs_block_group_chunk_objectid(&bgi), 491fce466eaSQu Wenruo BTRFS_FIRST_CHUNK_TREE_OBJECTID); 492fce466eaSQu Wenruo return -EUCLEAN; 493fce466eaSQu Wenruo } 494fce466eaSQu Wenruo 495fce466eaSQu Wenruo if (btrfs_block_group_used(&bgi) > key->offset) { 4964806bd88SDavid Sterba block_group_err(leaf, slot, 497fce466eaSQu Wenruo "invalid block group used, have %llu expect [0, %llu)", 498fce466eaSQu Wenruo btrfs_block_group_used(&bgi), key->offset); 499fce466eaSQu Wenruo return -EUCLEAN; 500fce466eaSQu Wenruo } 501fce466eaSQu Wenruo 502fce466eaSQu Wenruo flags = btrfs_block_group_flags(&bgi); 503fce466eaSQu Wenruo if (hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) > 1) { 5044806bd88SDavid Sterba block_group_err(leaf, slot, 505fce466eaSQu Wenruo "invalid profile flags, have 0x%llx (%lu bits set) expect no more than 1 bit set", 506fce466eaSQu Wenruo flags & BTRFS_BLOCK_GROUP_PROFILE_MASK, 507fce466eaSQu Wenruo hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK)); 508fce466eaSQu Wenruo return -EUCLEAN; 509fce466eaSQu Wenruo } 510fce466eaSQu Wenruo 511fce466eaSQu Wenruo type = flags & BTRFS_BLOCK_GROUP_TYPE_MASK; 512fce466eaSQu Wenruo if (type != BTRFS_BLOCK_GROUP_DATA && 513fce466eaSQu Wenruo type != BTRFS_BLOCK_GROUP_METADATA && 514fce466eaSQu Wenruo type != BTRFS_BLOCK_GROUP_SYSTEM && 515fce466eaSQu Wenruo type != (BTRFS_BLOCK_GROUP_METADATA | 516fce466eaSQu Wenruo BTRFS_BLOCK_GROUP_DATA)) { 5174806bd88SDavid Sterba block_group_err(leaf, slot, 518761333f2SShaokun Zhang "invalid type, have 0x%llx (%lu bits set) expect either 0x%llx, 0x%llx, 0x%llx or 0x%llx", 519fce466eaSQu Wenruo type, hweight64(type), 520fce466eaSQu Wenruo BTRFS_BLOCK_GROUP_DATA, BTRFS_BLOCK_GROUP_METADATA, 521fce466eaSQu Wenruo BTRFS_BLOCK_GROUP_SYSTEM, 522fce466eaSQu Wenruo BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA); 523fce466eaSQu Wenruo return -EUCLEAN; 524fce466eaSQu Wenruo } 525fce466eaSQu Wenruo return 0; 526fce466eaSQu Wenruo } 527fce466eaSQu Wenruo 528d001e4a3SDavid Sterba __printf(4, 5) 529f1140243SQu Wenruo __cold 530d001e4a3SDavid Sterba static void chunk_err(const struct extent_buffer *leaf, 531f1140243SQu Wenruo const struct btrfs_chunk *chunk, u64 logical, 532f1140243SQu Wenruo const char *fmt, ...) 533f1140243SQu Wenruo { 534d001e4a3SDavid Sterba const struct btrfs_fs_info *fs_info = leaf->fs_info; 535f1140243SQu Wenruo bool is_sb; 536f1140243SQu Wenruo struct va_format vaf; 537f1140243SQu Wenruo va_list args; 538f1140243SQu Wenruo int i; 539f1140243SQu Wenruo int slot = -1; 540f1140243SQu Wenruo 541f1140243SQu Wenruo /* Only superblock eb is able to have such small offset */ 542f1140243SQu Wenruo is_sb = (leaf->start == BTRFS_SUPER_INFO_OFFSET); 543f1140243SQu Wenruo 544f1140243SQu Wenruo if (!is_sb) { 545f1140243SQu Wenruo /* 546f1140243SQu Wenruo * Get the slot number by iterating through all slots, this 547f1140243SQu Wenruo * would provide better readability. 548f1140243SQu Wenruo */ 549f1140243SQu Wenruo for (i = 0; i < btrfs_header_nritems(leaf); i++) { 550f1140243SQu Wenruo if (btrfs_item_ptr_offset(leaf, i) == 551f1140243SQu Wenruo (unsigned long)chunk) { 552f1140243SQu Wenruo slot = i; 553f1140243SQu Wenruo break; 554f1140243SQu Wenruo } 555f1140243SQu Wenruo } 556f1140243SQu Wenruo } 557f1140243SQu Wenruo va_start(args, fmt); 558f1140243SQu Wenruo vaf.fmt = fmt; 559f1140243SQu Wenruo vaf.va = &args; 560f1140243SQu Wenruo 561f1140243SQu Wenruo if (is_sb) 562f1140243SQu Wenruo btrfs_crit(fs_info, 563f1140243SQu Wenruo "corrupt superblock syschunk array: chunk_start=%llu, %pV", 564f1140243SQu Wenruo logical, &vaf); 565f1140243SQu Wenruo else 566f1140243SQu Wenruo btrfs_crit(fs_info, 567f1140243SQu Wenruo "corrupt leaf: root=%llu block=%llu slot=%d chunk_start=%llu, %pV", 568f1140243SQu Wenruo BTRFS_CHUNK_TREE_OBJECTID, leaf->start, slot, 569f1140243SQu Wenruo logical, &vaf); 570f1140243SQu Wenruo va_end(args); 571f1140243SQu Wenruo } 572f1140243SQu Wenruo 573ad7b0368SQu Wenruo /* 57482fc28fbSQu Wenruo * The common chunk check which could also work on super block sys chunk array. 57582fc28fbSQu Wenruo * 576bf871c3bSQu Wenruo * Return -EUCLEAN if anything is corrupted. 57782fc28fbSQu Wenruo * Return 0 if everything is OK. 57882fc28fbSQu Wenruo */ 579ddaf1d5aSDavid Sterba int btrfs_check_chunk_valid(struct extent_buffer *leaf, 58082fc28fbSQu Wenruo struct btrfs_chunk *chunk, u64 logical) 58182fc28fbSQu Wenruo { 582ddaf1d5aSDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 58382fc28fbSQu Wenruo u64 length; 58482fc28fbSQu Wenruo u64 stripe_len; 58582fc28fbSQu Wenruo u16 num_stripes; 58682fc28fbSQu Wenruo u16 sub_stripes; 58782fc28fbSQu Wenruo u64 type; 58882fc28fbSQu Wenruo u64 features; 58982fc28fbSQu Wenruo bool mixed = false; 59082fc28fbSQu Wenruo 59182fc28fbSQu Wenruo length = btrfs_chunk_length(leaf, chunk); 59282fc28fbSQu Wenruo stripe_len = btrfs_chunk_stripe_len(leaf, chunk); 59382fc28fbSQu Wenruo num_stripes = btrfs_chunk_num_stripes(leaf, chunk); 59482fc28fbSQu Wenruo sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk); 59582fc28fbSQu Wenruo type = btrfs_chunk_type(leaf, chunk); 59682fc28fbSQu Wenruo 59782fc28fbSQu Wenruo if (!num_stripes) { 598d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 599f1140243SQu Wenruo "invalid chunk num_stripes, have %u", num_stripes); 600bf871c3bSQu Wenruo return -EUCLEAN; 60182fc28fbSQu Wenruo } 60282fc28fbSQu Wenruo if (!IS_ALIGNED(logical, fs_info->sectorsize)) { 603d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 604f1140243SQu Wenruo "invalid chunk logical, have %llu should aligned to %u", 605f1140243SQu Wenruo logical, fs_info->sectorsize); 606bf871c3bSQu Wenruo return -EUCLEAN; 60782fc28fbSQu Wenruo } 60882fc28fbSQu Wenruo if (btrfs_chunk_sector_size(leaf, chunk) != fs_info->sectorsize) { 609d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 610f1140243SQu Wenruo "invalid chunk sectorsize, have %u expect %u", 611f1140243SQu Wenruo btrfs_chunk_sector_size(leaf, chunk), 612f1140243SQu Wenruo fs_info->sectorsize); 613bf871c3bSQu Wenruo return -EUCLEAN; 61482fc28fbSQu Wenruo } 61582fc28fbSQu Wenruo if (!length || !IS_ALIGNED(length, fs_info->sectorsize)) { 616d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 617f1140243SQu Wenruo "invalid chunk length, have %llu", length); 618bf871c3bSQu Wenruo return -EUCLEAN; 61982fc28fbSQu Wenruo } 62082fc28fbSQu Wenruo if (!is_power_of_2(stripe_len) || stripe_len != BTRFS_STRIPE_LEN) { 621d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 622f1140243SQu Wenruo "invalid chunk stripe length: %llu", 62382fc28fbSQu Wenruo stripe_len); 624bf871c3bSQu Wenruo return -EUCLEAN; 62582fc28fbSQu Wenruo } 62682fc28fbSQu Wenruo if (~(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_PROFILE_MASK) & 62782fc28fbSQu Wenruo type) { 628d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 629f1140243SQu Wenruo "unrecognized chunk type: 0x%llx", 63082fc28fbSQu Wenruo ~(BTRFS_BLOCK_GROUP_TYPE_MASK | 63182fc28fbSQu Wenruo BTRFS_BLOCK_GROUP_PROFILE_MASK) & 63282fc28fbSQu Wenruo btrfs_chunk_type(leaf, chunk)); 633bf871c3bSQu Wenruo return -EUCLEAN; 63482fc28fbSQu Wenruo } 63582fc28fbSQu Wenruo 636*c1499166SDavid Sterba if (!has_single_bit_set(type & BTRFS_BLOCK_GROUP_PROFILE_MASK) && 63780e46cf2SQu Wenruo (type & BTRFS_BLOCK_GROUP_PROFILE_MASK) != 0) { 638d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 63980e46cf2SQu Wenruo "invalid chunk profile flag: 0x%llx, expect 0 or 1 bit set", 64080e46cf2SQu Wenruo type & BTRFS_BLOCK_GROUP_PROFILE_MASK); 64180e46cf2SQu Wenruo return -EUCLEAN; 64280e46cf2SQu Wenruo } 64382fc28fbSQu Wenruo if ((type & BTRFS_BLOCK_GROUP_TYPE_MASK) == 0) { 644d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 645f1140243SQu Wenruo "missing chunk type flag, have 0x%llx one bit must be set in 0x%llx", 646f1140243SQu Wenruo type, BTRFS_BLOCK_GROUP_TYPE_MASK); 647bf871c3bSQu Wenruo return -EUCLEAN; 64882fc28fbSQu Wenruo } 64982fc28fbSQu Wenruo 65082fc28fbSQu Wenruo if ((type & BTRFS_BLOCK_GROUP_SYSTEM) && 65182fc28fbSQu Wenruo (type & (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA))) { 652d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 653f1140243SQu Wenruo "system chunk with data or metadata type: 0x%llx", 654f1140243SQu Wenruo type); 655bf871c3bSQu Wenruo return -EUCLEAN; 65682fc28fbSQu Wenruo } 65782fc28fbSQu Wenruo 65882fc28fbSQu Wenruo features = btrfs_super_incompat_flags(fs_info->super_copy); 65982fc28fbSQu Wenruo if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) 66082fc28fbSQu Wenruo mixed = true; 66182fc28fbSQu Wenruo 66282fc28fbSQu Wenruo if (!mixed) { 66382fc28fbSQu Wenruo if ((type & BTRFS_BLOCK_GROUP_METADATA) && 66482fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_DATA)) { 665d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 66682fc28fbSQu Wenruo "mixed chunk type in non-mixed mode: 0x%llx", type); 667bf871c3bSQu Wenruo return -EUCLEAN; 66882fc28fbSQu Wenruo } 66982fc28fbSQu Wenruo } 67082fc28fbSQu Wenruo 67182fc28fbSQu Wenruo if ((type & BTRFS_BLOCK_GROUP_RAID10 && sub_stripes != 2) || 67282fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_RAID1 && num_stripes != 2) || 67382fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_RAID5 && num_stripes < 2) || 67482fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_RAID6 && num_stripes < 3) || 67582fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_DUP && num_stripes != 2) || 67682fc28fbSQu Wenruo ((type & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0 && num_stripes != 1)) { 677d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 67882fc28fbSQu Wenruo "invalid num_stripes:sub_stripes %u:%u for profile %llu", 67982fc28fbSQu Wenruo num_stripes, sub_stripes, 68082fc28fbSQu Wenruo type & BTRFS_BLOCK_GROUP_PROFILE_MASK); 681bf871c3bSQu Wenruo return -EUCLEAN; 68282fc28fbSQu Wenruo } 68382fc28fbSQu Wenruo 68482fc28fbSQu Wenruo return 0; 68582fc28fbSQu Wenruo } 68682fc28fbSQu Wenruo 6875617ed80SDavid Sterba __printf(3, 4) 688ab4ba2e1SQu Wenruo __cold 6895617ed80SDavid Sterba static void dev_item_err(const struct extent_buffer *eb, int slot, 690ab4ba2e1SQu Wenruo const char *fmt, ...) 691ab4ba2e1SQu Wenruo { 692ab4ba2e1SQu Wenruo struct btrfs_key key; 693ab4ba2e1SQu Wenruo struct va_format vaf; 694ab4ba2e1SQu Wenruo va_list args; 695ab4ba2e1SQu Wenruo 696ab4ba2e1SQu Wenruo btrfs_item_key_to_cpu(eb, &key, slot); 697ab4ba2e1SQu Wenruo va_start(args, fmt); 698ab4ba2e1SQu Wenruo 699ab4ba2e1SQu Wenruo vaf.fmt = fmt; 700ab4ba2e1SQu Wenruo vaf.va = &args; 701ab4ba2e1SQu Wenruo 7025617ed80SDavid Sterba btrfs_crit(eb->fs_info, 703ab4ba2e1SQu Wenruo "corrupt %s: root=%llu block=%llu slot=%d devid=%llu %pV", 704ab4ba2e1SQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 705ab4ba2e1SQu Wenruo btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, 706ab4ba2e1SQu Wenruo key.objectid, &vaf); 707ab4ba2e1SQu Wenruo va_end(args); 708ab4ba2e1SQu Wenruo } 709ab4ba2e1SQu Wenruo 710412a2312SDavid Sterba static int check_dev_item(struct extent_buffer *leaf, 711ab4ba2e1SQu Wenruo struct btrfs_key *key, int slot) 712ab4ba2e1SQu Wenruo { 713ab4ba2e1SQu Wenruo struct btrfs_dev_item *ditem; 714ab4ba2e1SQu Wenruo 715ab4ba2e1SQu Wenruo if (key->objectid != BTRFS_DEV_ITEMS_OBJECTID) { 7165617ed80SDavid Sterba dev_item_err(leaf, slot, 717ab4ba2e1SQu Wenruo "invalid objectid: has=%llu expect=%llu", 718ab4ba2e1SQu Wenruo key->objectid, BTRFS_DEV_ITEMS_OBJECTID); 719ab4ba2e1SQu Wenruo return -EUCLEAN; 720ab4ba2e1SQu Wenruo } 721ab4ba2e1SQu Wenruo ditem = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item); 722ab4ba2e1SQu Wenruo if (btrfs_device_id(leaf, ditem) != key->offset) { 7235617ed80SDavid Sterba dev_item_err(leaf, slot, 724ab4ba2e1SQu Wenruo "devid mismatch: key has=%llu item has=%llu", 725ab4ba2e1SQu Wenruo key->offset, btrfs_device_id(leaf, ditem)); 726ab4ba2e1SQu Wenruo return -EUCLEAN; 727ab4ba2e1SQu Wenruo } 728ab4ba2e1SQu Wenruo 729ab4ba2e1SQu Wenruo /* 730ab4ba2e1SQu Wenruo * For device total_bytes, we don't have reliable way to check it, as 731ab4ba2e1SQu Wenruo * it can be 0 for device removal. Device size check can only be done 732ab4ba2e1SQu Wenruo * by dev extents check. 733ab4ba2e1SQu Wenruo */ 734ab4ba2e1SQu Wenruo if (btrfs_device_bytes_used(leaf, ditem) > 735ab4ba2e1SQu Wenruo btrfs_device_total_bytes(leaf, ditem)) { 7365617ed80SDavid Sterba dev_item_err(leaf, slot, 737ab4ba2e1SQu Wenruo "invalid bytes used: have %llu expect [0, %llu]", 738ab4ba2e1SQu Wenruo btrfs_device_bytes_used(leaf, ditem), 739ab4ba2e1SQu Wenruo btrfs_device_total_bytes(leaf, ditem)); 740ab4ba2e1SQu Wenruo return -EUCLEAN; 741ab4ba2e1SQu Wenruo } 742ab4ba2e1SQu Wenruo /* 743ab4ba2e1SQu Wenruo * Remaining members like io_align/type/gen/dev_group aren't really 744ab4ba2e1SQu Wenruo * utilized. Skip them to make later usage of them easier. 745ab4ba2e1SQu Wenruo */ 746ab4ba2e1SQu Wenruo return 0; 747ab4ba2e1SQu Wenruo } 748ab4ba2e1SQu Wenruo 749496245caSQu Wenruo /* Inode item error output has the same format as dir_item_err() */ 750496245caSQu Wenruo #define inode_item_err(fs_info, eb, slot, fmt, ...) \ 751d98ced68SDavid Sterba dir_item_err(eb, slot, fmt, __VA_ARGS__) 752496245caSQu Wenruo 75339e57f49SDavid Sterba static int check_inode_item(struct extent_buffer *leaf, 754496245caSQu Wenruo struct btrfs_key *key, int slot) 755496245caSQu Wenruo { 75639e57f49SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 757496245caSQu Wenruo struct btrfs_inode_item *iitem; 758496245caSQu Wenruo u64 super_gen = btrfs_super_generation(fs_info->super_copy); 759496245caSQu Wenruo u32 valid_mask = (S_IFMT | S_ISUID | S_ISGID | S_ISVTX | 0777); 760496245caSQu Wenruo u32 mode; 761496245caSQu Wenruo 762496245caSQu Wenruo if ((key->objectid < BTRFS_FIRST_FREE_OBJECTID || 763496245caSQu Wenruo key->objectid > BTRFS_LAST_FREE_OBJECTID) && 764496245caSQu Wenruo key->objectid != BTRFS_ROOT_TREE_DIR_OBJECTID && 765496245caSQu Wenruo key->objectid != BTRFS_FREE_INO_OBJECTID) { 76686a6be3aSDavid Sterba generic_err(leaf, slot, 767496245caSQu Wenruo "invalid key objectid: has %llu expect %llu or [%llu, %llu] or %llu", 768496245caSQu Wenruo key->objectid, BTRFS_ROOT_TREE_DIR_OBJECTID, 769496245caSQu Wenruo BTRFS_FIRST_FREE_OBJECTID, 770496245caSQu Wenruo BTRFS_LAST_FREE_OBJECTID, 771496245caSQu Wenruo BTRFS_FREE_INO_OBJECTID); 772496245caSQu Wenruo return -EUCLEAN; 773496245caSQu Wenruo } 774496245caSQu Wenruo if (key->offset != 0) { 775496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 776496245caSQu Wenruo "invalid key offset: has %llu expect 0", 777496245caSQu Wenruo key->offset); 778496245caSQu Wenruo return -EUCLEAN; 779496245caSQu Wenruo } 780496245caSQu Wenruo iitem = btrfs_item_ptr(leaf, slot, struct btrfs_inode_item); 781496245caSQu Wenruo 782496245caSQu Wenruo /* Here we use super block generation + 1 to handle log tree */ 783496245caSQu Wenruo if (btrfs_inode_generation(leaf, iitem) > super_gen + 1) { 784496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 785496245caSQu Wenruo "invalid inode generation: has %llu expect (0, %llu]", 786496245caSQu Wenruo btrfs_inode_generation(leaf, iitem), 787496245caSQu Wenruo super_gen + 1); 788496245caSQu Wenruo return -EUCLEAN; 789496245caSQu Wenruo } 790496245caSQu Wenruo /* Note for ROOT_TREE_DIR_ITEM, mkfs could set its transid 0 */ 791496245caSQu Wenruo if (btrfs_inode_transid(leaf, iitem) > super_gen + 1) { 792496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 793496245caSQu Wenruo "invalid inode generation: has %llu expect [0, %llu]", 794496245caSQu Wenruo btrfs_inode_transid(leaf, iitem), super_gen + 1); 795496245caSQu Wenruo return -EUCLEAN; 796496245caSQu Wenruo } 797496245caSQu Wenruo 798496245caSQu Wenruo /* 799496245caSQu Wenruo * For size and nbytes it's better not to be too strict, as for dir 800496245caSQu Wenruo * item its size/nbytes can easily get wrong, but doesn't affect 801496245caSQu Wenruo * anything in the fs. So here we skip the check. 802496245caSQu Wenruo */ 803496245caSQu Wenruo mode = btrfs_inode_mode(leaf, iitem); 804496245caSQu Wenruo if (mode & ~valid_mask) { 805496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 806496245caSQu Wenruo "unknown mode bit detected: 0x%x", 807496245caSQu Wenruo mode & ~valid_mask); 808496245caSQu Wenruo return -EUCLEAN; 809496245caSQu Wenruo } 810496245caSQu Wenruo 811496245caSQu Wenruo /* 812*c1499166SDavid Sterba * S_IFMT is not bit mapped so we can't completely rely on 813*c1499166SDavid Sterba * is_power_of_2/has_single_bit_set, but it can save us from checking 814*c1499166SDavid Sterba * FIFO/CHR/DIR/REG. Only needs to check BLK, LNK and SOCKS 815496245caSQu Wenruo */ 816*c1499166SDavid Sterba if (!has_single_bit_set(mode & S_IFMT)) { 817496245caSQu Wenruo if (!S_ISLNK(mode) && !S_ISBLK(mode) && !S_ISSOCK(mode)) { 818496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 819496245caSQu Wenruo "invalid mode: has 0%o expect valid S_IF* bit(s)", 820496245caSQu Wenruo mode & S_IFMT); 821496245caSQu Wenruo return -EUCLEAN; 822496245caSQu Wenruo } 823496245caSQu Wenruo } 824496245caSQu Wenruo if (S_ISDIR(mode) && btrfs_inode_nlink(leaf, iitem) > 1) { 825496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 826496245caSQu Wenruo "invalid nlink: has %u expect no more than 1 for dir", 827496245caSQu Wenruo btrfs_inode_nlink(leaf, iitem)); 828496245caSQu Wenruo return -EUCLEAN; 829496245caSQu Wenruo } 830496245caSQu Wenruo if (btrfs_inode_flags(leaf, iitem) & ~BTRFS_INODE_FLAG_MASK) { 831496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 832496245caSQu Wenruo "unknown flags detected: 0x%llx", 833496245caSQu Wenruo btrfs_inode_flags(leaf, iitem) & 834496245caSQu Wenruo ~BTRFS_INODE_FLAG_MASK); 835496245caSQu Wenruo return -EUCLEAN; 836496245caSQu Wenruo } 837496245caSQu Wenruo return 0; 838496245caSQu Wenruo } 839496245caSQu Wenruo 840259ee775SQu Wenruo static int check_root_item(struct extent_buffer *leaf, struct btrfs_key *key, 841259ee775SQu Wenruo int slot) 842259ee775SQu Wenruo { 843259ee775SQu Wenruo struct btrfs_fs_info *fs_info = leaf->fs_info; 844259ee775SQu Wenruo struct btrfs_root_item ri; 845259ee775SQu Wenruo const u64 valid_root_flags = BTRFS_ROOT_SUBVOL_RDONLY | 846259ee775SQu Wenruo BTRFS_ROOT_SUBVOL_DEAD; 847259ee775SQu Wenruo 848259ee775SQu Wenruo /* No such tree id */ 849259ee775SQu Wenruo if (key->objectid == 0) { 850259ee775SQu Wenruo generic_err(leaf, slot, "invalid root id 0"); 851259ee775SQu Wenruo return -EUCLEAN; 852259ee775SQu Wenruo } 853259ee775SQu Wenruo 854259ee775SQu Wenruo /* 855259ee775SQu Wenruo * Some older kernel may create ROOT_ITEM with non-zero offset, so here 856259ee775SQu Wenruo * we only check offset for reloc tree whose key->offset must be a 857259ee775SQu Wenruo * valid tree. 858259ee775SQu Wenruo */ 859259ee775SQu Wenruo if (key->objectid == BTRFS_TREE_RELOC_OBJECTID && key->offset == 0) { 860259ee775SQu Wenruo generic_err(leaf, slot, "invalid root id 0 for reloc tree"); 861259ee775SQu Wenruo return -EUCLEAN; 862259ee775SQu Wenruo } 863259ee775SQu Wenruo 864259ee775SQu Wenruo if (btrfs_item_size_nr(leaf, slot) != sizeof(ri)) { 865259ee775SQu Wenruo generic_err(leaf, slot, 866259ee775SQu Wenruo "invalid root item size, have %u expect %zu", 867259ee775SQu Wenruo btrfs_item_size_nr(leaf, slot), sizeof(ri)); 868259ee775SQu Wenruo } 869259ee775SQu Wenruo 870259ee775SQu Wenruo read_extent_buffer(leaf, &ri, btrfs_item_ptr_offset(leaf, slot), 871259ee775SQu Wenruo sizeof(ri)); 872259ee775SQu Wenruo 873259ee775SQu Wenruo /* Generation related */ 874259ee775SQu Wenruo if (btrfs_root_generation(&ri) > 875259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1) { 876259ee775SQu Wenruo generic_err(leaf, slot, 877259ee775SQu Wenruo "invalid root generation, have %llu expect (0, %llu]", 878259ee775SQu Wenruo btrfs_root_generation(&ri), 879259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1); 880259ee775SQu Wenruo return -EUCLEAN; 881259ee775SQu Wenruo } 882259ee775SQu Wenruo if (btrfs_root_generation_v2(&ri) > 883259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1) { 884259ee775SQu Wenruo generic_err(leaf, slot, 885259ee775SQu Wenruo "invalid root v2 generation, have %llu expect (0, %llu]", 886259ee775SQu Wenruo btrfs_root_generation_v2(&ri), 887259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1); 888259ee775SQu Wenruo return -EUCLEAN; 889259ee775SQu Wenruo } 890259ee775SQu Wenruo if (btrfs_root_last_snapshot(&ri) > 891259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1) { 892259ee775SQu Wenruo generic_err(leaf, slot, 893259ee775SQu Wenruo "invalid root last_snapshot, have %llu expect (0, %llu]", 894259ee775SQu Wenruo btrfs_root_last_snapshot(&ri), 895259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1); 896259ee775SQu Wenruo return -EUCLEAN; 897259ee775SQu Wenruo } 898259ee775SQu Wenruo 899259ee775SQu Wenruo /* Alignment and level check */ 900259ee775SQu Wenruo if (!IS_ALIGNED(btrfs_root_bytenr(&ri), fs_info->sectorsize)) { 901259ee775SQu Wenruo generic_err(leaf, slot, 902259ee775SQu Wenruo "invalid root bytenr, have %llu expect to be aligned to %u", 903259ee775SQu Wenruo btrfs_root_bytenr(&ri), fs_info->sectorsize); 904259ee775SQu Wenruo return -EUCLEAN; 905259ee775SQu Wenruo } 906259ee775SQu Wenruo if (btrfs_root_level(&ri) >= BTRFS_MAX_LEVEL) { 907259ee775SQu Wenruo generic_err(leaf, slot, 908259ee775SQu Wenruo "invalid root level, have %u expect [0, %u]", 909259ee775SQu Wenruo btrfs_root_level(&ri), BTRFS_MAX_LEVEL - 1); 910259ee775SQu Wenruo return -EUCLEAN; 911259ee775SQu Wenruo } 912259ee775SQu Wenruo if (ri.drop_level >= BTRFS_MAX_LEVEL) { 913259ee775SQu Wenruo generic_err(leaf, slot, 914259ee775SQu Wenruo "invalid root level, have %u expect [0, %u]", 915259ee775SQu Wenruo ri.drop_level, BTRFS_MAX_LEVEL - 1); 916259ee775SQu Wenruo return -EUCLEAN; 917259ee775SQu Wenruo } 918259ee775SQu Wenruo 919259ee775SQu Wenruo /* Flags check */ 920259ee775SQu Wenruo if (btrfs_root_flags(&ri) & ~valid_root_flags) { 921259ee775SQu Wenruo generic_err(leaf, slot, 922259ee775SQu Wenruo "invalid root flags, have 0x%llx expect mask 0x%llx", 923259ee775SQu Wenruo btrfs_root_flags(&ri), valid_root_flags); 924259ee775SQu Wenruo return -EUCLEAN; 925259ee775SQu Wenruo } 926259ee775SQu Wenruo return 0; 927259ee775SQu Wenruo } 928259ee775SQu Wenruo 929f82d1c7cSQu Wenruo __printf(3,4) 930f82d1c7cSQu Wenruo __cold 931f82d1c7cSQu Wenruo static void extent_err(const struct extent_buffer *eb, int slot, 932f82d1c7cSQu Wenruo const char *fmt, ...) 933f82d1c7cSQu Wenruo { 934f82d1c7cSQu Wenruo struct btrfs_key key; 935f82d1c7cSQu Wenruo struct va_format vaf; 936f82d1c7cSQu Wenruo va_list args; 937f82d1c7cSQu Wenruo u64 bytenr; 938f82d1c7cSQu Wenruo u64 len; 939f82d1c7cSQu Wenruo 940f82d1c7cSQu Wenruo btrfs_item_key_to_cpu(eb, &key, slot); 941f82d1c7cSQu Wenruo bytenr = key.objectid; 942e2406a6fSQu Wenruo if (key.type == BTRFS_METADATA_ITEM_KEY || 943e2406a6fSQu Wenruo key.type == BTRFS_TREE_BLOCK_REF_KEY || 944e2406a6fSQu Wenruo key.type == BTRFS_SHARED_BLOCK_REF_KEY) 945f82d1c7cSQu Wenruo len = eb->fs_info->nodesize; 946f82d1c7cSQu Wenruo else 947f82d1c7cSQu Wenruo len = key.offset; 948f82d1c7cSQu Wenruo va_start(args, fmt); 949f82d1c7cSQu Wenruo 950f82d1c7cSQu Wenruo vaf.fmt = fmt; 951f82d1c7cSQu Wenruo vaf.va = &args; 952f82d1c7cSQu Wenruo 953f82d1c7cSQu Wenruo btrfs_crit(eb->fs_info, 954f82d1c7cSQu Wenruo "corrupt %s: block=%llu slot=%d extent bytenr=%llu len=%llu %pV", 955f82d1c7cSQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 956f82d1c7cSQu Wenruo eb->start, slot, bytenr, len, &vaf); 957f82d1c7cSQu Wenruo va_end(args); 958f82d1c7cSQu Wenruo } 959f82d1c7cSQu Wenruo 960f82d1c7cSQu Wenruo static int check_extent_item(struct extent_buffer *leaf, 961f82d1c7cSQu Wenruo struct btrfs_key *key, int slot) 962f82d1c7cSQu Wenruo { 963f82d1c7cSQu Wenruo struct btrfs_fs_info *fs_info = leaf->fs_info; 964f82d1c7cSQu Wenruo struct btrfs_extent_item *ei; 965f82d1c7cSQu Wenruo bool is_tree_block = false; 966f82d1c7cSQu Wenruo unsigned long ptr; /* Current pointer inside inline refs */ 967f82d1c7cSQu Wenruo unsigned long end; /* Extent item end */ 968f82d1c7cSQu Wenruo const u32 item_size = btrfs_item_size_nr(leaf, slot); 969f82d1c7cSQu Wenruo u64 flags; 970f82d1c7cSQu Wenruo u64 generation; 971f82d1c7cSQu Wenruo u64 total_refs; /* Total refs in btrfs_extent_item */ 972f82d1c7cSQu Wenruo u64 inline_refs = 0; /* found total inline refs */ 973f82d1c7cSQu Wenruo 974f82d1c7cSQu Wenruo if (key->type == BTRFS_METADATA_ITEM_KEY && 975f82d1c7cSQu Wenruo !btrfs_fs_incompat(fs_info, SKINNY_METADATA)) { 976f82d1c7cSQu Wenruo generic_err(leaf, slot, 977f82d1c7cSQu Wenruo "invalid key type, METADATA_ITEM type invalid when SKINNY_METADATA feature disabled"); 978f82d1c7cSQu Wenruo return -EUCLEAN; 979f82d1c7cSQu Wenruo } 980f82d1c7cSQu Wenruo /* key->objectid is the bytenr for both key types */ 981f82d1c7cSQu Wenruo if (!IS_ALIGNED(key->objectid, fs_info->sectorsize)) { 982f82d1c7cSQu Wenruo generic_err(leaf, slot, 983f82d1c7cSQu Wenruo "invalid key objectid, have %llu expect to be aligned to %u", 984f82d1c7cSQu Wenruo key->objectid, fs_info->sectorsize); 985f82d1c7cSQu Wenruo return -EUCLEAN; 986f82d1c7cSQu Wenruo } 987f82d1c7cSQu Wenruo 988f82d1c7cSQu Wenruo /* key->offset is tree level for METADATA_ITEM_KEY */ 989f82d1c7cSQu Wenruo if (key->type == BTRFS_METADATA_ITEM_KEY && 990f82d1c7cSQu Wenruo key->offset >= BTRFS_MAX_LEVEL) { 991f82d1c7cSQu Wenruo extent_err(leaf, slot, 992f82d1c7cSQu Wenruo "invalid tree level, have %llu expect [0, %u]", 993f82d1c7cSQu Wenruo key->offset, BTRFS_MAX_LEVEL - 1); 994f82d1c7cSQu Wenruo return -EUCLEAN; 995f82d1c7cSQu Wenruo } 996f82d1c7cSQu Wenruo 997f82d1c7cSQu Wenruo /* 998f82d1c7cSQu Wenruo * EXTENT/METADATA_ITEM consists of: 999f82d1c7cSQu Wenruo * 1) One btrfs_extent_item 1000f82d1c7cSQu Wenruo * Records the total refs, type and generation of the extent. 1001f82d1c7cSQu Wenruo * 1002f82d1c7cSQu Wenruo * 2) One btrfs_tree_block_info (for EXTENT_ITEM and tree backref only) 1003f82d1c7cSQu Wenruo * Records the first key and level of the tree block. 1004f82d1c7cSQu Wenruo * 1005f82d1c7cSQu Wenruo * 2) Zero or more btrfs_extent_inline_ref(s) 1006f82d1c7cSQu Wenruo * Each inline ref has one btrfs_extent_inline_ref shows: 1007f82d1c7cSQu Wenruo * 2.1) The ref type, one of the 4 1008f82d1c7cSQu Wenruo * TREE_BLOCK_REF Tree block only 1009f82d1c7cSQu Wenruo * SHARED_BLOCK_REF Tree block only 1010f82d1c7cSQu Wenruo * EXTENT_DATA_REF Data only 1011f82d1c7cSQu Wenruo * SHARED_DATA_REF Data only 1012f82d1c7cSQu Wenruo * 2.2) Ref type specific data 1013f82d1c7cSQu Wenruo * Either using btrfs_extent_inline_ref::offset, or specific 1014f82d1c7cSQu Wenruo * data structure. 1015f82d1c7cSQu Wenruo */ 1016f82d1c7cSQu Wenruo if (item_size < sizeof(*ei)) { 1017f82d1c7cSQu Wenruo extent_err(leaf, slot, 1018f82d1c7cSQu Wenruo "invalid item size, have %u expect [%zu, %u)", 1019f82d1c7cSQu Wenruo item_size, sizeof(*ei), 1020f82d1c7cSQu Wenruo BTRFS_LEAF_DATA_SIZE(fs_info)); 1021f82d1c7cSQu Wenruo return -EUCLEAN; 1022f82d1c7cSQu Wenruo } 1023f82d1c7cSQu Wenruo end = item_size + btrfs_item_ptr_offset(leaf, slot); 1024f82d1c7cSQu Wenruo 1025f82d1c7cSQu Wenruo /* Checks against extent_item */ 1026f82d1c7cSQu Wenruo ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item); 1027f82d1c7cSQu Wenruo flags = btrfs_extent_flags(leaf, ei); 1028f82d1c7cSQu Wenruo total_refs = btrfs_extent_refs(leaf, ei); 1029f82d1c7cSQu Wenruo generation = btrfs_extent_generation(leaf, ei); 1030f82d1c7cSQu Wenruo if (generation > btrfs_super_generation(fs_info->super_copy) + 1) { 1031f82d1c7cSQu Wenruo extent_err(leaf, slot, 1032f82d1c7cSQu Wenruo "invalid generation, have %llu expect (0, %llu]", 1033f82d1c7cSQu Wenruo generation, 1034f82d1c7cSQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1); 1035f82d1c7cSQu Wenruo return -EUCLEAN; 1036f82d1c7cSQu Wenruo } 1037*c1499166SDavid Sterba if (!has_single_bit_set(flags & (BTRFS_EXTENT_FLAG_DATA | 1038f82d1c7cSQu Wenruo BTRFS_EXTENT_FLAG_TREE_BLOCK))) { 1039f82d1c7cSQu Wenruo extent_err(leaf, slot, 1040f82d1c7cSQu Wenruo "invalid extent flag, have 0x%llx expect 1 bit set in 0x%llx", 1041f82d1c7cSQu Wenruo flags, BTRFS_EXTENT_FLAG_DATA | 1042f82d1c7cSQu Wenruo BTRFS_EXTENT_FLAG_TREE_BLOCK); 1043f82d1c7cSQu Wenruo return -EUCLEAN; 1044f82d1c7cSQu Wenruo } 1045f82d1c7cSQu Wenruo is_tree_block = !!(flags & BTRFS_EXTENT_FLAG_TREE_BLOCK); 1046f82d1c7cSQu Wenruo if (is_tree_block) { 1047f82d1c7cSQu Wenruo if (key->type == BTRFS_EXTENT_ITEM_KEY && 1048f82d1c7cSQu Wenruo key->offset != fs_info->nodesize) { 1049f82d1c7cSQu Wenruo extent_err(leaf, slot, 1050f82d1c7cSQu Wenruo "invalid extent length, have %llu expect %u", 1051f82d1c7cSQu Wenruo key->offset, fs_info->nodesize); 1052f82d1c7cSQu Wenruo return -EUCLEAN; 1053f82d1c7cSQu Wenruo } 1054f82d1c7cSQu Wenruo } else { 1055f82d1c7cSQu Wenruo if (key->type != BTRFS_EXTENT_ITEM_KEY) { 1056f82d1c7cSQu Wenruo extent_err(leaf, slot, 1057f82d1c7cSQu Wenruo "invalid key type, have %u expect %u for data backref", 1058f82d1c7cSQu Wenruo key->type, BTRFS_EXTENT_ITEM_KEY); 1059f82d1c7cSQu Wenruo return -EUCLEAN; 1060f82d1c7cSQu Wenruo } 1061f82d1c7cSQu Wenruo if (!IS_ALIGNED(key->offset, fs_info->sectorsize)) { 1062f82d1c7cSQu Wenruo extent_err(leaf, slot, 1063f82d1c7cSQu Wenruo "invalid extent length, have %llu expect aligned to %u", 1064f82d1c7cSQu Wenruo key->offset, fs_info->sectorsize); 1065f82d1c7cSQu Wenruo return -EUCLEAN; 1066f82d1c7cSQu Wenruo } 1067f82d1c7cSQu Wenruo } 1068f82d1c7cSQu Wenruo ptr = (unsigned long)(struct btrfs_extent_item *)(ei + 1); 1069f82d1c7cSQu Wenruo 1070f82d1c7cSQu Wenruo /* Check the special case of btrfs_tree_block_info */ 1071f82d1c7cSQu Wenruo if (is_tree_block && key->type != BTRFS_METADATA_ITEM_KEY) { 1072f82d1c7cSQu Wenruo struct btrfs_tree_block_info *info; 1073f82d1c7cSQu Wenruo 1074f82d1c7cSQu Wenruo info = (struct btrfs_tree_block_info *)ptr; 1075f82d1c7cSQu Wenruo if (btrfs_tree_block_level(leaf, info) >= BTRFS_MAX_LEVEL) { 1076f82d1c7cSQu Wenruo extent_err(leaf, slot, 1077f82d1c7cSQu Wenruo "invalid tree block info level, have %u expect [0, %u]", 1078f82d1c7cSQu Wenruo btrfs_tree_block_level(leaf, info), 1079f82d1c7cSQu Wenruo BTRFS_MAX_LEVEL - 1); 1080f82d1c7cSQu Wenruo return -EUCLEAN; 1081f82d1c7cSQu Wenruo } 1082f82d1c7cSQu Wenruo ptr = (unsigned long)(struct btrfs_tree_block_info *)(info + 1); 1083f82d1c7cSQu Wenruo } 1084f82d1c7cSQu Wenruo 1085f82d1c7cSQu Wenruo /* Check inline refs */ 1086f82d1c7cSQu Wenruo while (ptr < end) { 1087f82d1c7cSQu Wenruo struct btrfs_extent_inline_ref *iref; 1088f82d1c7cSQu Wenruo struct btrfs_extent_data_ref *dref; 1089f82d1c7cSQu Wenruo struct btrfs_shared_data_ref *sref; 1090f82d1c7cSQu Wenruo u64 dref_offset; 1091f82d1c7cSQu Wenruo u64 inline_offset; 1092f82d1c7cSQu Wenruo u8 inline_type; 1093f82d1c7cSQu Wenruo 1094f82d1c7cSQu Wenruo if (ptr + sizeof(*iref) > end) { 1095f82d1c7cSQu Wenruo extent_err(leaf, slot, 1096f82d1c7cSQu Wenruo "inline ref item overflows extent item, ptr %lu iref size %zu end %lu", 1097f82d1c7cSQu Wenruo ptr, sizeof(*iref), end); 1098f82d1c7cSQu Wenruo return -EUCLEAN; 1099f82d1c7cSQu Wenruo } 1100f82d1c7cSQu Wenruo iref = (struct btrfs_extent_inline_ref *)ptr; 1101f82d1c7cSQu Wenruo inline_type = btrfs_extent_inline_ref_type(leaf, iref); 1102f82d1c7cSQu Wenruo inline_offset = btrfs_extent_inline_ref_offset(leaf, iref); 1103f82d1c7cSQu Wenruo if (ptr + btrfs_extent_inline_ref_size(inline_type) > end) { 1104f82d1c7cSQu Wenruo extent_err(leaf, slot, 1105f82d1c7cSQu Wenruo "inline ref item overflows extent item, ptr %lu iref size %u end %lu", 1106f82d1c7cSQu Wenruo ptr, inline_type, end); 1107f82d1c7cSQu Wenruo return -EUCLEAN; 1108f82d1c7cSQu Wenruo } 1109f82d1c7cSQu Wenruo 1110f82d1c7cSQu Wenruo switch (inline_type) { 1111f82d1c7cSQu Wenruo /* inline_offset is subvolid of the owner, no need to check */ 1112f82d1c7cSQu Wenruo case BTRFS_TREE_BLOCK_REF_KEY: 1113f82d1c7cSQu Wenruo inline_refs++; 1114f82d1c7cSQu Wenruo break; 1115f82d1c7cSQu Wenruo /* Contains parent bytenr */ 1116f82d1c7cSQu Wenruo case BTRFS_SHARED_BLOCK_REF_KEY: 1117f82d1c7cSQu Wenruo if (!IS_ALIGNED(inline_offset, fs_info->sectorsize)) { 1118f82d1c7cSQu Wenruo extent_err(leaf, slot, 1119f82d1c7cSQu Wenruo "invalid tree parent bytenr, have %llu expect aligned to %u", 1120f82d1c7cSQu Wenruo inline_offset, fs_info->sectorsize); 1121f82d1c7cSQu Wenruo return -EUCLEAN; 1122f82d1c7cSQu Wenruo } 1123f82d1c7cSQu Wenruo inline_refs++; 1124f82d1c7cSQu Wenruo break; 1125f82d1c7cSQu Wenruo /* 1126f82d1c7cSQu Wenruo * Contains owner subvolid, owner key objectid, adjusted offset. 1127f82d1c7cSQu Wenruo * The only obvious corruption can happen in that offset. 1128f82d1c7cSQu Wenruo */ 1129f82d1c7cSQu Wenruo case BTRFS_EXTENT_DATA_REF_KEY: 1130f82d1c7cSQu Wenruo dref = (struct btrfs_extent_data_ref *)(&iref->offset); 1131f82d1c7cSQu Wenruo dref_offset = btrfs_extent_data_ref_offset(leaf, dref); 1132f82d1c7cSQu Wenruo if (!IS_ALIGNED(dref_offset, fs_info->sectorsize)) { 1133f82d1c7cSQu Wenruo extent_err(leaf, slot, 1134f82d1c7cSQu Wenruo "invalid data ref offset, have %llu expect aligned to %u", 1135f82d1c7cSQu Wenruo dref_offset, fs_info->sectorsize); 1136f82d1c7cSQu Wenruo return -EUCLEAN; 1137f82d1c7cSQu Wenruo } 1138f82d1c7cSQu Wenruo inline_refs += btrfs_extent_data_ref_count(leaf, dref); 1139f82d1c7cSQu Wenruo break; 1140f82d1c7cSQu Wenruo /* Contains parent bytenr and ref count */ 1141f82d1c7cSQu Wenruo case BTRFS_SHARED_DATA_REF_KEY: 1142f82d1c7cSQu Wenruo sref = (struct btrfs_shared_data_ref *)(iref + 1); 1143f82d1c7cSQu Wenruo if (!IS_ALIGNED(inline_offset, fs_info->sectorsize)) { 1144f82d1c7cSQu Wenruo extent_err(leaf, slot, 1145f82d1c7cSQu Wenruo "invalid data parent bytenr, have %llu expect aligned to %u", 1146f82d1c7cSQu Wenruo inline_offset, fs_info->sectorsize); 1147f82d1c7cSQu Wenruo return -EUCLEAN; 1148f82d1c7cSQu Wenruo } 1149f82d1c7cSQu Wenruo inline_refs += btrfs_shared_data_ref_count(leaf, sref); 1150f82d1c7cSQu Wenruo break; 1151f82d1c7cSQu Wenruo default: 1152f82d1c7cSQu Wenruo extent_err(leaf, slot, "unknown inline ref type: %u", 1153f82d1c7cSQu Wenruo inline_type); 1154f82d1c7cSQu Wenruo return -EUCLEAN; 1155f82d1c7cSQu Wenruo } 1156f82d1c7cSQu Wenruo ptr += btrfs_extent_inline_ref_size(inline_type); 1157f82d1c7cSQu Wenruo } 1158f82d1c7cSQu Wenruo /* No padding is allowed */ 1159f82d1c7cSQu Wenruo if (ptr != end) { 1160f82d1c7cSQu Wenruo extent_err(leaf, slot, 1161f82d1c7cSQu Wenruo "invalid extent item size, padding bytes found"); 1162f82d1c7cSQu Wenruo return -EUCLEAN; 1163f82d1c7cSQu Wenruo } 1164f82d1c7cSQu Wenruo 1165f82d1c7cSQu Wenruo /* Finally, check the inline refs against total refs */ 1166f82d1c7cSQu Wenruo if (inline_refs > total_refs) { 1167f82d1c7cSQu Wenruo extent_err(leaf, slot, 1168f82d1c7cSQu Wenruo "invalid extent refs, have %llu expect >= inline %llu", 1169f82d1c7cSQu Wenruo total_refs, inline_refs); 1170f82d1c7cSQu Wenruo return -EUCLEAN; 1171f82d1c7cSQu Wenruo } 1172f82d1c7cSQu Wenruo return 0; 1173f82d1c7cSQu Wenruo } 1174f82d1c7cSQu Wenruo 1175e2406a6fSQu Wenruo static int check_simple_keyed_refs(struct extent_buffer *leaf, 1176e2406a6fSQu Wenruo struct btrfs_key *key, int slot) 1177e2406a6fSQu Wenruo { 1178e2406a6fSQu Wenruo u32 expect_item_size = 0; 1179e2406a6fSQu Wenruo 1180e2406a6fSQu Wenruo if (key->type == BTRFS_SHARED_DATA_REF_KEY) 1181e2406a6fSQu Wenruo expect_item_size = sizeof(struct btrfs_shared_data_ref); 1182e2406a6fSQu Wenruo 1183e2406a6fSQu Wenruo if (btrfs_item_size_nr(leaf, slot) != expect_item_size) { 1184e2406a6fSQu Wenruo generic_err(leaf, slot, 1185e2406a6fSQu Wenruo "invalid item size, have %u expect %u for key type %u", 1186e2406a6fSQu Wenruo btrfs_item_size_nr(leaf, slot), 1187e2406a6fSQu Wenruo expect_item_size, key->type); 1188e2406a6fSQu Wenruo return -EUCLEAN; 1189e2406a6fSQu Wenruo } 1190e2406a6fSQu Wenruo if (!IS_ALIGNED(key->objectid, leaf->fs_info->sectorsize)) { 1191e2406a6fSQu Wenruo generic_err(leaf, slot, 1192e2406a6fSQu Wenruo "invalid key objectid for shared block ref, have %llu expect aligned to %u", 1193e2406a6fSQu Wenruo key->objectid, leaf->fs_info->sectorsize); 1194e2406a6fSQu Wenruo return -EUCLEAN; 1195e2406a6fSQu Wenruo } 1196e2406a6fSQu Wenruo if (key->type != BTRFS_TREE_BLOCK_REF_KEY && 1197e2406a6fSQu Wenruo !IS_ALIGNED(key->offset, leaf->fs_info->sectorsize)) { 1198e2406a6fSQu Wenruo extent_err(leaf, slot, 1199e2406a6fSQu Wenruo "invalid tree parent bytenr, have %llu expect aligned to %u", 1200e2406a6fSQu Wenruo key->offset, leaf->fs_info->sectorsize); 1201e2406a6fSQu Wenruo return -EUCLEAN; 1202e2406a6fSQu Wenruo } 1203e2406a6fSQu Wenruo return 0; 1204e2406a6fSQu Wenruo } 1205e2406a6fSQu Wenruo 12060785a9aaSQu Wenruo static int check_extent_data_ref(struct extent_buffer *leaf, 12070785a9aaSQu Wenruo struct btrfs_key *key, int slot) 12080785a9aaSQu Wenruo { 12090785a9aaSQu Wenruo struct btrfs_extent_data_ref *dref; 12100785a9aaSQu Wenruo unsigned long ptr = btrfs_item_ptr_offset(leaf, slot); 12110785a9aaSQu Wenruo const unsigned long end = ptr + btrfs_item_size_nr(leaf, slot); 12120785a9aaSQu Wenruo 12130785a9aaSQu Wenruo if (btrfs_item_size_nr(leaf, slot) % sizeof(*dref) != 0) { 12140785a9aaSQu Wenruo generic_err(leaf, slot, 12150785a9aaSQu Wenruo "invalid item size, have %u expect aligned to %zu for key type %u", 12160785a9aaSQu Wenruo btrfs_item_size_nr(leaf, slot), 12170785a9aaSQu Wenruo sizeof(*dref), key->type); 12180785a9aaSQu Wenruo } 12190785a9aaSQu Wenruo if (!IS_ALIGNED(key->objectid, leaf->fs_info->sectorsize)) { 12200785a9aaSQu Wenruo generic_err(leaf, slot, 12210785a9aaSQu Wenruo "invalid key objectid for shared block ref, have %llu expect aligned to %u", 12220785a9aaSQu Wenruo key->objectid, leaf->fs_info->sectorsize); 12230785a9aaSQu Wenruo return -EUCLEAN; 12240785a9aaSQu Wenruo } 12250785a9aaSQu Wenruo for (; ptr < end; ptr += sizeof(*dref)) { 12260785a9aaSQu Wenruo u64 root_objectid; 12270785a9aaSQu Wenruo u64 owner; 12280785a9aaSQu Wenruo u64 offset; 12290785a9aaSQu Wenruo u64 hash; 12300785a9aaSQu Wenruo 12310785a9aaSQu Wenruo dref = (struct btrfs_extent_data_ref *)ptr; 12320785a9aaSQu Wenruo root_objectid = btrfs_extent_data_ref_root(leaf, dref); 12330785a9aaSQu Wenruo owner = btrfs_extent_data_ref_objectid(leaf, dref); 12340785a9aaSQu Wenruo offset = btrfs_extent_data_ref_offset(leaf, dref); 12350785a9aaSQu Wenruo hash = hash_extent_data_ref(root_objectid, owner, offset); 12360785a9aaSQu Wenruo if (hash != key->offset) { 12370785a9aaSQu Wenruo extent_err(leaf, slot, 12380785a9aaSQu Wenruo "invalid extent data ref hash, item has 0x%016llx key has 0x%016llx", 12390785a9aaSQu Wenruo hash, key->offset); 12400785a9aaSQu Wenruo return -EUCLEAN; 12410785a9aaSQu Wenruo } 12420785a9aaSQu Wenruo if (!IS_ALIGNED(offset, leaf->fs_info->sectorsize)) { 12430785a9aaSQu Wenruo extent_err(leaf, slot, 12440785a9aaSQu Wenruo "invalid extent data backref offset, have %llu expect aligned to %u", 12450785a9aaSQu Wenruo offset, leaf->fs_info->sectorsize); 12460785a9aaSQu Wenruo } 12470785a9aaSQu Wenruo } 12480785a9aaSQu Wenruo return 0; 12490785a9aaSQu Wenruo } 12500785a9aaSQu Wenruo 125171bf92a9SQu Wenruo #define inode_ref_err(fs_info, eb, slot, fmt, args...) \ 125271bf92a9SQu Wenruo inode_item_err(fs_info, eb, slot, fmt, ##args) 125371bf92a9SQu Wenruo static int check_inode_ref(struct extent_buffer *leaf, 125471bf92a9SQu Wenruo struct btrfs_key *key, struct btrfs_key *prev_key, 125571bf92a9SQu Wenruo int slot) 125671bf92a9SQu Wenruo { 125771bf92a9SQu Wenruo struct btrfs_inode_ref *iref; 125871bf92a9SQu Wenruo unsigned long ptr; 125971bf92a9SQu Wenruo unsigned long end; 126071bf92a9SQu Wenruo 126171bf92a9SQu Wenruo /* namelen can't be 0, so item_size == sizeof() is also invalid */ 126271bf92a9SQu Wenruo if (btrfs_item_size_nr(leaf, slot) <= sizeof(*iref)) { 126371bf92a9SQu Wenruo inode_ref_err(fs_info, leaf, slot, 126471bf92a9SQu Wenruo "invalid item size, have %u expect (%zu, %u)", 126571bf92a9SQu Wenruo btrfs_item_size_nr(leaf, slot), 126671bf92a9SQu Wenruo sizeof(*iref), BTRFS_LEAF_DATA_SIZE(leaf->fs_info)); 126771bf92a9SQu Wenruo return -EUCLEAN; 126871bf92a9SQu Wenruo } 126971bf92a9SQu Wenruo 127071bf92a9SQu Wenruo ptr = btrfs_item_ptr_offset(leaf, slot); 127171bf92a9SQu Wenruo end = ptr + btrfs_item_size_nr(leaf, slot); 127271bf92a9SQu Wenruo while (ptr < end) { 127371bf92a9SQu Wenruo u16 namelen; 127471bf92a9SQu Wenruo 127571bf92a9SQu Wenruo if (ptr + sizeof(iref) > end) { 127671bf92a9SQu Wenruo inode_ref_err(fs_info, leaf, slot, 127771bf92a9SQu Wenruo "inode ref overflow, ptr %lu end %lu inode_ref_size %zu", 127871bf92a9SQu Wenruo ptr, end, sizeof(iref)); 127971bf92a9SQu Wenruo return -EUCLEAN; 128071bf92a9SQu Wenruo } 128171bf92a9SQu Wenruo 128271bf92a9SQu Wenruo iref = (struct btrfs_inode_ref *)ptr; 128371bf92a9SQu Wenruo namelen = btrfs_inode_ref_name_len(leaf, iref); 128471bf92a9SQu Wenruo if (ptr + sizeof(*iref) + namelen > end) { 128571bf92a9SQu Wenruo inode_ref_err(fs_info, leaf, slot, 128671bf92a9SQu Wenruo "inode ref overflow, ptr %lu end %lu namelen %u", 128771bf92a9SQu Wenruo ptr, end, namelen); 128871bf92a9SQu Wenruo return -EUCLEAN; 128971bf92a9SQu Wenruo } 129071bf92a9SQu Wenruo 129171bf92a9SQu Wenruo /* 129271bf92a9SQu Wenruo * NOTE: In theory we should record all found index numbers 129371bf92a9SQu Wenruo * to find any duplicated indexes, but that will be too time 129471bf92a9SQu Wenruo * consuming for inodes with too many hard links. 129571bf92a9SQu Wenruo */ 129671bf92a9SQu Wenruo ptr += sizeof(*iref) + namelen; 129771bf92a9SQu Wenruo } 129871bf92a9SQu Wenruo return 0; 129971bf92a9SQu Wenruo } 130071bf92a9SQu Wenruo 130182fc28fbSQu Wenruo /* 1302557ea5ddSQu Wenruo * Common point to switch the item-specific validation. 1303557ea5ddSQu Wenruo */ 13040076bc89SDavid Sterba static int check_leaf_item(struct extent_buffer *leaf, 13054e9845efSFilipe Manana struct btrfs_key *key, int slot, 13064e9845efSFilipe Manana struct btrfs_key *prev_key) 1307557ea5ddSQu Wenruo { 1308557ea5ddSQu Wenruo int ret = 0; 1309075cb3c7SQu Wenruo struct btrfs_chunk *chunk; 1310557ea5ddSQu Wenruo 1311557ea5ddSQu Wenruo switch (key->type) { 1312557ea5ddSQu Wenruo case BTRFS_EXTENT_DATA_KEY: 13134e9845efSFilipe Manana ret = check_extent_data_item(leaf, key, slot, prev_key); 1314557ea5ddSQu Wenruo break; 1315557ea5ddSQu Wenruo case BTRFS_EXTENT_CSUM_KEY: 131668128ce7SDavid Sterba ret = check_csum_item(leaf, key, slot); 1317557ea5ddSQu Wenruo break; 1318ad7b0368SQu Wenruo case BTRFS_DIR_ITEM_KEY: 1319ad7b0368SQu Wenruo case BTRFS_DIR_INDEX_KEY: 1320ad7b0368SQu Wenruo case BTRFS_XATTR_ITEM_KEY: 1321c18679ebSQu Wenruo ret = check_dir_item(leaf, key, prev_key, slot); 1322ad7b0368SQu Wenruo break; 132371bf92a9SQu Wenruo case BTRFS_INODE_REF_KEY: 132471bf92a9SQu Wenruo ret = check_inode_ref(leaf, key, prev_key, slot); 132571bf92a9SQu Wenruo break; 1326fce466eaSQu Wenruo case BTRFS_BLOCK_GROUP_ITEM_KEY: 1327af60ce2bSDavid Sterba ret = check_block_group_item(leaf, key, slot); 1328fce466eaSQu Wenruo break; 1329075cb3c7SQu Wenruo case BTRFS_CHUNK_ITEM_KEY: 1330075cb3c7SQu Wenruo chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); 1331ddaf1d5aSDavid Sterba ret = btrfs_check_chunk_valid(leaf, chunk, key->offset); 1332075cb3c7SQu Wenruo break; 1333ab4ba2e1SQu Wenruo case BTRFS_DEV_ITEM_KEY: 1334412a2312SDavid Sterba ret = check_dev_item(leaf, key, slot); 1335ab4ba2e1SQu Wenruo break; 1336496245caSQu Wenruo case BTRFS_INODE_ITEM_KEY: 133739e57f49SDavid Sterba ret = check_inode_item(leaf, key, slot); 1338496245caSQu Wenruo break; 1339259ee775SQu Wenruo case BTRFS_ROOT_ITEM_KEY: 1340259ee775SQu Wenruo ret = check_root_item(leaf, key, slot); 1341259ee775SQu Wenruo break; 1342f82d1c7cSQu Wenruo case BTRFS_EXTENT_ITEM_KEY: 1343f82d1c7cSQu Wenruo case BTRFS_METADATA_ITEM_KEY: 1344f82d1c7cSQu Wenruo ret = check_extent_item(leaf, key, slot); 1345f82d1c7cSQu Wenruo break; 1346e2406a6fSQu Wenruo case BTRFS_TREE_BLOCK_REF_KEY: 1347e2406a6fSQu Wenruo case BTRFS_SHARED_DATA_REF_KEY: 1348e2406a6fSQu Wenruo case BTRFS_SHARED_BLOCK_REF_KEY: 1349e2406a6fSQu Wenruo ret = check_simple_keyed_refs(leaf, key, slot); 1350e2406a6fSQu Wenruo break; 13510785a9aaSQu Wenruo case BTRFS_EXTENT_DATA_REF_KEY: 13520785a9aaSQu Wenruo ret = check_extent_data_ref(leaf, key, slot); 13530785a9aaSQu Wenruo break; 1354557ea5ddSQu Wenruo } 1355557ea5ddSQu Wenruo return ret; 1356557ea5ddSQu Wenruo } 1357557ea5ddSQu Wenruo 1358e2ccd361SDavid Sterba static int check_leaf(struct extent_buffer *leaf, bool check_item_data) 1359557ea5ddSQu Wenruo { 1360e2ccd361SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 1361557ea5ddSQu Wenruo /* No valid key type is 0, so all key should be larger than this key */ 1362557ea5ddSQu Wenruo struct btrfs_key prev_key = {0, 0, 0}; 1363557ea5ddSQu Wenruo struct btrfs_key key; 1364557ea5ddSQu Wenruo u32 nritems = btrfs_header_nritems(leaf); 1365557ea5ddSQu Wenruo int slot; 1366557ea5ddSQu Wenruo 1367f556faa4SQu Wenruo if (btrfs_header_level(leaf) != 0) { 136886a6be3aSDavid Sterba generic_err(leaf, 0, 1369f556faa4SQu Wenruo "invalid level for leaf, have %d expect 0", 1370f556faa4SQu Wenruo btrfs_header_level(leaf)); 1371f556faa4SQu Wenruo return -EUCLEAN; 1372f556faa4SQu Wenruo } 1373f556faa4SQu Wenruo 1374557ea5ddSQu Wenruo /* 1375557ea5ddSQu Wenruo * Extent buffers from a relocation tree have a owner field that 1376557ea5ddSQu Wenruo * corresponds to the subvolume tree they are based on. So just from an 1377557ea5ddSQu Wenruo * extent buffer alone we can not find out what is the id of the 1378557ea5ddSQu Wenruo * corresponding subvolume tree, so we can not figure out if the extent 1379557ea5ddSQu Wenruo * buffer corresponds to the root of the relocation tree or not. So 1380557ea5ddSQu Wenruo * skip this check for relocation trees. 1381557ea5ddSQu Wenruo */ 1382557ea5ddSQu Wenruo if (nritems == 0 && !btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_RELOC)) { 1383ba480dd4SQu Wenruo u64 owner = btrfs_header_owner(leaf); 1384557ea5ddSQu Wenruo 1385ba480dd4SQu Wenruo /* These trees must never be empty */ 1386ba480dd4SQu Wenruo if (owner == BTRFS_ROOT_TREE_OBJECTID || 1387ba480dd4SQu Wenruo owner == BTRFS_CHUNK_TREE_OBJECTID || 1388ba480dd4SQu Wenruo owner == BTRFS_EXTENT_TREE_OBJECTID || 1389ba480dd4SQu Wenruo owner == BTRFS_DEV_TREE_OBJECTID || 1390ba480dd4SQu Wenruo owner == BTRFS_FS_TREE_OBJECTID || 1391ba480dd4SQu Wenruo owner == BTRFS_DATA_RELOC_TREE_OBJECTID) { 139286a6be3aSDavid Sterba generic_err(leaf, 0, 1393ba480dd4SQu Wenruo "invalid root, root %llu must never be empty", 1394ba480dd4SQu Wenruo owner); 1395ba480dd4SQu Wenruo return -EUCLEAN; 1396ba480dd4SQu Wenruo } 139762fdaa52SQu Wenruo /* Unknown tree */ 139862fdaa52SQu Wenruo if (owner == 0) { 139962fdaa52SQu Wenruo generic_err(leaf, 0, 140062fdaa52SQu Wenruo "invalid owner, root 0 is not defined"); 140162fdaa52SQu Wenruo return -EUCLEAN; 140262fdaa52SQu Wenruo } 1403557ea5ddSQu Wenruo return 0; 1404557ea5ddSQu Wenruo } 1405557ea5ddSQu Wenruo 1406557ea5ddSQu Wenruo if (nritems == 0) 1407557ea5ddSQu Wenruo return 0; 1408557ea5ddSQu Wenruo 1409557ea5ddSQu Wenruo /* 1410557ea5ddSQu Wenruo * Check the following things to make sure this is a good leaf, and 1411557ea5ddSQu Wenruo * leaf users won't need to bother with similar sanity checks: 1412557ea5ddSQu Wenruo * 1413557ea5ddSQu Wenruo * 1) key ordering 1414557ea5ddSQu Wenruo * 2) item offset and size 1415557ea5ddSQu Wenruo * No overlap, no hole, all inside the leaf. 1416557ea5ddSQu Wenruo * 3) item content 1417557ea5ddSQu Wenruo * If possible, do comprehensive sanity check. 1418557ea5ddSQu Wenruo * NOTE: All checks must only rely on the item data itself. 1419557ea5ddSQu Wenruo */ 1420557ea5ddSQu Wenruo for (slot = 0; slot < nritems; slot++) { 1421557ea5ddSQu Wenruo u32 item_end_expected; 1422557ea5ddSQu Wenruo int ret; 1423557ea5ddSQu Wenruo 1424557ea5ddSQu Wenruo btrfs_item_key_to_cpu(leaf, &key, slot); 1425557ea5ddSQu Wenruo 1426557ea5ddSQu Wenruo /* Make sure the keys are in the right order */ 1427557ea5ddSQu Wenruo if (btrfs_comp_cpu_keys(&prev_key, &key) >= 0) { 142886a6be3aSDavid Sterba generic_err(leaf, slot, 1429478d01b3SQu Wenruo "bad key order, prev (%llu %u %llu) current (%llu %u %llu)", 1430478d01b3SQu Wenruo prev_key.objectid, prev_key.type, 1431478d01b3SQu Wenruo prev_key.offset, key.objectid, key.type, 1432478d01b3SQu Wenruo key.offset); 1433557ea5ddSQu Wenruo return -EUCLEAN; 1434557ea5ddSQu Wenruo } 1435557ea5ddSQu Wenruo 1436557ea5ddSQu Wenruo /* 1437557ea5ddSQu Wenruo * Make sure the offset and ends are right, remember that the 1438557ea5ddSQu Wenruo * item data starts at the end of the leaf and grows towards the 1439557ea5ddSQu Wenruo * front. 1440557ea5ddSQu Wenruo */ 1441557ea5ddSQu Wenruo if (slot == 0) 1442557ea5ddSQu Wenruo item_end_expected = BTRFS_LEAF_DATA_SIZE(fs_info); 1443557ea5ddSQu Wenruo else 1444557ea5ddSQu Wenruo item_end_expected = btrfs_item_offset_nr(leaf, 1445557ea5ddSQu Wenruo slot - 1); 1446557ea5ddSQu Wenruo if (btrfs_item_end_nr(leaf, slot) != item_end_expected) { 144786a6be3aSDavid Sterba generic_err(leaf, slot, 1448478d01b3SQu Wenruo "unexpected item end, have %u expect %u", 1449478d01b3SQu Wenruo btrfs_item_end_nr(leaf, slot), 1450478d01b3SQu Wenruo item_end_expected); 1451557ea5ddSQu Wenruo return -EUCLEAN; 1452557ea5ddSQu Wenruo } 1453557ea5ddSQu Wenruo 1454557ea5ddSQu Wenruo /* 1455557ea5ddSQu Wenruo * Check to make sure that we don't point outside of the leaf, 1456557ea5ddSQu Wenruo * just in case all the items are consistent to each other, but 1457557ea5ddSQu Wenruo * all point outside of the leaf. 1458557ea5ddSQu Wenruo */ 1459557ea5ddSQu Wenruo if (btrfs_item_end_nr(leaf, slot) > 1460557ea5ddSQu Wenruo BTRFS_LEAF_DATA_SIZE(fs_info)) { 146186a6be3aSDavid Sterba generic_err(leaf, slot, 1462478d01b3SQu Wenruo "slot end outside of leaf, have %u expect range [0, %u]", 1463478d01b3SQu Wenruo btrfs_item_end_nr(leaf, slot), 1464478d01b3SQu Wenruo BTRFS_LEAF_DATA_SIZE(fs_info)); 1465557ea5ddSQu Wenruo return -EUCLEAN; 1466557ea5ddSQu Wenruo } 1467557ea5ddSQu Wenruo 1468557ea5ddSQu Wenruo /* Also check if the item pointer overlaps with btrfs item. */ 1469557ea5ddSQu Wenruo if (btrfs_item_nr_offset(slot) + sizeof(struct btrfs_item) > 1470557ea5ddSQu Wenruo btrfs_item_ptr_offset(leaf, slot)) { 147186a6be3aSDavid Sterba generic_err(leaf, slot, 1472478d01b3SQu Wenruo "slot overlaps with its data, item end %lu data start %lu", 1473478d01b3SQu Wenruo btrfs_item_nr_offset(slot) + 1474478d01b3SQu Wenruo sizeof(struct btrfs_item), 1475478d01b3SQu Wenruo btrfs_item_ptr_offset(leaf, slot)); 1476557ea5ddSQu Wenruo return -EUCLEAN; 1477557ea5ddSQu Wenruo } 1478557ea5ddSQu Wenruo 147969fc6cbbSQu Wenruo if (check_item_data) { 148069fc6cbbSQu Wenruo /* 148169fc6cbbSQu Wenruo * Check if the item size and content meet other 148269fc6cbbSQu Wenruo * criteria 148369fc6cbbSQu Wenruo */ 14844e9845efSFilipe Manana ret = check_leaf_item(leaf, &key, slot, &prev_key); 1485557ea5ddSQu Wenruo if (ret < 0) 1486557ea5ddSQu Wenruo return ret; 148769fc6cbbSQu Wenruo } 1488557ea5ddSQu Wenruo 1489557ea5ddSQu Wenruo prev_key.objectid = key.objectid; 1490557ea5ddSQu Wenruo prev_key.type = key.type; 1491557ea5ddSQu Wenruo prev_key.offset = key.offset; 1492557ea5ddSQu Wenruo } 1493557ea5ddSQu Wenruo 1494557ea5ddSQu Wenruo return 0; 1495557ea5ddSQu Wenruo } 1496557ea5ddSQu Wenruo 14971c4360eeSDavid Sterba int btrfs_check_leaf_full(struct extent_buffer *leaf) 149869fc6cbbSQu Wenruo { 1499e2ccd361SDavid Sterba return check_leaf(leaf, true); 150069fc6cbbSQu Wenruo } 150102529d7aSQu Wenruo ALLOW_ERROR_INJECTION(btrfs_check_leaf_full, ERRNO); 150269fc6cbbSQu Wenruo 1503cfdaad5eSDavid Sterba int btrfs_check_leaf_relaxed(struct extent_buffer *leaf) 15042f659546SQu Wenruo { 1505e2ccd361SDavid Sterba return check_leaf(leaf, false); 15062f659546SQu Wenruo } 15072f659546SQu Wenruo 1508813fd1dcSDavid Sterba int btrfs_check_node(struct extent_buffer *node) 1509557ea5ddSQu Wenruo { 1510813fd1dcSDavid Sterba struct btrfs_fs_info *fs_info = node->fs_info; 1511557ea5ddSQu Wenruo unsigned long nr = btrfs_header_nritems(node); 1512557ea5ddSQu Wenruo struct btrfs_key key, next_key; 1513557ea5ddSQu Wenruo int slot; 1514f556faa4SQu Wenruo int level = btrfs_header_level(node); 1515557ea5ddSQu Wenruo u64 bytenr; 1516557ea5ddSQu Wenruo int ret = 0; 1517557ea5ddSQu Wenruo 1518f556faa4SQu Wenruo if (level <= 0 || level >= BTRFS_MAX_LEVEL) { 151986a6be3aSDavid Sterba generic_err(node, 0, 1520f556faa4SQu Wenruo "invalid level for node, have %d expect [1, %d]", 1521f556faa4SQu Wenruo level, BTRFS_MAX_LEVEL - 1); 1522f556faa4SQu Wenruo return -EUCLEAN; 1523f556faa4SQu Wenruo } 15242f659546SQu Wenruo if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(fs_info)) { 15252f659546SQu Wenruo btrfs_crit(fs_info, 1526bba4f298SQu Wenruo "corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%u]", 15272f659546SQu Wenruo btrfs_header_owner(node), node->start, 1528bba4f298SQu Wenruo nr == 0 ? "small" : "large", nr, 15292f659546SQu Wenruo BTRFS_NODEPTRS_PER_BLOCK(fs_info)); 1530bba4f298SQu Wenruo return -EUCLEAN; 1531557ea5ddSQu Wenruo } 1532557ea5ddSQu Wenruo 1533557ea5ddSQu Wenruo for (slot = 0; slot < nr - 1; slot++) { 1534557ea5ddSQu Wenruo bytenr = btrfs_node_blockptr(node, slot); 1535557ea5ddSQu Wenruo btrfs_node_key_to_cpu(node, &key, slot); 1536557ea5ddSQu Wenruo btrfs_node_key_to_cpu(node, &next_key, slot + 1); 1537557ea5ddSQu Wenruo 1538557ea5ddSQu Wenruo if (!bytenr) { 153986a6be3aSDavid Sterba generic_err(node, slot, 1540bba4f298SQu Wenruo "invalid NULL node pointer"); 1541bba4f298SQu Wenruo ret = -EUCLEAN; 1542bba4f298SQu Wenruo goto out; 1543bba4f298SQu Wenruo } 15442f659546SQu Wenruo if (!IS_ALIGNED(bytenr, fs_info->sectorsize)) { 154586a6be3aSDavid Sterba generic_err(node, slot, 1546bba4f298SQu Wenruo "unaligned pointer, have %llu should be aligned to %u", 15472f659546SQu Wenruo bytenr, fs_info->sectorsize); 1548bba4f298SQu Wenruo ret = -EUCLEAN; 1549557ea5ddSQu Wenruo goto out; 1550557ea5ddSQu Wenruo } 1551557ea5ddSQu Wenruo 1552557ea5ddSQu Wenruo if (btrfs_comp_cpu_keys(&key, &next_key) >= 0) { 155386a6be3aSDavid Sterba generic_err(node, slot, 1554bba4f298SQu Wenruo "bad key order, current (%llu %u %llu) next (%llu %u %llu)", 1555bba4f298SQu Wenruo key.objectid, key.type, key.offset, 1556bba4f298SQu Wenruo next_key.objectid, next_key.type, 1557bba4f298SQu Wenruo next_key.offset); 1558bba4f298SQu Wenruo ret = -EUCLEAN; 1559557ea5ddSQu Wenruo goto out; 1560557ea5ddSQu Wenruo } 1561557ea5ddSQu Wenruo } 1562557ea5ddSQu Wenruo out: 1563557ea5ddSQu Wenruo return ret; 1564557ea5ddSQu Wenruo } 156502529d7aSQu Wenruo ALLOW_ERROR_INJECTION(btrfs_check_node, ERRNO); 1566