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 144557ea5ddSQu Wenruo fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); 145557ea5ddSQu Wenruo 146557ea5ddSQu Wenruo if (btrfs_file_extent_type(leaf, fi) > BTRFS_FILE_EXTENT_TYPES) { 1471fd715ffSDavid Sterba file_extent_err(leaf, slot, 1488806d718SQu Wenruo "invalid type for file extent, have %u expect range [0, %u]", 1498806d718SQu Wenruo btrfs_file_extent_type(leaf, fi), 1508806d718SQu Wenruo BTRFS_FILE_EXTENT_TYPES); 151557ea5ddSQu Wenruo return -EUCLEAN; 152557ea5ddSQu Wenruo } 153557ea5ddSQu Wenruo 154557ea5ddSQu Wenruo /* 15552042d8eSAndrea Gelmini * Support for new compression/encryption must introduce incompat flag, 156557ea5ddSQu Wenruo * and must be caught in open_ctree(). 157557ea5ddSQu Wenruo */ 158557ea5ddSQu Wenruo if (btrfs_file_extent_compression(leaf, fi) > BTRFS_COMPRESS_TYPES) { 1591fd715ffSDavid Sterba file_extent_err(leaf, slot, 1608806d718SQu Wenruo "invalid compression for file extent, have %u expect range [0, %u]", 1618806d718SQu Wenruo btrfs_file_extent_compression(leaf, fi), 1628806d718SQu Wenruo BTRFS_COMPRESS_TYPES); 163557ea5ddSQu Wenruo return -EUCLEAN; 164557ea5ddSQu Wenruo } 165557ea5ddSQu Wenruo if (btrfs_file_extent_encryption(leaf, fi)) { 1661fd715ffSDavid Sterba file_extent_err(leaf, slot, 1678806d718SQu Wenruo "invalid encryption for file extent, have %u expect 0", 1688806d718SQu Wenruo btrfs_file_extent_encryption(leaf, fi)); 169557ea5ddSQu Wenruo return -EUCLEAN; 170557ea5ddSQu Wenruo } 171557ea5ddSQu Wenruo if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_INLINE) { 172557ea5ddSQu Wenruo /* Inline extent must have 0 as key offset */ 173557ea5ddSQu Wenruo if (key->offset) { 1741fd715ffSDavid Sterba file_extent_err(leaf, slot, 1758806d718SQu Wenruo "invalid file_offset for inline file extent, have %llu expect 0", 1768806d718SQu Wenruo key->offset); 177557ea5ddSQu Wenruo return -EUCLEAN; 178557ea5ddSQu Wenruo } 179557ea5ddSQu Wenruo 180557ea5ddSQu Wenruo /* Compressed inline extent has no on-disk size, skip it */ 181557ea5ddSQu Wenruo if (btrfs_file_extent_compression(leaf, fi) != 182557ea5ddSQu Wenruo BTRFS_COMPRESS_NONE) 183557ea5ddSQu Wenruo return 0; 184557ea5ddSQu Wenruo 185557ea5ddSQu Wenruo /* Uncompressed inline extent size must match item size */ 186557ea5ddSQu Wenruo if (item_size != BTRFS_FILE_EXTENT_INLINE_DATA_START + 187557ea5ddSQu Wenruo btrfs_file_extent_ram_bytes(leaf, fi)) { 1881fd715ffSDavid Sterba file_extent_err(leaf, slot, 1898806d718SQu Wenruo "invalid ram_bytes for uncompressed inline extent, have %u expect %llu", 1908806d718SQu Wenruo item_size, BTRFS_FILE_EXTENT_INLINE_DATA_START + 1918806d718SQu Wenruo btrfs_file_extent_ram_bytes(leaf, fi)); 192557ea5ddSQu Wenruo return -EUCLEAN; 193557ea5ddSQu Wenruo } 194557ea5ddSQu Wenruo return 0; 195557ea5ddSQu Wenruo } 196557ea5ddSQu Wenruo 197557ea5ddSQu Wenruo /* Regular or preallocated extent has fixed item size */ 198557ea5ddSQu Wenruo if (item_size != sizeof(*fi)) { 1991fd715ffSDavid Sterba file_extent_err(leaf, slot, 200709a95c3SArnd Bergmann "invalid item size for reg/prealloc file extent, have %u expect %zu", 2018806d718SQu Wenruo item_size, sizeof(*fi)); 202557ea5ddSQu Wenruo return -EUCLEAN; 203557ea5ddSQu Wenruo } 204033774dcSDavid Sterba if (CHECK_FE_ALIGNED(leaf, slot, fi, ram_bytes, sectorsize) || 205033774dcSDavid Sterba CHECK_FE_ALIGNED(leaf, slot, fi, disk_bytenr, sectorsize) || 206033774dcSDavid Sterba CHECK_FE_ALIGNED(leaf, slot, fi, disk_num_bytes, sectorsize) || 207033774dcSDavid Sterba CHECK_FE_ALIGNED(leaf, slot, fi, offset, sectorsize) || 208033774dcSDavid Sterba CHECK_FE_ALIGNED(leaf, slot, fi, num_bytes, sectorsize)) 209557ea5ddSQu Wenruo return -EUCLEAN; 2104e9845efSFilipe Manana 2114c094c33SQu Wenruo /* Catch extent end overflow */ 2124c094c33SQu Wenruo if (check_add_overflow(btrfs_file_extent_num_bytes(leaf, fi), 2134c094c33SQu Wenruo key->offset, &extent_end)) { 2144c094c33SQu Wenruo file_extent_err(leaf, slot, 2154c094c33SQu Wenruo "extent end overflow, have file offset %llu extent num bytes %llu", 2164c094c33SQu Wenruo key->offset, 2174c094c33SQu Wenruo btrfs_file_extent_num_bytes(leaf, fi)); 2184c094c33SQu Wenruo return -EUCLEAN; 2194c094c33SQu Wenruo } 2204c094c33SQu Wenruo 2214e9845efSFilipe Manana /* 2224e9845efSFilipe Manana * Check that no two consecutive file extent items, in the same leaf, 2234e9845efSFilipe Manana * present ranges that overlap each other. 2244e9845efSFilipe Manana */ 2254e9845efSFilipe Manana if (slot > 0 && 2264e9845efSFilipe Manana prev_key->objectid == key->objectid && 2274e9845efSFilipe Manana prev_key->type == BTRFS_EXTENT_DATA_KEY) { 2284e9845efSFilipe Manana struct btrfs_file_extent_item *prev_fi; 2294e9845efSFilipe Manana u64 prev_end; 2304e9845efSFilipe Manana 2314e9845efSFilipe Manana prev_fi = btrfs_item_ptr(leaf, slot - 1, 2324e9845efSFilipe Manana struct btrfs_file_extent_item); 2334e9845efSFilipe Manana prev_end = file_extent_end(leaf, prev_key, prev_fi); 2344e9845efSFilipe Manana if (prev_end > key->offset) { 2354e9845efSFilipe Manana file_extent_err(leaf, slot - 1, 2364e9845efSFilipe Manana "file extent end range (%llu) goes beyond start offset (%llu) of the next file extent", 2374e9845efSFilipe Manana prev_end, key->offset); 2384e9845efSFilipe Manana return -EUCLEAN; 2394e9845efSFilipe Manana } 2404e9845efSFilipe Manana } 2414e9845efSFilipe Manana 242557ea5ddSQu Wenruo return 0; 243557ea5ddSQu Wenruo } 244557ea5ddSQu Wenruo 24568128ce7SDavid Sterba static int check_csum_item(struct extent_buffer *leaf, struct btrfs_key *key, 2462f659546SQu Wenruo int slot) 247557ea5ddSQu Wenruo { 24868128ce7SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 2492f659546SQu Wenruo u32 sectorsize = fs_info->sectorsize; 2502f659546SQu Wenruo u32 csumsize = btrfs_super_csum_size(fs_info->super_copy); 251557ea5ddSQu Wenruo 252557ea5ddSQu Wenruo if (key->objectid != BTRFS_EXTENT_CSUM_OBJECTID) { 25386a6be3aSDavid Sterba generic_err(leaf, slot, 254d508c5f0SQu Wenruo "invalid key objectid for csum item, have %llu expect %llu", 255d508c5f0SQu Wenruo key->objectid, BTRFS_EXTENT_CSUM_OBJECTID); 256557ea5ddSQu Wenruo return -EUCLEAN; 257557ea5ddSQu Wenruo } 258557ea5ddSQu Wenruo if (!IS_ALIGNED(key->offset, sectorsize)) { 25986a6be3aSDavid Sterba generic_err(leaf, slot, 260d508c5f0SQu Wenruo "unaligned key offset for csum item, have %llu should be aligned to %u", 261d508c5f0SQu Wenruo key->offset, sectorsize); 262557ea5ddSQu Wenruo return -EUCLEAN; 263557ea5ddSQu Wenruo } 264557ea5ddSQu Wenruo if (!IS_ALIGNED(btrfs_item_size_nr(leaf, slot), csumsize)) { 26586a6be3aSDavid Sterba generic_err(leaf, slot, 266d508c5f0SQu Wenruo "unaligned item size for csum item, have %u should be aligned to %u", 267d508c5f0SQu Wenruo btrfs_item_size_nr(leaf, slot), csumsize); 268557ea5ddSQu Wenruo return -EUCLEAN; 269557ea5ddSQu Wenruo } 270557ea5ddSQu Wenruo return 0; 271557ea5ddSQu Wenruo } 272557ea5ddSQu Wenruo 273557ea5ddSQu Wenruo /* 274ad7b0368SQu Wenruo * Customized reported for dir_item, only important new info is key->objectid, 275ad7b0368SQu Wenruo * which represents inode number 276ad7b0368SQu Wenruo */ 277d98ced68SDavid Sterba __printf(3, 4) 278e67c718bSDavid Sterba __cold 279d98ced68SDavid Sterba static void dir_item_err(const struct extent_buffer *eb, int slot, 280ad7b0368SQu Wenruo const char *fmt, ...) 281ad7b0368SQu Wenruo { 282d98ced68SDavid Sterba const struct btrfs_fs_info *fs_info = eb->fs_info; 283ad7b0368SQu Wenruo struct btrfs_key key; 284ad7b0368SQu Wenruo struct va_format vaf; 285ad7b0368SQu Wenruo va_list args; 286ad7b0368SQu Wenruo 287ad7b0368SQu Wenruo btrfs_item_key_to_cpu(eb, &key, slot); 288ad7b0368SQu Wenruo va_start(args, fmt); 289ad7b0368SQu Wenruo 290ad7b0368SQu Wenruo vaf.fmt = fmt; 291ad7b0368SQu Wenruo vaf.va = &args; 292ad7b0368SQu Wenruo 2932f659546SQu Wenruo btrfs_crit(fs_info, 294ad7b0368SQu Wenruo "corrupt %s: root=%llu block=%llu slot=%d ino=%llu, %pV", 2952f659546SQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 2962f659546SQu Wenruo btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, 2972f659546SQu Wenruo key.objectid, &vaf); 298ad7b0368SQu Wenruo va_end(args); 299ad7b0368SQu Wenruo } 300ad7b0368SQu Wenruo 301ce4252c0SDavid Sterba static int check_dir_item(struct extent_buffer *leaf, 302ad7b0368SQu Wenruo struct btrfs_key *key, int slot) 303ad7b0368SQu Wenruo { 304ce4252c0SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 305ad7b0368SQu Wenruo struct btrfs_dir_item *di; 306ad7b0368SQu Wenruo u32 item_size = btrfs_item_size_nr(leaf, slot); 307ad7b0368SQu Wenruo u32 cur = 0; 308ad7b0368SQu Wenruo 309ad7b0368SQu Wenruo di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); 310ad7b0368SQu Wenruo while (cur < item_size) { 311ad7b0368SQu Wenruo u32 name_len; 312ad7b0368SQu Wenruo u32 data_len; 313ad7b0368SQu Wenruo u32 max_name_len; 314ad7b0368SQu Wenruo u32 total_size; 315ad7b0368SQu Wenruo u32 name_hash; 316ad7b0368SQu Wenruo u8 dir_type; 317ad7b0368SQu Wenruo 318ad7b0368SQu Wenruo /* header itself should not cross item boundary */ 319ad7b0368SQu Wenruo if (cur + sizeof(*di) > item_size) { 320d98ced68SDavid Sterba dir_item_err(leaf, slot, 3217cfad652SArnd Bergmann "dir item header crosses item boundary, have %zu boundary %u", 322ad7b0368SQu Wenruo cur + sizeof(*di), item_size); 323ad7b0368SQu Wenruo return -EUCLEAN; 324ad7b0368SQu Wenruo } 325ad7b0368SQu Wenruo 326ad7b0368SQu Wenruo /* dir type check */ 327ad7b0368SQu Wenruo dir_type = btrfs_dir_type(leaf, di); 328ad7b0368SQu Wenruo if (dir_type >= BTRFS_FT_MAX) { 329d98ced68SDavid Sterba dir_item_err(leaf, slot, 330ad7b0368SQu Wenruo "invalid dir item type, have %u expect [0, %u)", 331ad7b0368SQu Wenruo dir_type, BTRFS_FT_MAX); 332ad7b0368SQu Wenruo return -EUCLEAN; 333ad7b0368SQu Wenruo } 334ad7b0368SQu Wenruo 335ad7b0368SQu Wenruo if (key->type == BTRFS_XATTR_ITEM_KEY && 336ad7b0368SQu Wenruo dir_type != BTRFS_FT_XATTR) { 337d98ced68SDavid Sterba dir_item_err(leaf, slot, 338ad7b0368SQu Wenruo "invalid dir item type for XATTR key, have %u expect %u", 339ad7b0368SQu Wenruo dir_type, BTRFS_FT_XATTR); 340ad7b0368SQu Wenruo return -EUCLEAN; 341ad7b0368SQu Wenruo } 342ad7b0368SQu Wenruo if (dir_type == BTRFS_FT_XATTR && 343ad7b0368SQu Wenruo key->type != BTRFS_XATTR_ITEM_KEY) { 344d98ced68SDavid Sterba dir_item_err(leaf, slot, 345ad7b0368SQu Wenruo "xattr dir type found for non-XATTR key"); 346ad7b0368SQu Wenruo return -EUCLEAN; 347ad7b0368SQu Wenruo } 348ad7b0368SQu Wenruo if (dir_type == BTRFS_FT_XATTR) 349ad7b0368SQu Wenruo max_name_len = XATTR_NAME_MAX; 350ad7b0368SQu Wenruo else 351ad7b0368SQu Wenruo max_name_len = BTRFS_NAME_LEN; 352ad7b0368SQu Wenruo 353ad7b0368SQu Wenruo /* Name/data length check */ 354ad7b0368SQu Wenruo name_len = btrfs_dir_name_len(leaf, di); 355ad7b0368SQu Wenruo data_len = btrfs_dir_data_len(leaf, di); 356ad7b0368SQu Wenruo if (name_len > max_name_len) { 357d98ced68SDavid Sterba dir_item_err(leaf, slot, 358ad7b0368SQu Wenruo "dir item name len too long, have %u max %u", 359ad7b0368SQu Wenruo name_len, max_name_len); 360ad7b0368SQu Wenruo return -EUCLEAN; 361ad7b0368SQu Wenruo } 3622f659546SQu Wenruo if (name_len + data_len > BTRFS_MAX_XATTR_SIZE(fs_info)) { 363d98ced68SDavid Sterba dir_item_err(leaf, slot, 364ad7b0368SQu Wenruo "dir item name and data len too long, have %u max %u", 365ad7b0368SQu Wenruo name_len + data_len, 3662f659546SQu Wenruo BTRFS_MAX_XATTR_SIZE(fs_info)); 367ad7b0368SQu Wenruo return -EUCLEAN; 368ad7b0368SQu Wenruo } 369ad7b0368SQu Wenruo 370ad7b0368SQu Wenruo if (data_len && dir_type != BTRFS_FT_XATTR) { 371d98ced68SDavid Sterba dir_item_err(leaf, slot, 372ad7b0368SQu Wenruo "dir item with invalid data len, have %u expect 0", 373ad7b0368SQu Wenruo data_len); 374ad7b0368SQu Wenruo return -EUCLEAN; 375ad7b0368SQu Wenruo } 376ad7b0368SQu Wenruo 377ad7b0368SQu Wenruo total_size = sizeof(*di) + name_len + data_len; 378ad7b0368SQu Wenruo 379ad7b0368SQu Wenruo /* header and name/data should not cross item boundary */ 380ad7b0368SQu Wenruo if (cur + total_size > item_size) { 381d98ced68SDavid Sterba dir_item_err(leaf, slot, 382ad7b0368SQu Wenruo "dir item data crosses item boundary, have %u boundary %u", 383ad7b0368SQu Wenruo cur + total_size, item_size); 384ad7b0368SQu Wenruo return -EUCLEAN; 385ad7b0368SQu Wenruo } 386ad7b0368SQu Wenruo 387ad7b0368SQu Wenruo /* 388ad7b0368SQu Wenruo * Special check for XATTR/DIR_ITEM, as key->offset is name 389ad7b0368SQu Wenruo * hash, should match its name 390ad7b0368SQu Wenruo */ 391ad7b0368SQu Wenruo if (key->type == BTRFS_DIR_ITEM_KEY || 392ad7b0368SQu Wenruo key->type == BTRFS_XATTR_ITEM_KEY) { 393e2683fc9SDavid Sterba char namebuf[max(BTRFS_NAME_LEN, XATTR_NAME_MAX)]; 394e2683fc9SDavid Sterba 395ad7b0368SQu Wenruo read_extent_buffer(leaf, namebuf, 396ad7b0368SQu Wenruo (unsigned long)(di + 1), name_len); 397ad7b0368SQu Wenruo name_hash = btrfs_name_hash(namebuf, name_len); 398ad7b0368SQu Wenruo if (key->offset != name_hash) { 399d98ced68SDavid Sterba dir_item_err(leaf, slot, 400ad7b0368SQu Wenruo "name hash mismatch with key, have 0x%016x expect 0x%016llx", 401ad7b0368SQu Wenruo name_hash, key->offset); 402ad7b0368SQu Wenruo return -EUCLEAN; 403ad7b0368SQu Wenruo } 404ad7b0368SQu Wenruo } 405ad7b0368SQu Wenruo cur += total_size; 406ad7b0368SQu Wenruo di = (struct btrfs_dir_item *)((void *)di + total_size); 407ad7b0368SQu Wenruo } 408ad7b0368SQu Wenruo return 0; 409ad7b0368SQu Wenruo } 410ad7b0368SQu Wenruo 4114806bd88SDavid Sterba __printf(3, 4) 412fce466eaSQu Wenruo __cold 4134806bd88SDavid Sterba static void block_group_err(const struct extent_buffer *eb, int slot, 414fce466eaSQu Wenruo const char *fmt, ...) 415fce466eaSQu Wenruo { 4164806bd88SDavid Sterba const struct btrfs_fs_info *fs_info = eb->fs_info; 417fce466eaSQu Wenruo struct btrfs_key key; 418fce466eaSQu Wenruo struct va_format vaf; 419fce466eaSQu Wenruo va_list args; 420fce466eaSQu Wenruo 421fce466eaSQu Wenruo btrfs_item_key_to_cpu(eb, &key, slot); 422fce466eaSQu Wenruo va_start(args, fmt); 423fce466eaSQu Wenruo 424fce466eaSQu Wenruo vaf.fmt = fmt; 425fce466eaSQu Wenruo vaf.va = &args; 426fce466eaSQu Wenruo 427fce466eaSQu Wenruo btrfs_crit(fs_info, 428fce466eaSQu Wenruo "corrupt %s: root=%llu block=%llu slot=%d bg_start=%llu bg_len=%llu, %pV", 429fce466eaSQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 430fce466eaSQu Wenruo btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, 431fce466eaSQu Wenruo key.objectid, key.offset, &vaf); 432fce466eaSQu Wenruo va_end(args); 433fce466eaSQu Wenruo } 434fce466eaSQu Wenruo 435af60ce2bSDavid Sterba static int check_block_group_item(struct extent_buffer *leaf, 436fce466eaSQu Wenruo struct btrfs_key *key, int slot) 437fce466eaSQu Wenruo { 438fce466eaSQu Wenruo struct btrfs_block_group_item bgi; 439fce466eaSQu Wenruo u32 item_size = btrfs_item_size_nr(leaf, slot); 440fce466eaSQu Wenruo u64 flags; 441fce466eaSQu Wenruo u64 type; 442fce466eaSQu Wenruo 443fce466eaSQu Wenruo /* 444fce466eaSQu Wenruo * Here we don't really care about alignment since extent allocator can 44510950929SQu Wenruo * handle it. We care more about the size. 446fce466eaSQu Wenruo */ 44710950929SQu Wenruo if (key->offset == 0) { 4484806bd88SDavid Sterba block_group_err(leaf, slot, 44910950929SQu Wenruo "invalid block group size 0"); 450fce466eaSQu Wenruo return -EUCLEAN; 451fce466eaSQu Wenruo } 452fce466eaSQu Wenruo 453fce466eaSQu Wenruo if (item_size != sizeof(bgi)) { 4544806bd88SDavid Sterba block_group_err(leaf, slot, 455fce466eaSQu Wenruo "invalid item size, have %u expect %zu", 456fce466eaSQu Wenruo item_size, sizeof(bgi)); 457fce466eaSQu Wenruo return -EUCLEAN; 458fce466eaSQu Wenruo } 459fce466eaSQu Wenruo 460fce466eaSQu Wenruo read_extent_buffer(leaf, &bgi, btrfs_item_ptr_offset(leaf, slot), 461fce466eaSQu Wenruo sizeof(bgi)); 462fce466eaSQu Wenruo if (btrfs_block_group_chunk_objectid(&bgi) != 463fce466eaSQu Wenruo BTRFS_FIRST_CHUNK_TREE_OBJECTID) { 4644806bd88SDavid Sterba block_group_err(leaf, slot, 465fce466eaSQu Wenruo "invalid block group chunk objectid, have %llu expect %llu", 466fce466eaSQu Wenruo btrfs_block_group_chunk_objectid(&bgi), 467fce466eaSQu Wenruo BTRFS_FIRST_CHUNK_TREE_OBJECTID); 468fce466eaSQu Wenruo return -EUCLEAN; 469fce466eaSQu Wenruo } 470fce466eaSQu Wenruo 471fce466eaSQu Wenruo if (btrfs_block_group_used(&bgi) > key->offset) { 4724806bd88SDavid Sterba block_group_err(leaf, slot, 473fce466eaSQu Wenruo "invalid block group used, have %llu expect [0, %llu)", 474fce466eaSQu Wenruo btrfs_block_group_used(&bgi), key->offset); 475fce466eaSQu Wenruo return -EUCLEAN; 476fce466eaSQu Wenruo } 477fce466eaSQu Wenruo 478fce466eaSQu Wenruo flags = btrfs_block_group_flags(&bgi); 479fce466eaSQu Wenruo if (hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) > 1) { 4804806bd88SDavid Sterba block_group_err(leaf, slot, 481fce466eaSQu Wenruo "invalid profile flags, have 0x%llx (%lu bits set) expect no more than 1 bit set", 482fce466eaSQu Wenruo flags & BTRFS_BLOCK_GROUP_PROFILE_MASK, 483fce466eaSQu Wenruo hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK)); 484fce466eaSQu Wenruo return -EUCLEAN; 485fce466eaSQu Wenruo } 486fce466eaSQu Wenruo 487fce466eaSQu Wenruo type = flags & BTRFS_BLOCK_GROUP_TYPE_MASK; 488fce466eaSQu Wenruo if (type != BTRFS_BLOCK_GROUP_DATA && 489fce466eaSQu Wenruo type != BTRFS_BLOCK_GROUP_METADATA && 490fce466eaSQu Wenruo type != BTRFS_BLOCK_GROUP_SYSTEM && 491fce466eaSQu Wenruo type != (BTRFS_BLOCK_GROUP_METADATA | 492fce466eaSQu Wenruo BTRFS_BLOCK_GROUP_DATA)) { 4934806bd88SDavid Sterba block_group_err(leaf, slot, 494761333f2SShaokun Zhang "invalid type, have 0x%llx (%lu bits set) expect either 0x%llx, 0x%llx, 0x%llx or 0x%llx", 495fce466eaSQu Wenruo type, hweight64(type), 496fce466eaSQu Wenruo BTRFS_BLOCK_GROUP_DATA, BTRFS_BLOCK_GROUP_METADATA, 497fce466eaSQu Wenruo BTRFS_BLOCK_GROUP_SYSTEM, 498fce466eaSQu Wenruo BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA); 499fce466eaSQu Wenruo return -EUCLEAN; 500fce466eaSQu Wenruo } 501fce466eaSQu Wenruo return 0; 502fce466eaSQu Wenruo } 503fce466eaSQu Wenruo 504d001e4a3SDavid Sterba __printf(4, 5) 505f1140243SQu Wenruo __cold 506d001e4a3SDavid Sterba static void chunk_err(const struct extent_buffer *leaf, 507f1140243SQu Wenruo const struct btrfs_chunk *chunk, u64 logical, 508f1140243SQu Wenruo const char *fmt, ...) 509f1140243SQu Wenruo { 510d001e4a3SDavid Sterba const struct btrfs_fs_info *fs_info = leaf->fs_info; 511f1140243SQu Wenruo bool is_sb; 512f1140243SQu Wenruo struct va_format vaf; 513f1140243SQu Wenruo va_list args; 514f1140243SQu Wenruo int i; 515f1140243SQu Wenruo int slot = -1; 516f1140243SQu Wenruo 517f1140243SQu Wenruo /* Only superblock eb is able to have such small offset */ 518f1140243SQu Wenruo is_sb = (leaf->start == BTRFS_SUPER_INFO_OFFSET); 519f1140243SQu Wenruo 520f1140243SQu Wenruo if (!is_sb) { 521f1140243SQu Wenruo /* 522f1140243SQu Wenruo * Get the slot number by iterating through all slots, this 523f1140243SQu Wenruo * would provide better readability. 524f1140243SQu Wenruo */ 525f1140243SQu Wenruo for (i = 0; i < btrfs_header_nritems(leaf); i++) { 526f1140243SQu Wenruo if (btrfs_item_ptr_offset(leaf, i) == 527f1140243SQu Wenruo (unsigned long)chunk) { 528f1140243SQu Wenruo slot = i; 529f1140243SQu Wenruo break; 530f1140243SQu Wenruo } 531f1140243SQu Wenruo } 532f1140243SQu Wenruo } 533f1140243SQu Wenruo va_start(args, fmt); 534f1140243SQu Wenruo vaf.fmt = fmt; 535f1140243SQu Wenruo vaf.va = &args; 536f1140243SQu Wenruo 537f1140243SQu Wenruo if (is_sb) 538f1140243SQu Wenruo btrfs_crit(fs_info, 539f1140243SQu Wenruo "corrupt superblock syschunk array: chunk_start=%llu, %pV", 540f1140243SQu Wenruo logical, &vaf); 541f1140243SQu Wenruo else 542f1140243SQu Wenruo btrfs_crit(fs_info, 543f1140243SQu Wenruo "corrupt leaf: root=%llu block=%llu slot=%d chunk_start=%llu, %pV", 544f1140243SQu Wenruo BTRFS_CHUNK_TREE_OBJECTID, leaf->start, slot, 545f1140243SQu Wenruo logical, &vaf); 546f1140243SQu Wenruo va_end(args); 547f1140243SQu Wenruo } 548f1140243SQu Wenruo 549ad7b0368SQu Wenruo /* 55082fc28fbSQu Wenruo * The common chunk check which could also work on super block sys chunk array. 55182fc28fbSQu Wenruo * 552bf871c3bSQu Wenruo * Return -EUCLEAN if anything is corrupted. 55382fc28fbSQu Wenruo * Return 0 if everything is OK. 55482fc28fbSQu Wenruo */ 555ddaf1d5aSDavid Sterba int btrfs_check_chunk_valid(struct extent_buffer *leaf, 55682fc28fbSQu Wenruo struct btrfs_chunk *chunk, u64 logical) 55782fc28fbSQu Wenruo { 558ddaf1d5aSDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 55982fc28fbSQu Wenruo u64 length; 56082fc28fbSQu Wenruo u64 stripe_len; 56182fc28fbSQu Wenruo u16 num_stripes; 56282fc28fbSQu Wenruo u16 sub_stripes; 56382fc28fbSQu Wenruo u64 type; 56482fc28fbSQu Wenruo u64 features; 56582fc28fbSQu Wenruo bool mixed = false; 56682fc28fbSQu Wenruo 56782fc28fbSQu Wenruo length = btrfs_chunk_length(leaf, chunk); 56882fc28fbSQu Wenruo stripe_len = btrfs_chunk_stripe_len(leaf, chunk); 56982fc28fbSQu Wenruo num_stripes = btrfs_chunk_num_stripes(leaf, chunk); 57082fc28fbSQu Wenruo sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk); 57182fc28fbSQu Wenruo type = btrfs_chunk_type(leaf, chunk); 57282fc28fbSQu Wenruo 57382fc28fbSQu Wenruo if (!num_stripes) { 574d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 575f1140243SQu Wenruo "invalid chunk num_stripes, have %u", num_stripes); 576bf871c3bSQu Wenruo return -EUCLEAN; 57782fc28fbSQu Wenruo } 57882fc28fbSQu Wenruo if (!IS_ALIGNED(logical, fs_info->sectorsize)) { 579d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 580f1140243SQu Wenruo "invalid chunk logical, have %llu should aligned to %u", 581f1140243SQu Wenruo logical, fs_info->sectorsize); 582bf871c3bSQu Wenruo return -EUCLEAN; 58382fc28fbSQu Wenruo } 58482fc28fbSQu Wenruo if (btrfs_chunk_sector_size(leaf, chunk) != fs_info->sectorsize) { 585d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 586f1140243SQu Wenruo "invalid chunk sectorsize, have %u expect %u", 587f1140243SQu Wenruo btrfs_chunk_sector_size(leaf, chunk), 588f1140243SQu Wenruo fs_info->sectorsize); 589bf871c3bSQu Wenruo return -EUCLEAN; 59082fc28fbSQu Wenruo } 59182fc28fbSQu Wenruo if (!length || !IS_ALIGNED(length, fs_info->sectorsize)) { 592d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 593f1140243SQu Wenruo "invalid chunk length, have %llu", length); 594bf871c3bSQu Wenruo return -EUCLEAN; 59582fc28fbSQu Wenruo } 59682fc28fbSQu Wenruo if (!is_power_of_2(stripe_len) || stripe_len != BTRFS_STRIPE_LEN) { 597d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 598f1140243SQu Wenruo "invalid chunk stripe length: %llu", 59982fc28fbSQu Wenruo stripe_len); 600bf871c3bSQu Wenruo return -EUCLEAN; 60182fc28fbSQu Wenruo } 60282fc28fbSQu Wenruo if (~(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_PROFILE_MASK) & 60382fc28fbSQu Wenruo type) { 604d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 605f1140243SQu Wenruo "unrecognized chunk type: 0x%llx", 60682fc28fbSQu Wenruo ~(BTRFS_BLOCK_GROUP_TYPE_MASK | 60782fc28fbSQu Wenruo BTRFS_BLOCK_GROUP_PROFILE_MASK) & 60882fc28fbSQu Wenruo btrfs_chunk_type(leaf, chunk)); 609bf871c3bSQu Wenruo return -EUCLEAN; 61082fc28fbSQu Wenruo } 61182fc28fbSQu Wenruo 61280e46cf2SQu Wenruo if (!is_power_of_2(type & BTRFS_BLOCK_GROUP_PROFILE_MASK) && 61380e46cf2SQu Wenruo (type & BTRFS_BLOCK_GROUP_PROFILE_MASK) != 0) { 614d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 61580e46cf2SQu Wenruo "invalid chunk profile flag: 0x%llx, expect 0 or 1 bit set", 61680e46cf2SQu Wenruo type & BTRFS_BLOCK_GROUP_PROFILE_MASK); 61780e46cf2SQu Wenruo return -EUCLEAN; 61880e46cf2SQu Wenruo } 61982fc28fbSQu Wenruo if ((type & BTRFS_BLOCK_GROUP_TYPE_MASK) == 0) { 620d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 621f1140243SQu Wenruo "missing chunk type flag, have 0x%llx one bit must be set in 0x%llx", 622f1140243SQu Wenruo type, BTRFS_BLOCK_GROUP_TYPE_MASK); 623bf871c3bSQu Wenruo return -EUCLEAN; 62482fc28fbSQu Wenruo } 62582fc28fbSQu Wenruo 62682fc28fbSQu Wenruo if ((type & BTRFS_BLOCK_GROUP_SYSTEM) && 62782fc28fbSQu Wenruo (type & (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA))) { 628d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 629f1140243SQu Wenruo "system chunk with data or metadata type: 0x%llx", 630f1140243SQu Wenruo type); 631bf871c3bSQu Wenruo return -EUCLEAN; 63282fc28fbSQu Wenruo } 63382fc28fbSQu Wenruo 63482fc28fbSQu Wenruo features = btrfs_super_incompat_flags(fs_info->super_copy); 63582fc28fbSQu Wenruo if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) 63682fc28fbSQu Wenruo mixed = true; 63782fc28fbSQu Wenruo 63882fc28fbSQu Wenruo if (!mixed) { 63982fc28fbSQu Wenruo if ((type & BTRFS_BLOCK_GROUP_METADATA) && 64082fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_DATA)) { 641d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 64282fc28fbSQu Wenruo "mixed chunk type in non-mixed mode: 0x%llx", type); 643bf871c3bSQu Wenruo return -EUCLEAN; 64482fc28fbSQu Wenruo } 64582fc28fbSQu Wenruo } 64682fc28fbSQu Wenruo 64782fc28fbSQu Wenruo if ((type & BTRFS_BLOCK_GROUP_RAID10 && sub_stripes != 2) || 64882fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_RAID1 && num_stripes != 2) || 64982fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_RAID5 && num_stripes < 2) || 65082fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_RAID6 && num_stripes < 3) || 65182fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_DUP && num_stripes != 2) || 65282fc28fbSQu Wenruo ((type & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0 && num_stripes != 1)) { 653d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 65482fc28fbSQu Wenruo "invalid num_stripes:sub_stripes %u:%u for profile %llu", 65582fc28fbSQu Wenruo num_stripes, sub_stripes, 65682fc28fbSQu Wenruo type & BTRFS_BLOCK_GROUP_PROFILE_MASK); 657bf871c3bSQu Wenruo return -EUCLEAN; 65882fc28fbSQu Wenruo } 65982fc28fbSQu Wenruo 66082fc28fbSQu Wenruo return 0; 66182fc28fbSQu Wenruo } 66282fc28fbSQu Wenruo 6635617ed80SDavid Sterba __printf(3, 4) 664ab4ba2e1SQu Wenruo __cold 6655617ed80SDavid Sterba static void dev_item_err(const struct extent_buffer *eb, int slot, 666ab4ba2e1SQu Wenruo const char *fmt, ...) 667ab4ba2e1SQu Wenruo { 668ab4ba2e1SQu Wenruo struct btrfs_key key; 669ab4ba2e1SQu Wenruo struct va_format vaf; 670ab4ba2e1SQu Wenruo va_list args; 671ab4ba2e1SQu Wenruo 672ab4ba2e1SQu Wenruo btrfs_item_key_to_cpu(eb, &key, slot); 673ab4ba2e1SQu Wenruo va_start(args, fmt); 674ab4ba2e1SQu Wenruo 675ab4ba2e1SQu Wenruo vaf.fmt = fmt; 676ab4ba2e1SQu Wenruo vaf.va = &args; 677ab4ba2e1SQu Wenruo 6785617ed80SDavid Sterba btrfs_crit(eb->fs_info, 679ab4ba2e1SQu Wenruo "corrupt %s: root=%llu block=%llu slot=%d devid=%llu %pV", 680ab4ba2e1SQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 681ab4ba2e1SQu Wenruo btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, 682ab4ba2e1SQu Wenruo key.objectid, &vaf); 683ab4ba2e1SQu Wenruo va_end(args); 684ab4ba2e1SQu Wenruo } 685ab4ba2e1SQu Wenruo 686412a2312SDavid Sterba static int check_dev_item(struct extent_buffer *leaf, 687ab4ba2e1SQu Wenruo struct btrfs_key *key, int slot) 688ab4ba2e1SQu Wenruo { 689412a2312SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 690ab4ba2e1SQu Wenruo struct btrfs_dev_item *ditem; 691ab4ba2e1SQu Wenruo u64 max_devid = max(BTRFS_MAX_DEVS(fs_info), BTRFS_MAX_DEVS_SYS_CHUNK); 692ab4ba2e1SQu Wenruo 693ab4ba2e1SQu Wenruo if (key->objectid != BTRFS_DEV_ITEMS_OBJECTID) { 6945617ed80SDavid Sterba dev_item_err(leaf, slot, 695ab4ba2e1SQu Wenruo "invalid objectid: has=%llu expect=%llu", 696ab4ba2e1SQu Wenruo key->objectid, BTRFS_DEV_ITEMS_OBJECTID); 697ab4ba2e1SQu Wenruo return -EUCLEAN; 698ab4ba2e1SQu Wenruo } 699ab4ba2e1SQu Wenruo if (key->offset > max_devid) { 7005617ed80SDavid Sterba dev_item_err(leaf, slot, 701ab4ba2e1SQu Wenruo "invalid devid: has=%llu expect=[0, %llu]", 702ab4ba2e1SQu Wenruo key->offset, max_devid); 703ab4ba2e1SQu Wenruo return -EUCLEAN; 704ab4ba2e1SQu Wenruo } 705ab4ba2e1SQu Wenruo ditem = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item); 706ab4ba2e1SQu Wenruo if (btrfs_device_id(leaf, ditem) != key->offset) { 7075617ed80SDavid Sterba dev_item_err(leaf, slot, 708ab4ba2e1SQu Wenruo "devid mismatch: key has=%llu item has=%llu", 709ab4ba2e1SQu Wenruo key->offset, btrfs_device_id(leaf, ditem)); 710ab4ba2e1SQu Wenruo return -EUCLEAN; 711ab4ba2e1SQu Wenruo } 712ab4ba2e1SQu Wenruo 713ab4ba2e1SQu Wenruo /* 714ab4ba2e1SQu Wenruo * For device total_bytes, we don't have reliable way to check it, as 715ab4ba2e1SQu Wenruo * it can be 0 for device removal. Device size check can only be done 716ab4ba2e1SQu Wenruo * by dev extents check. 717ab4ba2e1SQu Wenruo */ 718ab4ba2e1SQu Wenruo if (btrfs_device_bytes_used(leaf, ditem) > 719ab4ba2e1SQu Wenruo btrfs_device_total_bytes(leaf, ditem)) { 7205617ed80SDavid Sterba dev_item_err(leaf, slot, 721ab4ba2e1SQu Wenruo "invalid bytes used: have %llu expect [0, %llu]", 722ab4ba2e1SQu Wenruo btrfs_device_bytes_used(leaf, ditem), 723ab4ba2e1SQu Wenruo btrfs_device_total_bytes(leaf, ditem)); 724ab4ba2e1SQu Wenruo return -EUCLEAN; 725ab4ba2e1SQu Wenruo } 726ab4ba2e1SQu Wenruo /* 727ab4ba2e1SQu Wenruo * Remaining members like io_align/type/gen/dev_group aren't really 728ab4ba2e1SQu Wenruo * utilized. Skip them to make later usage of them easier. 729ab4ba2e1SQu Wenruo */ 730ab4ba2e1SQu Wenruo return 0; 731ab4ba2e1SQu Wenruo } 732ab4ba2e1SQu Wenruo 733496245caSQu Wenruo /* Inode item error output has the same format as dir_item_err() */ 734496245caSQu Wenruo #define inode_item_err(fs_info, eb, slot, fmt, ...) \ 735d98ced68SDavid Sterba dir_item_err(eb, slot, fmt, __VA_ARGS__) 736496245caSQu Wenruo 73739e57f49SDavid Sterba static int check_inode_item(struct extent_buffer *leaf, 738496245caSQu Wenruo struct btrfs_key *key, int slot) 739496245caSQu Wenruo { 74039e57f49SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 741496245caSQu Wenruo struct btrfs_inode_item *iitem; 742496245caSQu Wenruo u64 super_gen = btrfs_super_generation(fs_info->super_copy); 743496245caSQu Wenruo u32 valid_mask = (S_IFMT | S_ISUID | S_ISGID | S_ISVTX | 0777); 744496245caSQu Wenruo u32 mode; 745496245caSQu Wenruo 746496245caSQu Wenruo if ((key->objectid < BTRFS_FIRST_FREE_OBJECTID || 747496245caSQu Wenruo key->objectid > BTRFS_LAST_FREE_OBJECTID) && 748496245caSQu Wenruo key->objectid != BTRFS_ROOT_TREE_DIR_OBJECTID && 749496245caSQu Wenruo key->objectid != BTRFS_FREE_INO_OBJECTID) { 75086a6be3aSDavid Sterba generic_err(leaf, slot, 751496245caSQu Wenruo "invalid key objectid: has %llu expect %llu or [%llu, %llu] or %llu", 752496245caSQu Wenruo key->objectid, BTRFS_ROOT_TREE_DIR_OBJECTID, 753496245caSQu Wenruo BTRFS_FIRST_FREE_OBJECTID, 754496245caSQu Wenruo BTRFS_LAST_FREE_OBJECTID, 755496245caSQu Wenruo BTRFS_FREE_INO_OBJECTID); 756496245caSQu Wenruo return -EUCLEAN; 757496245caSQu Wenruo } 758496245caSQu Wenruo if (key->offset != 0) { 759496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 760496245caSQu Wenruo "invalid key offset: has %llu expect 0", 761496245caSQu Wenruo key->offset); 762496245caSQu Wenruo return -EUCLEAN; 763496245caSQu Wenruo } 764496245caSQu Wenruo iitem = btrfs_item_ptr(leaf, slot, struct btrfs_inode_item); 765496245caSQu Wenruo 766496245caSQu Wenruo /* Here we use super block generation + 1 to handle log tree */ 767496245caSQu Wenruo if (btrfs_inode_generation(leaf, iitem) > super_gen + 1) { 768496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 769496245caSQu Wenruo "invalid inode generation: has %llu expect (0, %llu]", 770496245caSQu Wenruo btrfs_inode_generation(leaf, iitem), 771496245caSQu Wenruo super_gen + 1); 772496245caSQu Wenruo return -EUCLEAN; 773496245caSQu Wenruo } 774496245caSQu Wenruo /* Note for ROOT_TREE_DIR_ITEM, mkfs could set its transid 0 */ 775496245caSQu Wenruo if (btrfs_inode_transid(leaf, iitem) > super_gen + 1) { 776496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 777496245caSQu Wenruo "invalid inode generation: has %llu expect [0, %llu]", 778496245caSQu Wenruo btrfs_inode_transid(leaf, iitem), super_gen + 1); 779496245caSQu Wenruo return -EUCLEAN; 780496245caSQu Wenruo } 781496245caSQu Wenruo 782496245caSQu Wenruo /* 783496245caSQu Wenruo * For size and nbytes it's better not to be too strict, as for dir 784496245caSQu Wenruo * item its size/nbytes can easily get wrong, but doesn't affect 785496245caSQu Wenruo * anything in the fs. So here we skip the check. 786496245caSQu Wenruo */ 787496245caSQu Wenruo mode = btrfs_inode_mode(leaf, iitem); 788496245caSQu Wenruo if (mode & ~valid_mask) { 789496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 790496245caSQu Wenruo "unknown mode bit detected: 0x%x", 791496245caSQu Wenruo mode & ~valid_mask); 792496245caSQu Wenruo return -EUCLEAN; 793496245caSQu Wenruo } 794496245caSQu Wenruo 795496245caSQu Wenruo /* 796496245caSQu Wenruo * S_IFMT is not bit mapped so we can't completely rely on is_power_of_2, 797496245caSQu Wenruo * but is_power_of_2() can save us from checking FIFO/CHR/DIR/REG. 798496245caSQu Wenruo * Only needs to check BLK, LNK and SOCKS 799496245caSQu Wenruo */ 800496245caSQu Wenruo if (!is_power_of_2(mode & S_IFMT)) { 801496245caSQu Wenruo if (!S_ISLNK(mode) && !S_ISBLK(mode) && !S_ISSOCK(mode)) { 802496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 803496245caSQu Wenruo "invalid mode: has 0%o expect valid S_IF* bit(s)", 804496245caSQu Wenruo mode & S_IFMT); 805496245caSQu Wenruo return -EUCLEAN; 806496245caSQu Wenruo } 807496245caSQu Wenruo } 808496245caSQu Wenruo if (S_ISDIR(mode) && btrfs_inode_nlink(leaf, iitem) > 1) { 809496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 810496245caSQu Wenruo "invalid nlink: has %u expect no more than 1 for dir", 811496245caSQu Wenruo btrfs_inode_nlink(leaf, iitem)); 812496245caSQu Wenruo return -EUCLEAN; 813496245caSQu Wenruo } 814496245caSQu Wenruo if (btrfs_inode_flags(leaf, iitem) & ~BTRFS_INODE_FLAG_MASK) { 815496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 816496245caSQu Wenruo "unknown flags detected: 0x%llx", 817496245caSQu Wenruo btrfs_inode_flags(leaf, iitem) & 818496245caSQu Wenruo ~BTRFS_INODE_FLAG_MASK); 819496245caSQu Wenruo return -EUCLEAN; 820496245caSQu Wenruo } 821496245caSQu Wenruo return 0; 822496245caSQu Wenruo } 823496245caSQu Wenruo 824259ee775SQu Wenruo static int check_root_item(struct extent_buffer *leaf, struct btrfs_key *key, 825259ee775SQu Wenruo int slot) 826259ee775SQu Wenruo { 827259ee775SQu Wenruo struct btrfs_fs_info *fs_info = leaf->fs_info; 828259ee775SQu Wenruo struct btrfs_root_item ri; 829259ee775SQu Wenruo const u64 valid_root_flags = BTRFS_ROOT_SUBVOL_RDONLY | 830259ee775SQu Wenruo BTRFS_ROOT_SUBVOL_DEAD; 831259ee775SQu Wenruo 832259ee775SQu Wenruo /* No such tree id */ 833259ee775SQu Wenruo if (key->objectid == 0) { 834259ee775SQu Wenruo generic_err(leaf, slot, "invalid root id 0"); 835259ee775SQu Wenruo return -EUCLEAN; 836259ee775SQu Wenruo } 837259ee775SQu Wenruo 838259ee775SQu Wenruo /* 839259ee775SQu Wenruo * Some older kernel may create ROOT_ITEM with non-zero offset, so here 840259ee775SQu Wenruo * we only check offset for reloc tree whose key->offset must be a 841259ee775SQu Wenruo * valid tree. 842259ee775SQu Wenruo */ 843259ee775SQu Wenruo if (key->objectid == BTRFS_TREE_RELOC_OBJECTID && key->offset == 0) { 844259ee775SQu Wenruo generic_err(leaf, slot, "invalid root id 0 for reloc tree"); 845259ee775SQu Wenruo return -EUCLEAN; 846259ee775SQu Wenruo } 847259ee775SQu Wenruo 848259ee775SQu Wenruo if (btrfs_item_size_nr(leaf, slot) != sizeof(ri)) { 849259ee775SQu Wenruo generic_err(leaf, slot, 850259ee775SQu Wenruo "invalid root item size, have %u expect %zu", 851259ee775SQu Wenruo btrfs_item_size_nr(leaf, slot), sizeof(ri)); 852259ee775SQu Wenruo } 853259ee775SQu Wenruo 854259ee775SQu Wenruo read_extent_buffer(leaf, &ri, btrfs_item_ptr_offset(leaf, slot), 855259ee775SQu Wenruo sizeof(ri)); 856259ee775SQu Wenruo 857259ee775SQu Wenruo /* Generation related */ 858259ee775SQu Wenruo if (btrfs_root_generation(&ri) > 859259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1) { 860259ee775SQu Wenruo generic_err(leaf, slot, 861259ee775SQu Wenruo "invalid root generation, have %llu expect (0, %llu]", 862259ee775SQu Wenruo btrfs_root_generation(&ri), 863259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1); 864259ee775SQu Wenruo return -EUCLEAN; 865259ee775SQu Wenruo } 866259ee775SQu Wenruo if (btrfs_root_generation_v2(&ri) > 867259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1) { 868259ee775SQu Wenruo generic_err(leaf, slot, 869259ee775SQu Wenruo "invalid root v2 generation, have %llu expect (0, %llu]", 870259ee775SQu Wenruo btrfs_root_generation_v2(&ri), 871259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1); 872259ee775SQu Wenruo return -EUCLEAN; 873259ee775SQu Wenruo } 874259ee775SQu Wenruo if (btrfs_root_last_snapshot(&ri) > 875259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1) { 876259ee775SQu Wenruo generic_err(leaf, slot, 877259ee775SQu Wenruo "invalid root last_snapshot, have %llu expect (0, %llu]", 878259ee775SQu Wenruo btrfs_root_last_snapshot(&ri), 879259ee775SQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1); 880259ee775SQu Wenruo return -EUCLEAN; 881259ee775SQu Wenruo } 882259ee775SQu Wenruo 883259ee775SQu Wenruo /* Alignment and level check */ 884259ee775SQu Wenruo if (!IS_ALIGNED(btrfs_root_bytenr(&ri), fs_info->sectorsize)) { 885259ee775SQu Wenruo generic_err(leaf, slot, 886259ee775SQu Wenruo "invalid root bytenr, have %llu expect to be aligned to %u", 887259ee775SQu Wenruo btrfs_root_bytenr(&ri), fs_info->sectorsize); 888259ee775SQu Wenruo return -EUCLEAN; 889259ee775SQu Wenruo } 890259ee775SQu Wenruo if (btrfs_root_level(&ri) >= BTRFS_MAX_LEVEL) { 891259ee775SQu Wenruo generic_err(leaf, slot, 892259ee775SQu Wenruo "invalid root level, have %u expect [0, %u]", 893259ee775SQu Wenruo btrfs_root_level(&ri), BTRFS_MAX_LEVEL - 1); 894259ee775SQu Wenruo return -EUCLEAN; 895259ee775SQu Wenruo } 896259ee775SQu Wenruo if (ri.drop_level >= BTRFS_MAX_LEVEL) { 897259ee775SQu Wenruo generic_err(leaf, slot, 898259ee775SQu Wenruo "invalid root level, have %u expect [0, %u]", 899259ee775SQu Wenruo ri.drop_level, BTRFS_MAX_LEVEL - 1); 900259ee775SQu Wenruo return -EUCLEAN; 901259ee775SQu Wenruo } 902259ee775SQu Wenruo 903259ee775SQu Wenruo /* Flags check */ 904259ee775SQu Wenruo if (btrfs_root_flags(&ri) & ~valid_root_flags) { 905259ee775SQu Wenruo generic_err(leaf, slot, 906259ee775SQu Wenruo "invalid root flags, have 0x%llx expect mask 0x%llx", 907259ee775SQu Wenruo btrfs_root_flags(&ri), valid_root_flags); 908259ee775SQu Wenruo return -EUCLEAN; 909259ee775SQu Wenruo } 910259ee775SQu Wenruo return 0; 911259ee775SQu Wenruo } 912259ee775SQu Wenruo 913f82d1c7cSQu Wenruo __printf(3,4) 914f82d1c7cSQu Wenruo __cold 915f82d1c7cSQu Wenruo static void extent_err(const struct extent_buffer *eb, int slot, 916f82d1c7cSQu Wenruo const char *fmt, ...) 917f82d1c7cSQu Wenruo { 918f82d1c7cSQu Wenruo struct btrfs_key key; 919f82d1c7cSQu Wenruo struct va_format vaf; 920f82d1c7cSQu Wenruo va_list args; 921f82d1c7cSQu Wenruo u64 bytenr; 922f82d1c7cSQu Wenruo u64 len; 923f82d1c7cSQu Wenruo 924f82d1c7cSQu Wenruo btrfs_item_key_to_cpu(eb, &key, slot); 925f82d1c7cSQu Wenruo bytenr = key.objectid; 926e2406a6fSQu Wenruo if (key.type == BTRFS_METADATA_ITEM_KEY || 927e2406a6fSQu Wenruo key.type == BTRFS_TREE_BLOCK_REF_KEY || 928e2406a6fSQu Wenruo key.type == BTRFS_SHARED_BLOCK_REF_KEY) 929f82d1c7cSQu Wenruo len = eb->fs_info->nodesize; 930f82d1c7cSQu Wenruo else 931f82d1c7cSQu Wenruo len = key.offset; 932f82d1c7cSQu Wenruo va_start(args, fmt); 933f82d1c7cSQu Wenruo 934f82d1c7cSQu Wenruo vaf.fmt = fmt; 935f82d1c7cSQu Wenruo vaf.va = &args; 936f82d1c7cSQu Wenruo 937f82d1c7cSQu Wenruo btrfs_crit(eb->fs_info, 938f82d1c7cSQu Wenruo "corrupt %s: block=%llu slot=%d extent bytenr=%llu len=%llu %pV", 939f82d1c7cSQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 940f82d1c7cSQu Wenruo eb->start, slot, bytenr, len, &vaf); 941f82d1c7cSQu Wenruo va_end(args); 942f82d1c7cSQu Wenruo } 943f82d1c7cSQu Wenruo 944f82d1c7cSQu Wenruo static int check_extent_item(struct extent_buffer *leaf, 945f82d1c7cSQu Wenruo struct btrfs_key *key, int slot) 946f82d1c7cSQu Wenruo { 947f82d1c7cSQu Wenruo struct btrfs_fs_info *fs_info = leaf->fs_info; 948f82d1c7cSQu Wenruo struct btrfs_extent_item *ei; 949f82d1c7cSQu Wenruo bool is_tree_block = false; 950f82d1c7cSQu Wenruo unsigned long ptr; /* Current pointer inside inline refs */ 951f82d1c7cSQu Wenruo unsigned long end; /* Extent item end */ 952f82d1c7cSQu Wenruo const u32 item_size = btrfs_item_size_nr(leaf, slot); 953f82d1c7cSQu Wenruo u64 flags; 954f82d1c7cSQu Wenruo u64 generation; 955f82d1c7cSQu Wenruo u64 total_refs; /* Total refs in btrfs_extent_item */ 956f82d1c7cSQu Wenruo u64 inline_refs = 0; /* found total inline refs */ 957f82d1c7cSQu Wenruo 958f82d1c7cSQu Wenruo if (key->type == BTRFS_METADATA_ITEM_KEY && 959f82d1c7cSQu Wenruo !btrfs_fs_incompat(fs_info, SKINNY_METADATA)) { 960f82d1c7cSQu Wenruo generic_err(leaf, slot, 961f82d1c7cSQu Wenruo "invalid key type, METADATA_ITEM type invalid when SKINNY_METADATA feature disabled"); 962f82d1c7cSQu Wenruo return -EUCLEAN; 963f82d1c7cSQu Wenruo } 964f82d1c7cSQu Wenruo /* key->objectid is the bytenr for both key types */ 965f82d1c7cSQu Wenruo if (!IS_ALIGNED(key->objectid, fs_info->sectorsize)) { 966f82d1c7cSQu Wenruo generic_err(leaf, slot, 967f82d1c7cSQu Wenruo "invalid key objectid, have %llu expect to be aligned to %u", 968f82d1c7cSQu Wenruo key->objectid, fs_info->sectorsize); 969f82d1c7cSQu Wenruo return -EUCLEAN; 970f82d1c7cSQu Wenruo } 971f82d1c7cSQu Wenruo 972f82d1c7cSQu Wenruo /* key->offset is tree level for METADATA_ITEM_KEY */ 973f82d1c7cSQu Wenruo if (key->type == BTRFS_METADATA_ITEM_KEY && 974f82d1c7cSQu Wenruo key->offset >= BTRFS_MAX_LEVEL) { 975f82d1c7cSQu Wenruo extent_err(leaf, slot, 976f82d1c7cSQu Wenruo "invalid tree level, have %llu expect [0, %u]", 977f82d1c7cSQu Wenruo key->offset, BTRFS_MAX_LEVEL - 1); 978f82d1c7cSQu Wenruo return -EUCLEAN; 979f82d1c7cSQu Wenruo } 980f82d1c7cSQu Wenruo 981f82d1c7cSQu Wenruo /* 982f82d1c7cSQu Wenruo * EXTENT/METADATA_ITEM consists of: 983f82d1c7cSQu Wenruo * 1) One btrfs_extent_item 984f82d1c7cSQu Wenruo * Records the total refs, type and generation of the extent. 985f82d1c7cSQu Wenruo * 986f82d1c7cSQu Wenruo * 2) One btrfs_tree_block_info (for EXTENT_ITEM and tree backref only) 987f82d1c7cSQu Wenruo * Records the first key and level of the tree block. 988f82d1c7cSQu Wenruo * 989f82d1c7cSQu Wenruo * 2) Zero or more btrfs_extent_inline_ref(s) 990f82d1c7cSQu Wenruo * Each inline ref has one btrfs_extent_inline_ref shows: 991f82d1c7cSQu Wenruo * 2.1) The ref type, one of the 4 992f82d1c7cSQu Wenruo * TREE_BLOCK_REF Tree block only 993f82d1c7cSQu Wenruo * SHARED_BLOCK_REF Tree block only 994f82d1c7cSQu Wenruo * EXTENT_DATA_REF Data only 995f82d1c7cSQu Wenruo * SHARED_DATA_REF Data only 996f82d1c7cSQu Wenruo * 2.2) Ref type specific data 997f82d1c7cSQu Wenruo * Either using btrfs_extent_inline_ref::offset, or specific 998f82d1c7cSQu Wenruo * data structure. 999f82d1c7cSQu Wenruo */ 1000f82d1c7cSQu Wenruo if (item_size < sizeof(*ei)) { 1001f82d1c7cSQu Wenruo extent_err(leaf, slot, 1002f82d1c7cSQu Wenruo "invalid item size, have %u expect [%zu, %u)", 1003f82d1c7cSQu Wenruo item_size, sizeof(*ei), 1004f82d1c7cSQu Wenruo BTRFS_LEAF_DATA_SIZE(fs_info)); 1005f82d1c7cSQu Wenruo return -EUCLEAN; 1006f82d1c7cSQu Wenruo } 1007f82d1c7cSQu Wenruo end = item_size + btrfs_item_ptr_offset(leaf, slot); 1008f82d1c7cSQu Wenruo 1009f82d1c7cSQu Wenruo /* Checks against extent_item */ 1010f82d1c7cSQu Wenruo ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item); 1011f82d1c7cSQu Wenruo flags = btrfs_extent_flags(leaf, ei); 1012f82d1c7cSQu Wenruo total_refs = btrfs_extent_refs(leaf, ei); 1013f82d1c7cSQu Wenruo generation = btrfs_extent_generation(leaf, ei); 1014f82d1c7cSQu Wenruo if (generation > btrfs_super_generation(fs_info->super_copy) + 1) { 1015f82d1c7cSQu Wenruo extent_err(leaf, slot, 1016f82d1c7cSQu Wenruo "invalid generation, have %llu expect (0, %llu]", 1017f82d1c7cSQu Wenruo generation, 1018f82d1c7cSQu Wenruo btrfs_super_generation(fs_info->super_copy) + 1); 1019f82d1c7cSQu Wenruo return -EUCLEAN; 1020f82d1c7cSQu Wenruo } 1021f82d1c7cSQu Wenruo if (!is_power_of_2(flags & (BTRFS_EXTENT_FLAG_DATA | 1022f82d1c7cSQu Wenruo BTRFS_EXTENT_FLAG_TREE_BLOCK))) { 1023f82d1c7cSQu Wenruo extent_err(leaf, slot, 1024f82d1c7cSQu Wenruo "invalid extent flag, have 0x%llx expect 1 bit set in 0x%llx", 1025f82d1c7cSQu Wenruo flags, BTRFS_EXTENT_FLAG_DATA | 1026f82d1c7cSQu Wenruo BTRFS_EXTENT_FLAG_TREE_BLOCK); 1027f82d1c7cSQu Wenruo return -EUCLEAN; 1028f82d1c7cSQu Wenruo } 1029f82d1c7cSQu Wenruo is_tree_block = !!(flags & BTRFS_EXTENT_FLAG_TREE_BLOCK); 1030f82d1c7cSQu Wenruo if (is_tree_block) { 1031f82d1c7cSQu Wenruo if (key->type == BTRFS_EXTENT_ITEM_KEY && 1032f82d1c7cSQu Wenruo key->offset != fs_info->nodesize) { 1033f82d1c7cSQu Wenruo extent_err(leaf, slot, 1034f82d1c7cSQu Wenruo "invalid extent length, have %llu expect %u", 1035f82d1c7cSQu Wenruo key->offset, fs_info->nodesize); 1036f82d1c7cSQu Wenruo return -EUCLEAN; 1037f82d1c7cSQu Wenruo } 1038f82d1c7cSQu Wenruo } else { 1039f82d1c7cSQu Wenruo if (key->type != BTRFS_EXTENT_ITEM_KEY) { 1040f82d1c7cSQu Wenruo extent_err(leaf, slot, 1041f82d1c7cSQu Wenruo "invalid key type, have %u expect %u for data backref", 1042f82d1c7cSQu Wenruo key->type, BTRFS_EXTENT_ITEM_KEY); 1043f82d1c7cSQu Wenruo return -EUCLEAN; 1044f82d1c7cSQu Wenruo } 1045f82d1c7cSQu Wenruo if (!IS_ALIGNED(key->offset, fs_info->sectorsize)) { 1046f82d1c7cSQu Wenruo extent_err(leaf, slot, 1047f82d1c7cSQu Wenruo "invalid extent length, have %llu expect aligned to %u", 1048f82d1c7cSQu Wenruo key->offset, fs_info->sectorsize); 1049f82d1c7cSQu Wenruo return -EUCLEAN; 1050f82d1c7cSQu Wenruo } 1051f82d1c7cSQu Wenruo } 1052f82d1c7cSQu Wenruo ptr = (unsigned long)(struct btrfs_extent_item *)(ei + 1); 1053f82d1c7cSQu Wenruo 1054f82d1c7cSQu Wenruo /* Check the special case of btrfs_tree_block_info */ 1055f82d1c7cSQu Wenruo if (is_tree_block && key->type != BTRFS_METADATA_ITEM_KEY) { 1056f82d1c7cSQu Wenruo struct btrfs_tree_block_info *info; 1057f82d1c7cSQu Wenruo 1058f82d1c7cSQu Wenruo info = (struct btrfs_tree_block_info *)ptr; 1059f82d1c7cSQu Wenruo if (btrfs_tree_block_level(leaf, info) >= BTRFS_MAX_LEVEL) { 1060f82d1c7cSQu Wenruo extent_err(leaf, slot, 1061f82d1c7cSQu Wenruo "invalid tree block info level, have %u expect [0, %u]", 1062f82d1c7cSQu Wenruo btrfs_tree_block_level(leaf, info), 1063f82d1c7cSQu Wenruo BTRFS_MAX_LEVEL - 1); 1064f82d1c7cSQu Wenruo return -EUCLEAN; 1065f82d1c7cSQu Wenruo } 1066f82d1c7cSQu Wenruo ptr = (unsigned long)(struct btrfs_tree_block_info *)(info + 1); 1067f82d1c7cSQu Wenruo } 1068f82d1c7cSQu Wenruo 1069f82d1c7cSQu Wenruo /* Check inline refs */ 1070f82d1c7cSQu Wenruo while (ptr < end) { 1071f82d1c7cSQu Wenruo struct btrfs_extent_inline_ref *iref; 1072f82d1c7cSQu Wenruo struct btrfs_extent_data_ref *dref; 1073f82d1c7cSQu Wenruo struct btrfs_shared_data_ref *sref; 1074f82d1c7cSQu Wenruo u64 dref_offset; 1075f82d1c7cSQu Wenruo u64 inline_offset; 1076f82d1c7cSQu Wenruo u8 inline_type; 1077f82d1c7cSQu Wenruo 1078f82d1c7cSQu Wenruo if (ptr + sizeof(*iref) > end) { 1079f82d1c7cSQu Wenruo extent_err(leaf, slot, 1080f82d1c7cSQu Wenruo "inline ref item overflows extent item, ptr %lu iref size %zu end %lu", 1081f82d1c7cSQu Wenruo ptr, sizeof(*iref), end); 1082f82d1c7cSQu Wenruo return -EUCLEAN; 1083f82d1c7cSQu Wenruo } 1084f82d1c7cSQu Wenruo iref = (struct btrfs_extent_inline_ref *)ptr; 1085f82d1c7cSQu Wenruo inline_type = btrfs_extent_inline_ref_type(leaf, iref); 1086f82d1c7cSQu Wenruo inline_offset = btrfs_extent_inline_ref_offset(leaf, iref); 1087f82d1c7cSQu Wenruo if (ptr + btrfs_extent_inline_ref_size(inline_type) > end) { 1088f82d1c7cSQu Wenruo extent_err(leaf, slot, 1089f82d1c7cSQu Wenruo "inline ref item overflows extent item, ptr %lu iref size %u end %lu", 1090f82d1c7cSQu Wenruo ptr, inline_type, end); 1091f82d1c7cSQu Wenruo return -EUCLEAN; 1092f82d1c7cSQu Wenruo } 1093f82d1c7cSQu Wenruo 1094f82d1c7cSQu Wenruo switch (inline_type) { 1095f82d1c7cSQu Wenruo /* inline_offset is subvolid of the owner, no need to check */ 1096f82d1c7cSQu Wenruo case BTRFS_TREE_BLOCK_REF_KEY: 1097f82d1c7cSQu Wenruo inline_refs++; 1098f82d1c7cSQu Wenruo break; 1099f82d1c7cSQu Wenruo /* Contains parent bytenr */ 1100f82d1c7cSQu Wenruo case BTRFS_SHARED_BLOCK_REF_KEY: 1101f82d1c7cSQu Wenruo if (!IS_ALIGNED(inline_offset, fs_info->sectorsize)) { 1102f82d1c7cSQu Wenruo extent_err(leaf, slot, 1103f82d1c7cSQu Wenruo "invalid tree parent bytenr, have %llu expect aligned to %u", 1104f82d1c7cSQu Wenruo inline_offset, fs_info->sectorsize); 1105f82d1c7cSQu Wenruo return -EUCLEAN; 1106f82d1c7cSQu Wenruo } 1107f82d1c7cSQu Wenruo inline_refs++; 1108f82d1c7cSQu Wenruo break; 1109f82d1c7cSQu Wenruo /* 1110f82d1c7cSQu Wenruo * Contains owner subvolid, owner key objectid, adjusted offset. 1111f82d1c7cSQu Wenruo * The only obvious corruption can happen in that offset. 1112f82d1c7cSQu Wenruo */ 1113f82d1c7cSQu Wenruo case BTRFS_EXTENT_DATA_REF_KEY: 1114f82d1c7cSQu Wenruo dref = (struct btrfs_extent_data_ref *)(&iref->offset); 1115f82d1c7cSQu Wenruo dref_offset = btrfs_extent_data_ref_offset(leaf, dref); 1116f82d1c7cSQu Wenruo if (!IS_ALIGNED(dref_offset, fs_info->sectorsize)) { 1117f82d1c7cSQu Wenruo extent_err(leaf, slot, 1118f82d1c7cSQu Wenruo "invalid data ref offset, have %llu expect aligned to %u", 1119f82d1c7cSQu Wenruo dref_offset, fs_info->sectorsize); 1120f82d1c7cSQu Wenruo return -EUCLEAN; 1121f82d1c7cSQu Wenruo } 1122f82d1c7cSQu Wenruo inline_refs += btrfs_extent_data_ref_count(leaf, dref); 1123f82d1c7cSQu Wenruo break; 1124f82d1c7cSQu Wenruo /* Contains parent bytenr and ref count */ 1125f82d1c7cSQu Wenruo case BTRFS_SHARED_DATA_REF_KEY: 1126f82d1c7cSQu Wenruo sref = (struct btrfs_shared_data_ref *)(iref + 1); 1127f82d1c7cSQu Wenruo if (!IS_ALIGNED(inline_offset, fs_info->sectorsize)) { 1128f82d1c7cSQu Wenruo extent_err(leaf, slot, 1129f82d1c7cSQu Wenruo "invalid data parent bytenr, have %llu expect aligned to %u", 1130f82d1c7cSQu Wenruo inline_offset, fs_info->sectorsize); 1131f82d1c7cSQu Wenruo return -EUCLEAN; 1132f82d1c7cSQu Wenruo } 1133f82d1c7cSQu Wenruo inline_refs += btrfs_shared_data_ref_count(leaf, sref); 1134f82d1c7cSQu Wenruo break; 1135f82d1c7cSQu Wenruo default: 1136f82d1c7cSQu Wenruo extent_err(leaf, slot, "unknown inline ref type: %u", 1137f82d1c7cSQu Wenruo inline_type); 1138f82d1c7cSQu Wenruo return -EUCLEAN; 1139f82d1c7cSQu Wenruo } 1140f82d1c7cSQu Wenruo ptr += btrfs_extent_inline_ref_size(inline_type); 1141f82d1c7cSQu Wenruo } 1142f82d1c7cSQu Wenruo /* No padding is allowed */ 1143f82d1c7cSQu Wenruo if (ptr != end) { 1144f82d1c7cSQu Wenruo extent_err(leaf, slot, 1145f82d1c7cSQu Wenruo "invalid extent item size, padding bytes found"); 1146f82d1c7cSQu Wenruo return -EUCLEAN; 1147f82d1c7cSQu Wenruo } 1148f82d1c7cSQu Wenruo 1149f82d1c7cSQu Wenruo /* Finally, check the inline refs against total refs */ 1150f82d1c7cSQu Wenruo if (inline_refs > total_refs) { 1151f82d1c7cSQu Wenruo extent_err(leaf, slot, 1152f82d1c7cSQu Wenruo "invalid extent refs, have %llu expect >= inline %llu", 1153f82d1c7cSQu Wenruo total_refs, inline_refs); 1154f82d1c7cSQu Wenruo return -EUCLEAN; 1155f82d1c7cSQu Wenruo } 1156f82d1c7cSQu Wenruo return 0; 1157f82d1c7cSQu Wenruo } 1158f82d1c7cSQu Wenruo 1159e2406a6fSQu Wenruo static int check_simple_keyed_refs(struct extent_buffer *leaf, 1160e2406a6fSQu Wenruo struct btrfs_key *key, int slot) 1161e2406a6fSQu Wenruo { 1162e2406a6fSQu Wenruo u32 expect_item_size = 0; 1163e2406a6fSQu Wenruo 1164e2406a6fSQu Wenruo if (key->type == BTRFS_SHARED_DATA_REF_KEY) 1165e2406a6fSQu Wenruo expect_item_size = sizeof(struct btrfs_shared_data_ref); 1166e2406a6fSQu Wenruo 1167e2406a6fSQu Wenruo if (btrfs_item_size_nr(leaf, slot) != expect_item_size) { 1168e2406a6fSQu Wenruo generic_err(leaf, slot, 1169e2406a6fSQu Wenruo "invalid item size, have %u expect %u for key type %u", 1170e2406a6fSQu Wenruo btrfs_item_size_nr(leaf, slot), 1171e2406a6fSQu Wenruo expect_item_size, key->type); 1172e2406a6fSQu Wenruo return -EUCLEAN; 1173e2406a6fSQu Wenruo } 1174e2406a6fSQu Wenruo if (!IS_ALIGNED(key->objectid, leaf->fs_info->sectorsize)) { 1175e2406a6fSQu Wenruo generic_err(leaf, slot, 1176e2406a6fSQu Wenruo "invalid key objectid for shared block ref, have %llu expect aligned to %u", 1177e2406a6fSQu Wenruo key->objectid, leaf->fs_info->sectorsize); 1178e2406a6fSQu Wenruo return -EUCLEAN; 1179e2406a6fSQu Wenruo } 1180e2406a6fSQu Wenruo if (key->type != BTRFS_TREE_BLOCK_REF_KEY && 1181e2406a6fSQu Wenruo !IS_ALIGNED(key->offset, leaf->fs_info->sectorsize)) { 1182e2406a6fSQu Wenruo extent_err(leaf, slot, 1183e2406a6fSQu Wenruo "invalid tree parent bytenr, have %llu expect aligned to %u", 1184e2406a6fSQu Wenruo key->offset, leaf->fs_info->sectorsize); 1185e2406a6fSQu Wenruo return -EUCLEAN; 1186e2406a6fSQu Wenruo } 1187e2406a6fSQu Wenruo return 0; 1188e2406a6fSQu Wenruo } 1189e2406a6fSQu Wenruo 11900785a9aaSQu Wenruo static int check_extent_data_ref(struct extent_buffer *leaf, 11910785a9aaSQu Wenruo struct btrfs_key *key, int slot) 11920785a9aaSQu Wenruo { 11930785a9aaSQu Wenruo struct btrfs_extent_data_ref *dref; 11940785a9aaSQu Wenruo unsigned long ptr = btrfs_item_ptr_offset(leaf, slot); 11950785a9aaSQu Wenruo const unsigned long end = ptr + btrfs_item_size_nr(leaf, slot); 11960785a9aaSQu Wenruo 11970785a9aaSQu Wenruo if (btrfs_item_size_nr(leaf, slot) % sizeof(*dref) != 0) { 11980785a9aaSQu Wenruo generic_err(leaf, slot, 11990785a9aaSQu Wenruo "invalid item size, have %u expect aligned to %zu for key type %u", 12000785a9aaSQu Wenruo btrfs_item_size_nr(leaf, slot), 12010785a9aaSQu Wenruo sizeof(*dref), key->type); 12020785a9aaSQu Wenruo } 12030785a9aaSQu Wenruo if (!IS_ALIGNED(key->objectid, leaf->fs_info->sectorsize)) { 12040785a9aaSQu Wenruo generic_err(leaf, slot, 12050785a9aaSQu Wenruo "invalid key objectid for shared block ref, have %llu expect aligned to %u", 12060785a9aaSQu Wenruo key->objectid, leaf->fs_info->sectorsize); 12070785a9aaSQu Wenruo return -EUCLEAN; 12080785a9aaSQu Wenruo } 12090785a9aaSQu Wenruo for (; ptr < end; ptr += sizeof(*dref)) { 12100785a9aaSQu Wenruo u64 root_objectid; 12110785a9aaSQu Wenruo u64 owner; 12120785a9aaSQu Wenruo u64 offset; 12130785a9aaSQu Wenruo u64 hash; 12140785a9aaSQu Wenruo 12150785a9aaSQu Wenruo dref = (struct btrfs_extent_data_ref *)ptr; 12160785a9aaSQu Wenruo root_objectid = btrfs_extent_data_ref_root(leaf, dref); 12170785a9aaSQu Wenruo owner = btrfs_extent_data_ref_objectid(leaf, dref); 12180785a9aaSQu Wenruo offset = btrfs_extent_data_ref_offset(leaf, dref); 12190785a9aaSQu Wenruo hash = hash_extent_data_ref(root_objectid, owner, offset); 12200785a9aaSQu Wenruo if (hash != key->offset) { 12210785a9aaSQu Wenruo extent_err(leaf, slot, 12220785a9aaSQu Wenruo "invalid extent data ref hash, item has 0x%016llx key has 0x%016llx", 12230785a9aaSQu Wenruo hash, key->offset); 12240785a9aaSQu Wenruo return -EUCLEAN; 12250785a9aaSQu Wenruo } 12260785a9aaSQu Wenruo if (!IS_ALIGNED(offset, leaf->fs_info->sectorsize)) { 12270785a9aaSQu Wenruo extent_err(leaf, slot, 12280785a9aaSQu Wenruo "invalid extent data backref offset, have %llu expect aligned to %u", 12290785a9aaSQu Wenruo offset, leaf->fs_info->sectorsize); 12300785a9aaSQu Wenruo } 12310785a9aaSQu Wenruo } 12320785a9aaSQu Wenruo return 0; 12330785a9aaSQu Wenruo } 12340785a9aaSQu Wenruo 123582fc28fbSQu Wenruo /* 1236557ea5ddSQu Wenruo * Common point to switch the item-specific validation. 1237557ea5ddSQu Wenruo */ 12380076bc89SDavid Sterba static int check_leaf_item(struct extent_buffer *leaf, 12394e9845efSFilipe Manana struct btrfs_key *key, int slot, 12404e9845efSFilipe Manana struct btrfs_key *prev_key) 1241557ea5ddSQu Wenruo { 1242557ea5ddSQu Wenruo int ret = 0; 1243075cb3c7SQu Wenruo struct btrfs_chunk *chunk; 1244557ea5ddSQu Wenruo 1245557ea5ddSQu Wenruo switch (key->type) { 1246557ea5ddSQu Wenruo case BTRFS_EXTENT_DATA_KEY: 12474e9845efSFilipe Manana ret = check_extent_data_item(leaf, key, slot, prev_key); 1248557ea5ddSQu Wenruo break; 1249557ea5ddSQu Wenruo case BTRFS_EXTENT_CSUM_KEY: 125068128ce7SDavid Sterba ret = check_csum_item(leaf, key, slot); 1251557ea5ddSQu Wenruo break; 1252ad7b0368SQu Wenruo case BTRFS_DIR_ITEM_KEY: 1253ad7b0368SQu Wenruo case BTRFS_DIR_INDEX_KEY: 1254ad7b0368SQu Wenruo case BTRFS_XATTR_ITEM_KEY: 1255ce4252c0SDavid Sterba ret = check_dir_item(leaf, key, slot); 1256ad7b0368SQu Wenruo break; 1257fce466eaSQu Wenruo case BTRFS_BLOCK_GROUP_ITEM_KEY: 1258af60ce2bSDavid Sterba ret = check_block_group_item(leaf, key, slot); 1259fce466eaSQu Wenruo break; 1260075cb3c7SQu Wenruo case BTRFS_CHUNK_ITEM_KEY: 1261075cb3c7SQu Wenruo chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); 1262ddaf1d5aSDavid Sterba ret = btrfs_check_chunk_valid(leaf, chunk, key->offset); 1263075cb3c7SQu Wenruo break; 1264ab4ba2e1SQu Wenruo case BTRFS_DEV_ITEM_KEY: 1265412a2312SDavid Sterba ret = check_dev_item(leaf, key, slot); 1266ab4ba2e1SQu Wenruo break; 1267496245caSQu Wenruo case BTRFS_INODE_ITEM_KEY: 126839e57f49SDavid Sterba ret = check_inode_item(leaf, key, slot); 1269496245caSQu Wenruo break; 1270259ee775SQu Wenruo case BTRFS_ROOT_ITEM_KEY: 1271259ee775SQu Wenruo ret = check_root_item(leaf, key, slot); 1272259ee775SQu Wenruo break; 1273f82d1c7cSQu Wenruo case BTRFS_EXTENT_ITEM_KEY: 1274f82d1c7cSQu Wenruo case BTRFS_METADATA_ITEM_KEY: 1275f82d1c7cSQu Wenruo ret = check_extent_item(leaf, key, slot); 1276f82d1c7cSQu Wenruo break; 1277e2406a6fSQu Wenruo case BTRFS_TREE_BLOCK_REF_KEY: 1278e2406a6fSQu Wenruo case BTRFS_SHARED_DATA_REF_KEY: 1279e2406a6fSQu Wenruo case BTRFS_SHARED_BLOCK_REF_KEY: 1280e2406a6fSQu Wenruo ret = check_simple_keyed_refs(leaf, key, slot); 1281e2406a6fSQu Wenruo break; 12820785a9aaSQu Wenruo case BTRFS_EXTENT_DATA_REF_KEY: 12830785a9aaSQu Wenruo ret = check_extent_data_ref(leaf, key, slot); 12840785a9aaSQu Wenruo break; 1285557ea5ddSQu Wenruo } 1286557ea5ddSQu Wenruo return ret; 1287557ea5ddSQu Wenruo } 1288557ea5ddSQu Wenruo 1289e2ccd361SDavid Sterba static int check_leaf(struct extent_buffer *leaf, bool check_item_data) 1290557ea5ddSQu Wenruo { 1291e2ccd361SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 1292557ea5ddSQu Wenruo /* No valid key type is 0, so all key should be larger than this key */ 1293557ea5ddSQu Wenruo struct btrfs_key prev_key = {0, 0, 0}; 1294557ea5ddSQu Wenruo struct btrfs_key key; 1295557ea5ddSQu Wenruo u32 nritems = btrfs_header_nritems(leaf); 1296557ea5ddSQu Wenruo int slot; 1297557ea5ddSQu Wenruo 1298f556faa4SQu Wenruo if (btrfs_header_level(leaf) != 0) { 129986a6be3aSDavid Sterba generic_err(leaf, 0, 1300f556faa4SQu Wenruo "invalid level for leaf, have %d expect 0", 1301f556faa4SQu Wenruo btrfs_header_level(leaf)); 1302f556faa4SQu Wenruo return -EUCLEAN; 1303f556faa4SQu Wenruo } 1304f556faa4SQu Wenruo 1305557ea5ddSQu Wenruo /* 1306557ea5ddSQu Wenruo * Extent buffers from a relocation tree have a owner field that 1307557ea5ddSQu Wenruo * corresponds to the subvolume tree they are based on. So just from an 1308557ea5ddSQu Wenruo * extent buffer alone we can not find out what is the id of the 1309557ea5ddSQu Wenruo * corresponding subvolume tree, so we can not figure out if the extent 1310557ea5ddSQu Wenruo * buffer corresponds to the root of the relocation tree or not. So 1311557ea5ddSQu Wenruo * skip this check for relocation trees. 1312557ea5ddSQu Wenruo */ 1313557ea5ddSQu Wenruo if (nritems == 0 && !btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_RELOC)) { 1314ba480dd4SQu Wenruo u64 owner = btrfs_header_owner(leaf); 1315557ea5ddSQu Wenruo 1316ba480dd4SQu Wenruo /* These trees must never be empty */ 1317ba480dd4SQu Wenruo if (owner == BTRFS_ROOT_TREE_OBJECTID || 1318ba480dd4SQu Wenruo owner == BTRFS_CHUNK_TREE_OBJECTID || 1319ba480dd4SQu Wenruo owner == BTRFS_EXTENT_TREE_OBJECTID || 1320ba480dd4SQu Wenruo owner == BTRFS_DEV_TREE_OBJECTID || 1321ba480dd4SQu Wenruo owner == BTRFS_FS_TREE_OBJECTID || 1322ba480dd4SQu Wenruo owner == BTRFS_DATA_RELOC_TREE_OBJECTID) { 132386a6be3aSDavid Sterba generic_err(leaf, 0, 1324ba480dd4SQu Wenruo "invalid root, root %llu must never be empty", 1325ba480dd4SQu Wenruo owner); 1326ba480dd4SQu Wenruo return -EUCLEAN; 1327ba480dd4SQu Wenruo } 1328*62fdaa52SQu Wenruo /* Unknown tree */ 1329*62fdaa52SQu Wenruo if (owner == 0) { 1330*62fdaa52SQu Wenruo generic_err(leaf, 0, 1331*62fdaa52SQu Wenruo "invalid owner, root 0 is not defined"); 1332*62fdaa52SQu Wenruo return -EUCLEAN; 1333*62fdaa52SQu Wenruo } 1334557ea5ddSQu Wenruo return 0; 1335557ea5ddSQu Wenruo } 1336557ea5ddSQu Wenruo 1337557ea5ddSQu Wenruo if (nritems == 0) 1338557ea5ddSQu Wenruo return 0; 1339557ea5ddSQu Wenruo 1340557ea5ddSQu Wenruo /* 1341557ea5ddSQu Wenruo * Check the following things to make sure this is a good leaf, and 1342557ea5ddSQu Wenruo * leaf users won't need to bother with similar sanity checks: 1343557ea5ddSQu Wenruo * 1344557ea5ddSQu Wenruo * 1) key ordering 1345557ea5ddSQu Wenruo * 2) item offset and size 1346557ea5ddSQu Wenruo * No overlap, no hole, all inside the leaf. 1347557ea5ddSQu Wenruo * 3) item content 1348557ea5ddSQu Wenruo * If possible, do comprehensive sanity check. 1349557ea5ddSQu Wenruo * NOTE: All checks must only rely on the item data itself. 1350557ea5ddSQu Wenruo */ 1351557ea5ddSQu Wenruo for (slot = 0; slot < nritems; slot++) { 1352557ea5ddSQu Wenruo u32 item_end_expected; 1353557ea5ddSQu Wenruo int ret; 1354557ea5ddSQu Wenruo 1355557ea5ddSQu Wenruo btrfs_item_key_to_cpu(leaf, &key, slot); 1356557ea5ddSQu Wenruo 1357557ea5ddSQu Wenruo /* Make sure the keys are in the right order */ 1358557ea5ddSQu Wenruo if (btrfs_comp_cpu_keys(&prev_key, &key) >= 0) { 135986a6be3aSDavid Sterba generic_err(leaf, slot, 1360478d01b3SQu Wenruo "bad key order, prev (%llu %u %llu) current (%llu %u %llu)", 1361478d01b3SQu Wenruo prev_key.objectid, prev_key.type, 1362478d01b3SQu Wenruo prev_key.offset, key.objectid, key.type, 1363478d01b3SQu Wenruo key.offset); 1364557ea5ddSQu Wenruo return -EUCLEAN; 1365557ea5ddSQu Wenruo } 1366557ea5ddSQu Wenruo 1367557ea5ddSQu Wenruo /* 1368557ea5ddSQu Wenruo * Make sure the offset and ends are right, remember that the 1369557ea5ddSQu Wenruo * item data starts at the end of the leaf and grows towards the 1370557ea5ddSQu Wenruo * front. 1371557ea5ddSQu Wenruo */ 1372557ea5ddSQu Wenruo if (slot == 0) 1373557ea5ddSQu Wenruo item_end_expected = BTRFS_LEAF_DATA_SIZE(fs_info); 1374557ea5ddSQu Wenruo else 1375557ea5ddSQu Wenruo item_end_expected = btrfs_item_offset_nr(leaf, 1376557ea5ddSQu Wenruo slot - 1); 1377557ea5ddSQu Wenruo if (btrfs_item_end_nr(leaf, slot) != item_end_expected) { 137886a6be3aSDavid Sterba generic_err(leaf, slot, 1379478d01b3SQu Wenruo "unexpected item end, have %u expect %u", 1380478d01b3SQu Wenruo btrfs_item_end_nr(leaf, slot), 1381478d01b3SQu Wenruo item_end_expected); 1382557ea5ddSQu Wenruo return -EUCLEAN; 1383557ea5ddSQu Wenruo } 1384557ea5ddSQu Wenruo 1385557ea5ddSQu Wenruo /* 1386557ea5ddSQu Wenruo * Check to make sure that we don't point outside of the leaf, 1387557ea5ddSQu Wenruo * just in case all the items are consistent to each other, but 1388557ea5ddSQu Wenruo * all point outside of the leaf. 1389557ea5ddSQu Wenruo */ 1390557ea5ddSQu Wenruo if (btrfs_item_end_nr(leaf, slot) > 1391557ea5ddSQu Wenruo BTRFS_LEAF_DATA_SIZE(fs_info)) { 139286a6be3aSDavid Sterba generic_err(leaf, slot, 1393478d01b3SQu Wenruo "slot end outside of leaf, have %u expect range [0, %u]", 1394478d01b3SQu Wenruo btrfs_item_end_nr(leaf, slot), 1395478d01b3SQu Wenruo BTRFS_LEAF_DATA_SIZE(fs_info)); 1396557ea5ddSQu Wenruo return -EUCLEAN; 1397557ea5ddSQu Wenruo } 1398557ea5ddSQu Wenruo 1399557ea5ddSQu Wenruo /* Also check if the item pointer overlaps with btrfs item. */ 1400557ea5ddSQu Wenruo if (btrfs_item_nr_offset(slot) + sizeof(struct btrfs_item) > 1401557ea5ddSQu Wenruo btrfs_item_ptr_offset(leaf, slot)) { 140286a6be3aSDavid Sterba generic_err(leaf, slot, 1403478d01b3SQu Wenruo "slot overlaps with its data, item end %lu data start %lu", 1404478d01b3SQu Wenruo btrfs_item_nr_offset(slot) + 1405478d01b3SQu Wenruo sizeof(struct btrfs_item), 1406478d01b3SQu Wenruo btrfs_item_ptr_offset(leaf, slot)); 1407557ea5ddSQu Wenruo return -EUCLEAN; 1408557ea5ddSQu Wenruo } 1409557ea5ddSQu Wenruo 141069fc6cbbSQu Wenruo if (check_item_data) { 141169fc6cbbSQu Wenruo /* 141269fc6cbbSQu Wenruo * Check if the item size and content meet other 141369fc6cbbSQu Wenruo * criteria 141469fc6cbbSQu Wenruo */ 14154e9845efSFilipe Manana ret = check_leaf_item(leaf, &key, slot, &prev_key); 1416557ea5ddSQu Wenruo if (ret < 0) 1417557ea5ddSQu Wenruo return ret; 141869fc6cbbSQu Wenruo } 1419557ea5ddSQu Wenruo 1420557ea5ddSQu Wenruo prev_key.objectid = key.objectid; 1421557ea5ddSQu Wenruo prev_key.type = key.type; 1422557ea5ddSQu Wenruo prev_key.offset = key.offset; 1423557ea5ddSQu Wenruo } 1424557ea5ddSQu Wenruo 1425557ea5ddSQu Wenruo return 0; 1426557ea5ddSQu Wenruo } 1427557ea5ddSQu Wenruo 14281c4360eeSDavid Sterba int btrfs_check_leaf_full(struct extent_buffer *leaf) 142969fc6cbbSQu Wenruo { 1430e2ccd361SDavid Sterba return check_leaf(leaf, true); 143169fc6cbbSQu Wenruo } 143202529d7aSQu Wenruo ALLOW_ERROR_INJECTION(btrfs_check_leaf_full, ERRNO); 143369fc6cbbSQu Wenruo 1434cfdaad5eSDavid Sterba int btrfs_check_leaf_relaxed(struct extent_buffer *leaf) 14352f659546SQu Wenruo { 1436e2ccd361SDavid Sterba return check_leaf(leaf, false); 14372f659546SQu Wenruo } 14382f659546SQu Wenruo 1439813fd1dcSDavid Sterba int btrfs_check_node(struct extent_buffer *node) 1440557ea5ddSQu Wenruo { 1441813fd1dcSDavid Sterba struct btrfs_fs_info *fs_info = node->fs_info; 1442557ea5ddSQu Wenruo unsigned long nr = btrfs_header_nritems(node); 1443557ea5ddSQu Wenruo struct btrfs_key key, next_key; 1444557ea5ddSQu Wenruo int slot; 1445f556faa4SQu Wenruo int level = btrfs_header_level(node); 1446557ea5ddSQu Wenruo u64 bytenr; 1447557ea5ddSQu Wenruo int ret = 0; 1448557ea5ddSQu Wenruo 1449f556faa4SQu Wenruo if (level <= 0 || level >= BTRFS_MAX_LEVEL) { 145086a6be3aSDavid Sterba generic_err(node, 0, 1451f556faa4SQu Wenruo "invalid level for node, have %d expect [1, %d]", 1452f556faa4SQu Wenruo level, BTRFS_MAX_LEVEL - 1); 1453f556faa4SQu Wenruo return -EUCLEAN; 1454f556faa4SQu Wenruo } 14552f659546SQu Wenruo if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(fs_info)) { 14562f659546SQu Wenruo btrfs_crit(fs_info, 1457bba4f298SQu Wenruo "corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%u]", 14582f659546SQu Wenruo btrfs_header_owner(node), node->start, 1459bba4f298SQu Wenruo nr == 0 ? "small" : "large", nr, 14602f659546SQu Wenruo BTRFS_NODEPTRS_PER_BLOCK(fs_info)); 1461bba4f298SQu Wenruo return -EUCLEAN; 1462557ea5ddSQu Wenruo } 1463557ea5ddSQu Wenruo 1464557ea5ddSQu Wenruo for (slot = 0; slot < nr - 1; slot++) { 1465557ea5ddSQu Wenruo bytenr = btrfs_node_blockptr(node, slot); 1466557ea5ddSQu Wenruo btrfs_node_key_to_cpu(node, &key, slot); 1467557ea5ddSQu Wenruo btrfs_node_key_to_cpu(node, &next_key, slot + 1); 1468557ea5ddSQu Wenruo 1469557ea5ddSQu Wenruo if (!bytenr) { 147086a6be3aSDavid Sterba generic_err(node, slot, 1471bba4f298SQu Wenruo "invalid NULL node pointer"); 1472bba4f298SQu Wenruo ret = -EUCLEAN; 1473bba4f298SQu Wenruo goto out; 1474bba4f298SQu Wenruo } 14752f659546SQu Wenruo if (!IS_ALIGNED(bytenr, fs_info->sectorsize)) { 147686a6be3aSDavid Sterba generic_err(node, slot, 1477bba4f298SQu Wenruo "unaligned pointer, have %llu should be aligned to %u", 14782f659546SQu Wenruo bytenr, fs_info->sectorsize); 1479bba4f298SQu Wenruo ret = -EUCLEAN; 1480557ea5ddSQu Wenruo goto out; 1481557ea5ddSQu Wenruo } 1482557ea5ddSQu Wenruo 1483557ea5ddSQu Wenruo if (btrfs_comp_cpu_keys(&key, &next_key) >= 0) { 148486a6be3aSDavid Sterba generic_err(node, slot, 1485bba4f298SQu Wenruo "bad key order, current (%llu %u %llu) next (%llu %u %llu)", 1486bba4f298SQu Wenruo key.objectid, key.type, key.offset, 1487bba4f298SQu Wenruo next_key.objectid, next_key.type, 1488bba4f298SQu Wenruo next_key.offset); 1489bba4f298SQu Wenruo ret = -EUCLEAN; 1490557ea5ddSQu Wenruo goto out; 1491557ea5ddSQu Wenruo } 1492557ea5ddSQu Wenruo } 1493557ea5ddSQu Wenruo out: 1494557ea5ddSQu Wenruo return ret; 1495557ea5ddSQu Wenruo } 149602529d7aSQu Wenruo ALLOW_ERROR_INJECTION(btrfs_check_node, ERRNO); 1497