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 110*4e9845efSFilipe Manana static u64 file_extent_end(struct extent_buffer *leaf, 111*4e9845efSFilipe Manana struct btrfs_key *key, 112*4e9845efSFilipe Manana struct btrfs_file_extent_item *extent) 113*4e9845efSFilipe Manana { 114*4e9845efSFilipe Manana u64 end; 115*4e9845efSFilipe Manana u64 len; 116*4e9845efSFilipe Manana 117*4e9845efSFilipe Manana if (btrfs_file_extent_type(leaf, extent) == BTRFS_FILE_EXTENT_INLINE) { 118*4e9845efSFilipe Manana len = btrfs_file_extent_ram_bytes(leaf, extent); 119*4e9845efSFilipe Manana end = ALIGN(key->offset + len, leaf->fs_info->sectorsize); 120*4e9845efSFilipe Manana } else { 121*4e9845efSFilipe Manana len = btrfs_file_extent_num_bytes(leaf, extent); 122*4e9845efSFilipe Manana end = key->offset + len; 123*4e9845efSFilipe Manana } 124*4e9845efSFilipe Manana return end; 125*4e9845efSFilipe Manana } 126*4e9845efSFilipe Manana 127ae2a19d8SDavid Sterba static int check_extent_data_item(struct extent_buffer *leaf, 128*4e9845efSFilipe Manana struct btrfs_key *key, int slot, 129*4e9845efSFilipe 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); 135557ea5ddSQu Wenruo 136557ea5ddSQu Wenruo if (!IS_ALIGNED(key->offset, sectorsize)) { 1371fd715ffSDavid Sterba file_extent_err(leaf, slot, 1388806d718SQu Wenruo "unaligned file_offset for file extent, have %llu should be aligned to %u", 1398806d718SQu Wenruo key->offset, sectorsize); 140557ea5ddSQu Wenruo return -EUCLEAN; 141557ea5ddSQu Wenruo } 142557ea5ddSQu Wenruo 143557ea5ddSQu Wenruo fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); 144557ea5ddSQu Wenruo 145557ea5ddSQu Wenruo if (btrfs_file_extent_type(leaf, fi) > BTRFS_FILE_EXTENT_TYPES) { 1461fd715ffSDavid Sterba file_extent_err(leaf, slot, 1478806d718SQu Wenruo "invalid type for file extent, have %u expect range [0, %u]", 1488806d718SQu Wenruo btrfs_file_extent_type(leaf, fi), 1498806d718SQu Wenruo BTRFS_FILE_EXTENT_TYPES); 150557ea5ddSQu Wenruo return -EUCLEAN; 151557ea5ddSQu Wenruo } 152557ea5ddSQu Wenruo 153557ea5ddSQu Wenruo /* 15452042d8eSAndrea Gelmini * Support for new compression/encryption must introduce incompat flag, 155557ea5ddSQu Wenruo * and must be caught in open_ctree(). 156557ea5ddSQu Wenruo */ 157557ea5ddSQu Wenruo if (btrfs_file_extent_compression(leaf, fi) > BTRFS_COMPRESS_TYPES) { 1581fd715ffSDavid Sterba file_extent_err(leaf, slot, 1598806d718SQu Wenruo "invalid compression for file extent, have %u expect range [0, %u]", 1608806d718SQu Wenruo btrfs_file_extent_compression(leaf, fi), 1618806d718SQu Wenruo BTRFS_COMPRESS_TYPES); 162557ea5ddSQu Wenruo return -EUCLEAN; 163557ea5ddSQu Wenruo } 164557ea5ddSQu Wenruo if (btrfs_file_extent_encryption(leaf, fi)) { 1651fd715ffSDavid Sterba file_extent_err(leaf, slot, 1668806d718SQu Wenruo "invalid encryption for file extent, have %u expect 0", 1678806d718SQu Wenruo btrfs_file_extent_encryption(leaf, fi)); 168557ea5ddSQu Wenruo return -EUCLEAN; 169557ea5ddSQu Wenruo } 170557ea5ddSQu Wenruo if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_INLINE) { 171557ea5ddSQu Wenruo /* Inline extent must have 0 as key offset */ 172557ea5ddSQu Wenruo if (key->offset) { 1731fd715ffSDavid Sterba file_extent_err(leaf, slot, 1748806d718SQu Wenruo "invalid file_offset for inline file extent, have %llu expect 0", 1758806d718SQu Wenruo key->offset); 176557ea5ddSQu Wenruo return -EUCLEAN; 177557ea5ddSQu Wenruo } 178557ea5ddSQu Wenruo 179557ea5ddSQu Wenruo /* Compressed inline extent has no on-disk size, skip it */ 180557ea5ddSQu Wenruo if (btrfs_file_extent_compression(leaf, fi) != 181557ea5ddSQu Wenruo BTRFS_COMPRESS_NONE) 182557ea5ddSQu Wenruo return 0; 183557ea5ddSQu Wenruo 184557ea5ddSQu Wenruo /* Uncompressed inline extent size must match item size */ 185557ea5ddSQu Wenruo if (item_size != BTRFS_FILE_EXTENT_INLINE_DATA_START + 186557ea5ddSQu Wenruo btrfs_file_extent_ram_bytes(leaf, fi)) { 1871fd715ffSDavid Sterba file_extent_err(leaf, slot, 1888806d718SQu Wenruo "invalid ram_bytes for uncompressed inline extent, have %u expect %llu", 1898806d718SQu Wenruo item_size, BTRFS_FILE_EXTENT_INLINE_DATA_START + 1908806d718SQu Wenruo btrfs_file_extent_ram_bytes(leaf, fi)); 191557ea5ddSQu Wenruo return -EUCLEAN; 192557ea5ddSQu Wenruo } 193557ea5ddSQu Wenruo return 0; 194557ea5ddSQu Wenruo } 195557ea5ddSQu Wenruo 196557ea5ddSQu Wenruo /* Regular or preallocated extent has fixed item size */ 197557ea5ddSQu Wenruo if (item_size != sizeof(*fi)) { 1981fd715ffSDavid Sterba file_extent_err(leaf, slot, 199709a95c3SArnd Bergmann "invalid item size for reg/prealloc file extent, have %u expect %zu", 2008806d718SQu Wenruo item_size, sizeof(*fi)); 201557ea5ddSQu Wenruo return -EUCLEAN; 202557ea5ddSQu Wenruo } 203033774dcSDavid Sterba if (CHECK_FE_ALIGNED(leaf, slot, fi, ram_bytes, sectorsize) || 204033774dcSDavid Sterba CHECK_FE_ALIGNED(leaf, slot, fi, disk_bytenr, sectorsize) || 205033774dcSDavid Sterba CHECK_FE_ALIGNED(leaf, slot, fi, disk_num_bytes, sectorsize) || 206033774dcSDavid Sterba CHECK_FE_ALIGNED(leaf, slot, fi, offset, sectorsize) || 207033774dcSDavid Sterba CHECK_FE_ALIGNED(leaf, slot, fi, num_bytes, sectorsize)) 208557ea5ddSQu Wenruo return -EUCLEAN; 209*4e9845efSFilipe Manana 210*4e9845efSFilipe Manana /* 211*4e9845efSFilipe Manana * Check that no two consecutive file extent items, in the same leaf, 212*4e9845efSFilipe Manana * present ranges that overlap each other. 213*4e9845efSFilipe Manana */ 214*4e9845efSFilipe Manana if (slot > 0 && 215*4e9845efSFilipe Manana prev_key->objectid == key->objectid && 216*4e9845efSFilipe Manana prev_key->type == BTRFS_EXTENT_DATA_KEY) { 217*4e9845efSFilipe Manana struct btrfs_file_extent_item *prev_fi; 218*4e9845efSFilipe Manana u64 prev_end; 219*4e9845efSFilipe Manana 220*4e9845efSFilipe Manana prev_fi = btrfs_item_ptr(leaf, slot - 1, 221*4e9845efSFilipe Manana struct btrfs_file_extent_item); 222*4e9845efSFilipe Manana prev_end = file_extent_end(leaf, prev_key, prev_fi); 223*4e9845efSFilipe Manana if (prev_end > key->offset) { 224*4e9845efSFilipe Manana file_extent_err(leaf, slot - 1, 225*4e9845efSFilipe Manana "file extent end range (%llu) goes beyond start offset (%llu) of the next file extent", 226*4e9845efSFilipe Manana prev_end, key->offset); 227*4e9845efSFilipe Manana return -EUCLEAN; 228*4e9845efSFilipe Manana } 229*4e9845efSFilipe Manana } 230*4e9845efSFilipe Manana 231557ea5ddSQu Wenruo return 0; 232557ea5ddSQu Wenruo } 233557ea5ddSQu Wenruo 23468128ce7SDavid Sterba static int check_csum_item(struct extent_buffer *leaf, struct btrfs_key *key, 2352f659546SQu Wenruo int slot) 236557ea5ddSQu Wenruo { 23768128ce7SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 2382f659546SQu Wenruo u32 sectorsize = fs_info->sectorsize; 2392f659546SQu Wenruo u32 csumsize = btrfs_super_csum_size(fs_info->super_copy); 240557ea5ddSQu Wenruo 241557ea5ddSQu Wenruo if (key->objectid != BTRFS_EXTENT_CSUM_OBJECTID) { 24286a6be3aSDavid Sterba generic_err(leaf, slot, 243d508c5f0SQu Wenruo "invalid key objectid for csum item, have %llu expect %llu", 244d508c5f0SQu Wenruo key->objectid, BTRFS_EXTENT_CSUM_OBJECTID); 245557ea5ddSQu Wenruo return -EUCLEAN; 246557ea5ddSQu Wenruo } 247557ea5ddSQu Wenruo if (!IS_ALIGNED(key->offset, sectorsize)) { 24886a6be3aSDavid Sterba generic_err(leaf, slot, 249d508c5f0SQu Wenruo "unaligned key offset for csum item, have %llu should be aligned to %u", 250d508c5f0SQu Wenruo key->offset, sectorsize); 251557ea5ddSQu Wenruo return -EUCLEAN; 252557ea5ddSQu Wenruo } 253557ea5ddSQu Wenruo if (!IS_ALIGNED(btrfs_item_size_nr(leaf, slot), csumsize)) { 25486a6be3aSDavid Sterba generic_err(leaf, slot, 255d508c5f0SQu Wenruo "unaligned item size for csum item, have %u should be aligned to %u", 256d508c5f0SQu Wenruo btrfs_item_size_nr(leaf, slot), csumsize); 257557ea5ddSQu Wenruo return -EUCLEAN; 258557ea5ddSQu Wenruo } 259557ea5ddSQu Wenruo return 0; 260557ea5ddSQu Wenruo } 261557ea5ddSQu Wenruo 262557ea5ddSQu Wenruo /* 263ad7b0368SQu Wenruo * Customized reported for dir_item, only important new info is key->objectid, 264ad7b0368SQu Wenruo * which represents inode number 265ad7b0368SQu Wenruo */ 266d98ced68SDavid Sterba __printf(3, 4) 267e67c718bSDavid Sterba __cold 268d98ced68SDavid Sterba static void dir_item_err(const struct extent_buffer *eb, int slot, 269ad7b0368SQu Wenruo const char *fmt, ...) 270ad7b0368SQu Wenruo { 271d98ced68SDavid Sterba const struct btrfs_fs_info *fs_info = eb->fs_info; 272ad7b0368SQu Wenruo struct btrfs_key key; 273ad7b0368SQu Wenruo struct va_format vaf; 274ad7b0368SQu Wenruo va_list args; 275ad7b0368SQu Wenruo 276ad7b0368SQu Wenruo btrfs_item_key_to_cpu(eb, &key, slot); 277ad7b0368SQu Wenruo va_start(args, fmt); 278ad7b0368SQu Wenruo 279ad7b0368SQu Wenruo vaf.fmt = fmt; 280ad7b0368SQu Wenruo vaf.va = &args; 281ad7b0368SQu Wenruo 2822f659546SQu Wenruo btrfs_crit(fs_info, 283ad7b0368SQu Wenruo "corrupt %s: root=%llu block=%llu slot=%d ino=%llu, %pV", 2842f659546SQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 2852f659546SQu Wenruo btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, 2862f659546SQu Wenruo key.objectid, &vaf); 287ad7b0368SQu Wenruo va_end(args); 288ad7b0368SQu Wenruo } 289ad7b0368SQu Wenruo 290ce4252c0SDavid Sterba static int check_dir_item(struct extent_buffer *leaf, 291ad7b0368SQu Wenruo struct btrfs_key *key, int slot) 292ad7b0368SQu Wenruo { 293ce4252c0SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 294ad7b0368SQu Wenruo struct btrfs_dir_item *di; 295ad7b0368SQu Wenruo u32 item_size = btrfs_item_size_nr(leaf, slot); 296ad7b0368SQu Wenruo u32 cur = 0; 297ad7b0368SQu Wenruo 298ad7b0368SQu Wenruo di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); 299ad7b0368SQu Wenruo while (cur < item_size) { 300ad7b0368SQu Wenruo u32 name_len; 301ad7b0368SQu Wenruo u32 data_len; 302ad7b0368SQu Wenruo u32 max_name_len; 303ad7b0368SQu Wenruo u32 total_size; 304ad7b0368SQu Wenruo u32 name_hash; 305ad7b0368SQu Wenruo u8 dir_type; 306ad7b0368SQu Wenruo 307ad7b0368SQu Wenruo /* header itself should not cross item boundary */ 308ad7b0368SQu Wenruo if (cur + sizeof(*di) > item_size) { 309d98ced68SDavid Sterba dir_item_err(leaf, slot, 3107cfad652SArnd Bergmann "dir item header crosses item boundary, have %zu boundary %u", 311ad7b0368SQu Wenruo cur + sizeof(*di), item_size); 312ad7b0368SQu Wenruo return -EUCLEAN; 313ad7b0368SQu Wenruo } 314ad7b0368SQu Wenruo 315ad7b0368SQu Wenruo /* dir type check */ 316ad7b0368SQu Wenruo dir_type = btrfs_dir_type(leaf, di); 317ad7b0368SQu Wenruo if (dir_type >= BTRFS_FT_MAX) { 318d98ced68SDavid Sterba dir_item_err(leaf, slot, 319ad7b0368SQu Wenruo "invalid dir item type, have %u expect [0, %u)", 320ad7b0368SQu Wenruo dir_type, BTRFS_FT_MAX); 321ad7b0368SQu Wenruo return -EUCLEAN; 322ad7b0368SQu Wenruo } 323ad7b0368SQu Wenruo 324ad7b0368SQu Wenruo if (key->type == BTRFS_XATTR_ITEM_KEY && 325ad7b0368SQu Wenruo dir_type != BTRFS_FT_XATTR) { 326d98ced68SDavid Sterba dir_item_err(leaf, slot, 327ad7b0368SQu Wenruo "invalid dir item type for XATTR key, have %u expect %u", 328ad7b0368SQu Wenruo dir_type, BTRFS_FT_XATTR); 329ad7b0368SQu Wenruo return -EUCLEAN; 330ad7b0368SQu Wenruo } 331ad7b0368SQu Wenruo if (dir_type == BTRFS_FT_XATTR && 332ad7b0368SQu Wenruo key->type != BTRFS_XATTR_ITEM_KEY) { 333d98ced68SDavid Sterba dir_item_err(leaf, slot, 334ad7b0368SQu Wenruo "xattr dir type found for non-XATTR key"); 335ad7b0368SQu Wenruo return -EUCLEAN; 336ad7b0368SQu Wenruo } 337ad7b0368SQu Wenruo if (dir_type == BTRFS_FT_XATTR) 338ad7b0368SQu Wenruo max_name_len = XATTR_NAME_MAX; 339ad7b0368SQu Wenruo else 340ad7b0368SQu Wenruo max_name_len = BTRFS_NAME_LEN; 341ad7b0368SQu Wenruo 342ad7b0368SQu Wenruo /* Name/data length check */ 343ad7b0368SQu Wenruo name_len = btrfs_dir_name_len(leaf, di); 344ad7b0368SQu Wenruo data_len = btrfs_dir_data_len(leaf, di); 345ad7b0368SQu Wenruo if (name_len > max_name_len) { 346d98ced68SDavid Sterba dir_item_err(leaf, slot, 347ad7b0368SQu Wenruo "dir item name len too long, have %u max %u", 348ad7b0368SQu Wenruo name_len, max_name_len); 349ad7b0368SQu Wenruo return -EUCLEAN; 350ad7b0368SQu Wenruo } 3512f659546SQu Wenruo if (name_len + data_len > BTRFS_MAX_XATTR_SIZE(fs_info)) { 352d98ced68SDavid Sterba dir_item_err(leaf, slot, 353ad7b0368SQu Wenruo "dir item name and data len too long, have %u max %u", 354ad7b0368SQu Wenruo name_len + data_len, 3552f659546SQu Wenruo BTRFS_MAX_XATTR_SIZE(fs_info)); 356ad7b0368SQu Wenruo return -EUCLEAN; 357ad7b0368SQu Wenruo } 358ad7b0368SQu Wenruo 359ad7b0368SQu Wenruo if (data_len && dir_type != BTRFS_FT_XATTR) { 360d98ced68SDavid Sterba dir_item_err(leaf, slot, 361ad7b0368SQu Wenruo "dir item with invalid data len, have %u expect 0", 362ad7b0368SQu Wenruo data_len); 363ad7b0368SQu Wenruo return -EUCLEAN; 364ad7b0368SQu Wenruo } 365ad7b0368SQu Wenruo 366ad7b0368SQu Wenruo total_size = sizeof(*di) + name_len + data_len; 367ad7b0368SQu Wenruo 368ad7b0368SQu Wenruo /* header and name/data should not cross item boundary */ 369ad7b0368SQu Wenruo if (cur + total_size > item_size) { 370d98ced68SDavid Sterba dir_item_err(leaf, slot, 371ad7b0368SQu Wenruo "dir item data crosses item boundary, have %u boundary %u", 372ad7b0368SQu Wenruo cur + total_size, item_size); 373ad7b0368SQu Wenruo return -EUCLEAN; 374ad7b0368SQu Wenruo } 375ad7b0368SQu Wenruo 376ad7b0368SQu Wenruo /* 377ad7b0368SQu Wenruo * Special check for XATTR/DIR_ITEM, as key->offset is name 378ad7b0368SQu Wenruo * hash, should match its name 379ad7b0368SQu Wenruo */ 380ad7b0368SQu Wenruo if (key->type == BTRFS_DIR_ITEM_KEY || 381ad7b0368SQu Wenruo key->type == BTRFS_XATTR_ITEM_KEY) { 382e2683fc9SDavid Sterba char namebuf[max(BTRFS_NAME_LEN, XATTR_NAME_MAX)]; 383e2683fc9SDavid Sterba 384ad7b0368SQu Wenruo read_extent_buffer(leaf, namebuf, 385ad7b0368SQu Wenruo (unsigned long)(di + 1), name_len); 386ad7b0368SQu Wenruo name_hash = btrfs_name_hash(namebuf, name_len); 387ad7b0368SQu Wenruo if (key->offset != name_hash) { 388d98ced68SDavid Sterba dir_item_err(leaf, slot, 389ad7b0368SQu Wenruo "name hash mismatch with key, have 0x%016x expect 0x%016llx", 390ad7b0368SQu Wenruo name_hash, key->offset); 391ad7b0368SQu Wenruo return -EUCLEAN; 392ad7b0368SQu Wenruo } 393ad7b0368SQu Wenruo } 394ad7b0368SQu Wenruo cur += total_size; 395ad7b0368SQu Wenruo di = (struct btrfs_dir_item *)((void *)di + total_size); 396ad7b0368SQu Wenruo } 397ad7b0368SQu Wenruo return 0; 398ad7b0368SQu Wenruo } 399ad7b0368SQu Wenruo 4004806bd88SDavid Sterba __printf(3, 4) 401fce466eaSQu Wenruo __cold 4024806bd88SDavid Sterba static void block_group_err(const struct extent_buffer *eb, int slot, 403fce466eaSQu Wenruo const char *fmt, ...) 404fce466eaSQu Wenruo { 4054806bd88SDavid Sterba const struct btrfs_fs_info *fs_info = eb->fs_info; 406fce466eaSQu Wenruo struct btrfs_key key; 407fce466eaSQu Wenruo struct va_format vaf; 408fce466eaSQu Wenruo va_list args; 409fce466eaSQu Wenruo 410fce466eaSQu Wenruo btrfs_item_key_to_cpu(eb, &key, slot); 411fce466eaSQu Wenruo va_start(args, fmt); 412fce466eaSQu Wenruo 413fce466eaSQu Wenruo vaf.fmt = fmt; 414fce466eaSQu Wenruo vaf.va = &args; 415fce466eaSQu Wenruo 416fce466eaSQu Wenruo btrfs_crit(fs_info, 417fce466eaSQu Wenruo "corrupt %s: root=%llu block=%llu slot=%d bg_start=%llu bg_len=%llu, %pV", 418fce466eaSQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 419fce466eaSQu Wenruo btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, 420fce466eaSQu Wenruo key.objectid, key.offset, &vaf); 421fce466eaSQu Wenruo va_end(args); 422fce466eaSQu Wenruo } 423fce466eaSQu Wenruo 424af60ce2bSDavid Sterba static int check_block_group_item(struct extent_buffer *leaf, 425fce466eaSQu Wenruo struct btrfs_key *key, int slot) 426fce466eaSQu Wenruo { 427fce466eaSQu Wenruo struct btrfs_block_group_item bgi; 428fce466eaSQu Wenruo u32 item_size = btrfs_item_size_nr(leaf, slot); 429fce466eaSQu Wenruo u64 flags; 430fce466eaSQu Wenruo u64 type; 431fce466eaSQu Wenruo 432fce466eaSQu Wenruo /* 433fce466eaSQu Wenruo * Here we don't really care about alignment since extent allocator can 43410950929SQu Wenruo * handle it. We care more about the size. 435fce466eaSQu Wenruo */ 43610950929SQu Wenruo if (key->offset == 0) { 4374806bd88SDavid Sterba block_group_err(leaf, slot, 43810950929SQu Wenruo "invalid block group size 0"); 439fce466eaSQu Wenruo return -EUCLEAN; 440fce466eaSQu Wenruo } 441fce466eaSQu Wenruo 442fce466eaSQu Wenruo if (item_size != sizeof(bgi)) { 4434806bd88SDavid Sterba block_group_err(leaf, slot, 444fce466eaSQu Wenruo "invalid item size, have %u expect %zu", 445fce466eaSQu Wenruo item_size, sizeof(bgi)); 446fce466eaSQu Wenruo return -EUCLEAN; 447fce466eaSQu Wenruo } 448fce466eaSQu Wenruo 449fce466eaSQu Wenruo read_extent_buffer(leaf, &bgi, btrfs_item_ptr_offset(leaf, slot), 450fce466eaSQu Wenruo sizeof(bgi)); 451fce466eaSQu Wenruo if (btrfs_block_group_chunk_objectid(&bgi) != 452fce466eaSQu Wenruo BTRFS_FIRST_CHUNK_TREE_OBJECTID) { 4534806bd88SDavid Sterba block_group_err(leaf, slot, 454fce466eaSQu Wenruo "invalid block group chunk objectid, have %llu expect %llu", 455fce466eaSQu Wenruo btrfs_block_group_chunk_objectid(&bgi), 456fce466eaSQu Wenruo BTRFS_FIRST_CHUNK_TREE_OBJECTID); 457fce466eaSQu Wenruo return -EUCLEAN; 458fce466eaSQu Wenruo } 459fce466eaSQu Wenruo 460fce466eaSQu Wenruo if (btrfs_block_group_used(&bgi) > key->offset) { 4614806bd88SDavid Sterba block_group_err(leaf, slot, 462fce466eaSQu Wenruo "invalid block group used, have %llu expect [0, %llu)", 463fce466eaSQu Wenruo btrfs_block_group_used(&bgi), key->offset); 464fce466eaSQu Wenruo return -EUCLEAN; 465fce466eaSQu Wenruo } 466fce466eaSQu Wenruo 467fce466eaSQu Wenruo flags = btrfs_block_group_flags(&bgi); 468fce466eaSQu Wenruo if (hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) > 1) { 4694806bd88SDavid Sterba block_group_err(leaf, slot, 470fce466eaSQu Wenruo "invalid profile flags, have 0x%llx (%lu bits set) expect no more than 1 bit set", 471fce466eaSQu Wenruo flags & BTRFS_BLOCK_GROUP_PROFILE_MASK, 472fce466eaSQu Wenruo hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK)); 473fce466eaSQu Wenruo return -EUCLEAN; 474fce466eaSQu Wenruo } 475fce466eaSQu Wenruo 476fce466eaSQu Wenruo type = flags & BTRFS_BLOCK_GROUP_TYPE_MASK; 477fce466eaSQu Wenruo if (type != BTRFS_BLOCK_GROUP_DATA && 478fce466eaSQu Wenruo type != BTRFS_BLOCK_GROUP_METADATA && 479fce466eaSQu Wenruo type != BTRFS_BLOCK_GROUP_SYSTEM && 480fce466eaSQu Wenruo type != (BTRFS_BLOCK_GROUP_METADATA | 481fce466eaSQu Wenruo BTRFS_BLOCK_GROUP_DATA)) { 4824806bd88SDavid Sterba block_group_err(leaf, slot, 483761333f2SShaokun Zhang "invalid type, have 0x%llx (%lu bits set) expect either 0x%llx, 0x%llx, 0x%llx or 0x%llx", 484fce466eaSQu Wenruo type, hweight64(type), 485fce466eaSQu Wenruo BTRFS_BLOCK_GROUP_DATA, BTRFS_BLOCK_GROUP_METADATA, 486fce466eaSQu Wenruo BTRFS_BLOCK_GROUP_SYSTEM, 487fce466eaSQu Wenruo BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA); 488fce466eaSQu Wenruo return -EUCLEAN; 489fce466eaSQu Wenruo } 490fce466eaSQu Wenruo return 0; 491fce466eaSQu Wenruo } 492fce466eaSQu Wenruo 493d001e4a3SDavid Sterba __printf(4, 5) 494f1140243SQu Wenruo __cold 495d001e4a3SDavid Sterba static void chunk_err(const struct extent_buffer *leaf, 496f1140243SQu Wenruo const struct btrfs_chunk *chunk, u64 logical, 497f1140243SQu Wenruo const char *fmt, ...) 498f1140243SQu Wenruo { 499d001e4a3SDavid Sterba const struct btrfs_fs_info *fs_info = leaf->fs_info; 500f1140243SQu Wenruo bool is_sb; 501f1140243SQu Wenruo struct va_format vaf; 502f1140243SQu Wenruo va_list args; 503f1140243SQu Wenruo int i; 504f1140243SQu Wenruo int slot = -1; 505f1140243SQu Wenruo 506f1140243SQu Wenruo /* Only superblock eb is able to have such small offset */ 507f1140243SQu Wenruo is_sb = (leaf->start == BTRFS_SUPER_INFO_OFFSET); 508f1140243SQu Wenruo 509f1140243SQu Wenruo if (!is_sb) { 510f1140243SQu Wenruo /* 511f1140243SQu Wenruo * Get the slot number by iterating through all slots, this 512f1140243SQu Wenruo * would provide better readability. 513f1140243SQu Wenruo */ 514f1140243SQu Wenruo for (i = 0; i < btrfs_header_nritems(leaf); i++) { 515f1140243SQu Wenruo if (btrfs_item_ptr_offset(leaf, i) == 516f1140243SQu Wenruo (unsigned long)chunk) { 517f1140243SQu Wenruo slot = i; 518f1140243SQu Wenruo break; 519f1140243SQu Wenruo } 520f1140243SQu Wenruo } 521f1140243SQu Wenruo } 522f1140243SQu Wenruo va_start(args, fmt); 523f1140243SQu Wenruo vaf.fmt = fmt; 524f1140243SQu Wenruo vaf.va = &args; 525f1140243SQu Wenruo 526f1140243SQu Wenruo if (is_sb) 527f1140243SQu Wenruo btrfs_crit(fs_info, 528f1140243SQu Wenruo "corrupt superblock syschunk array: chunk_start=%llu, %pV", 529f1140243SQu Wenruo logical, &vaf); 530f1140243SQu Wenruo else 531f1140243SQu Wenruo btrfs_crit(fs_info, 532f1140243SQu Wenruo "corrupt leaf: root=%llu block=%llu slot=%d chunk_start=%llu, %pV", 533f1140243SQu Wenruo BTRFS_CHUNK_TREE_OBJECTID, leaf->start, slot, 534f1140243SQu Wenruo logical, &vaf); 535f1140243SQu Wenruo va_end(args); 536f1140243SQu Wenruo } 537f1140243SQu Wenruo 538ad7b0368SQu Wenruo /* 53982fc28fbSQu Wenruo * The common chunk check which could also work on super block sys chunk array. 54082fc28fbSQu Wenruo * 541bf871c3bSQu Wenruo * Return -EUCLEAN if anything is corrupted. 54282fc28fbSQu Wenruo * Return 0 if everything is OK. 54382fc28fbSQu Wenruo */ 544ddaf1d5aSDavid Sterba int btrfs_check_chunk_valid(struct extent_buffer *leaf, 54582fc28fbSQu Wenruo struct btrfs_chunk *chunk, u64 logical) 54682fc28fbSQu Wenruo { 547ddaf1d5aSDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 54882fc28fbSQu Wenruo u64 length; 54982fc28fbSQu Wenruo u64 stripe_len; 55082fc28fbSQu Wenruo u16 num_stripes; 55182fc28fbSQu Wenruo u16 sub_stripes; 55282fc28fbSQu Wenruo u64 type; 55382fc28fbSQu Wenruo u64 features; 55482fc28fbSQu Wenruo bool mixed = false; 55582fc28fbSQu Wenruo 55682fc28fbSQu Wenruo length = btrfs_chunk_length(leaf, chunk); 55782fc28fbSQu Wenruo stripe_len = btrfs_chunk_stripe_len(leaf, chunk); 55882fc28fbSQu Wenruo num_stripes = btrfs_chunk_num_stripes(leaf, chunk); 55982fc28fbSQu Wenruo sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk); 56082fc28fbSQu Wenruo type = btrfs_chunk_type(leaf, chunk); 56182fc28fbSQu Wenruo 56282fc28fbSQu Wenruo if (!num_stripes) { 563d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 564f1140243SQu Wenruo "invalid chunk num_stripes, have %u", num_stripes); 565bf871c3bSQu Wenruo return -EUCLEAN; 56682fc28fbSQu Wenruo } 56782fc28fbSQu Wenruo if (!IS_ALIGNED(logical, fs_info->sectorsize)) { 568d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 569f1140243SQu Wenruo "invalid chunk logical, have %llu should aligned to %u", 570f1140243SQu Wenruo logical, fs_info->sectorsize); 571bf871c3bSQu Wenruo return -EUCLEAN; 57282fc28fbSQu Wenruo } 57382fc28fbSQu Wenruo if (btrfs_chunk_sector_size(leaf, chunk) != fs_info->sectorsize) { 574d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 575f1140243SQu Wenruo "invalid chunk sectorsize, have %u expect %u", 576f1140243SQu Wenruo btrfs_chunk_sector_size(leaf, chunk), 577f1140243SQu Wenruo fs_info->sectorsize); 578bf871c3bSQu Wenruo return -EUCLEAN; 57982fc28fbSQu Wenruo } 58082fc28fbSQu Wenruo if (!length || !IS_ALIGNED(length, fs_info->sectorsize)) { 581d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 582f1140243SQu Wenruo "invalid chunk length, have %llu", length); 583bf871c3bSQu Wenruo return -EUCLEAN; 58482fc28fbSQu Wenruo } 58582fc28fbSQu Wenruo if (!is_power_of_2(stripe_len) || stripe_len != BTRFS_STRIPE_LEN) { 586d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 587f1140243SQu Wenruo "invalid chunk stripe length: %llu", 58882fc28fbSQu Wenruo stripe_len); 589bf871c3bSQu Wenruo return -EUCLEAN; 59082fc28fbSQu Wenruo } 59182fc28fbSQu Wenruo if (~(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_PROFILE_MASK) & 59282fc28fbSQu Wenruo type) { 593d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 594f1140243SQu Wenruo "unrecognized chunk type: 0x%llx", 59582fc28fbSQu Wenruo ~(BTRFS_BLOCK_GROUP_TYPE_MASK | 59682fc28fbSQu Wenruo BTRFS_BLOCK_GROUP_PROFILE_MASK) & 59782fc28fbSQu Wenruo btrfs_chunk_type(leaf, chunk)); 598bf871c3bSQu Wenruo return -EUCLEAN; 59982fc28fbSQu Wenruo } 60082fc28fbSQu Wenruo 60180e46cf2SQu Wenruo if (!is_power_of_2(type & BTRFS_BLOCK_GROUP_PROFILE_MASK) && 60280e46cf2SQu Wenruo (type & BTRFS_BLOCK_GROUP_PROFILE_MASK) != 0) { 603d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 60480e46cf2SQu Wenruo "invalid chunk profile flag: 0x%llx, expect 0 or 1 bit set", 60580e46cf2SQu Wenruo type & BTRFS_BLOCK_GROUP_PROFILE_MASK); 60680e46cf2SQu Wenruo return -EUCLEAN; 60780e46cf2SQu Wenruo } 60882fc28fbSQu Wenruo if ((type & BTRFS_BLOCK_GROUP_TYPE_MASK) == 0) { 609d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 610f1140243SQu Wenruo "missing chunk type flag, have 0x%llx one bit must be set in 0x%llx", 611f1140243SQu Wenruo type, BTRFS_BLOCK_GROUP_TYPE_MASK); 612bf871c3bSQu Wenruo return -EUCLEAN; 61382fc28fbSQu Wenruo } 61482fc28fbSQu Wenruo 61582fc28fbSQu Wenruo if ((type & BTRFS_BLOCK_GROUP_SYSTEM) && 61682fc28fbSQu Wenruo (type & (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA))) { 617d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 618f1140243SQu Wenruo "system chunk with data or metadata type: 0x%llx", 619f1140243SQu Wenruo type); 620bf871c3bSQu Wenruo return -EUCLEAN; 62182fc28fbSQu Wenruo } 62282fc28fbSQu Wenruo 62382fc28fbSQu Wenruo features = btrfs_super_incompat_flags(fs_info->super_copy); 62482fc28fbSQu Wenruo if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) 62582fc28fbSQu Wenruo mixed = true; 62682fc28fbSQu Wenruo 62782fc28fbSQu Wenruo if (!mixed) { 62882fc28fbSQu Wenruo if ((type & BTRFS_BLOCK_GROUP_METADATA) && 62982fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_DATA)) { 630d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 63182fc28fbSQu Wenruo "mixed chunk type in non-mixed mode: 0x%llx", type); 632bf871c3bSQu Wenruo return -EUCLEAN; 63382fc28fbSQu Wenruo } 63482fc28fbSQu Wenruo } 63582fc28fbSQu Wenruo 63682fc28fbSQu Wenruo if ((type & BTRFS_BLOCK_GROUP_RAID10 && sub_stripes != 2) || 63782fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_RAID1 && num_stripes != 2) || 63882fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_RAID5 && num_stripes < 2) || 63982fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_RAID6 && num_stripes < 3) || 64082fc28fbSQu Wenruo (type & BTRFS_BLOCK_GROUP_DUP && num_stripes != 2) || 64182fc28fbSQu Wenruo ((type & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0 && num_stripes != 1)) { 642d001e4a3SDavid Sterba chunk_err(leaf, chunk, logical, 64382fc28fbSQu Wenruo "invalid num_stripes:sub_stripes %u:%u for profile %llu", 64482fc28fbSQu Wenruo num_stripes, sub_stripes, 64582fc28fbSQu Wenruo type & BTRFS_BLOCK_GROUP_PROFILE_MASK); 646bf871c3bSQu Wenruo return -EUCLEAN; 64782fc28fbSQu Wenruo } 64882fc28fbSQu Wenruo 64982fc28fbSQu Wenruo return 0; 65082fc28fbSQu Wenruo } 65182fc28fbSQu Wenruo 6525617ed80SDavid Sterba __printf(3, 4) 653ab4ba2e1SQu Wenruo __cold 6545617ed80SDavid Sterba static void dev_item_err(const struct extent_buffer *eb, int slot, 655ab4ba2e1SQu Wenruo const char *fmt, ...) 656ab4ba2e1SQu Wenruo { 657ab4ba2e1SQu Wenruo struct btrfs_key key; 658ab4ba2e1SQu Wenruo struct va_format vaf; 659ab4ba2e1SQu Wenruo va_list args; 660ab4ba2e1SQu Wenruo 661ab4ba2e1SQu Wenruo btrfs_item_key_to_cpu(eb, &key, slot); 662ab4ba2e1SQu Wenruo va_start(args, fmt); 663ab4ba2e1SQu Wenruo 664ab4ba2e1SQu Wenruo vaf.fmt = fmt; 665ab4ba2e1SQu Wenruo vaf.va = &args; 666ab4ba2e1SQu Wenruo 6675617ed80SDavid Sterba btrfs_crit(eb->fs_info, 668ab4ba2e1SQu Wenruo "corrupt %s: root=%llu block=%llu slot=%d devid=%llu %pV", 669ab4ba2e1SQu Wenruo btrfs_header_level(eb) == 0 ? "leaf" : "node", 670ab4ba2e1SQu Wenruo btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, 671ab4ba2e1SQu Wenruo key.objectid, &vaf); 672ab4ba2e1SQu Wenruo va_end(args); 673ab4ba2e1SQu Wenruo } 674ab4ba2e1SQu Wenruo 675412a2312SDavid Sterba static int check_dev_item(struct extent_buffer *leaf, 676ab4ba2e1SQu Wenruo struct btrfs_key *key, int slot) 677ab4ba2e1SQu Wenruo { 678412a2312SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 679ab4ba2e1SQu Wenruo struct btrfs_dev_item *ditem; 680ab4ba2e1SQu Wenruo u64 max_devid = max(BTRFS_MAX_DEVS(fs_info), BTRFS_MAX_DEVS_SYS_CHUNK); 681ab4ba2e1SQu Wenruo 682ab4ba2e1SQu Wenruo if (key->objectid != BTRFS_DEV_ITEMS_OBJECTID) { 6835617ed80SDavid Sterba dev_item_err(leaf, slot, 684ab4ba2e1SQu Wenruo "invalid objectid: has=%llu expect=%llu", 685ab4ba2e1SQu Wenruo key->objectid, BTRFS_DEV_ITEMS_OBJECTID); 686ab4ba2e1SQu Wenruo return -EUCLEAN; 687ab4ba2e1SQu Wenruo } 688ab4ba2e1SQu Wenruo if (key->offset > max_devid) { 6895617ed80SDavid Sterba dev_item_err(leaf, slot, 690ab4ba2e1SQu Wenruo "invalid devid: has=%llu expect=[0, %llu]", 691ab4ba2e1SQu Wenruo key->offset, max_devid); 692ab4ba2e1SQu Wenruo return -EUCLEAN; 693ab4ba2e1SQu Wenruo } 694ab4ba2e1SQu Wenruo ditem = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item); 695ab4ba2e1SQu Wenruo if (btrfs_device_id(leaf, ditem) != key->offset) { 6965617ed80SDavid Sterba dev_item_err(leaf, slot, 697ab4ba2e1SQu Wenruo "devid mismatch: key has=%llu item has=%llu", 698ab4ba2e1SQu Wenruo key->offset, btrfs_device_id(leaf, ditem)); 699ab4ba2e1SQu Wenruo return -EUCLEAN; 700ab4ba2e1SQu Wenruo } 701ab4ba2e1SQu Wenruo 702ab4ba2e1SQu Wenruo /* 703ab4ba2e1SQu Wenruo * For device total_bytes, we don't have reliable way to check it, as 704ab4ba2e1SQu Wenruo * it can be 0 for device removal. Device size check can only be done 705ab4ba2e1SQu Wenruo * by dev extents check. 706ab4ba2e1SQu Wenruo */ 707ab4ba2e1SQu Wenruo if (btrfs_device_bytes_used(leaf, ditem) > 708ab4ba2e1SQu Wenruo btrfs_device_total_bytes(leaf, ditem)) { 7095617ed80SDavid Sterba dev_item_err(leaf, slot, 710ab4ba2e1SQu Wenruo "invalid bytes used: have %llu expect [0, %llu]", 711ab4ba2e1SQu Wenruo btrfs_device_bytes_used(leaf, ditem), 712ab4ba2e1SQu Wenruo btrfs_device_total_bytes(leaf, ditem)); 713ab4ba2e1SQu Wenruo return -EUCLEAN; 714ab4ba2e1SQu Wenruo } 715ab4ba2e1SQu Wenruo /* 716ab4ba2e1SQu Wenruo * Remaining members like io_align/type/gen/dev_group aren't really 717ab4ba2e1SQu Wenruo * utilized. Skip them to make later usage of them easier. 718ab4ba2e1SQu Wenruo */ 719ab4ba2e1SQu Wenruo return 0; 720ab4ba2e1SQu Wenruo } 721ab4ba2e1SQu Wenruo 722496245caSQu Wenruo /* Inode item error output has the same format as dir_item_err() */ 723496245caSQu Wenruo #define inode_item_err(fs_info, eb, slot, fmt, ...) \ 724d98ced68SDavid Sterba dir_item_err(eb, slot, fmt, __VA_ARGS__) 725496245caSQu Wenruo 72639e57f49SDavid Sterba static int check_inode_item(struct extent_buffer *leaf, 727496245caSQu Wenruo struct btrfs_key *key, int slot) 728496245caSQu Wenruo { 72939e57f49SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 730496245caSQu Wenruo struct btrfs_inode_item *iitem; 731496245caSQu Wenruo u64 super_gen = btrfs_super_generation(fs_info->super_copy); 732496245caSQu Wenruo u32 valid_mask = (S_IFMT | S_ISUID | S_ISGID | S_ISVTX | 0777); 733496245caSQu Wenruo u32 mode; 734496245caSQu Wenruo 735496245caSQu Wenruo if ((key->objectid < BTRFS_FIRST_FREE_OBJECTID || 736496245caSQu Wenruo key->objectid > BTRFS_LAST_FREE_OBJECTID) && 737496245caSQu Wenruo key->objectid != BTRFS_ROOT_TREE_DIR_OBJECTID && 738496245caSQu Wenruo key->objectid != BTRFS_FREE_INO_OBJECTID) { 73986a6be3aSDavid Sterba generic_err(leaf, slot, 740496245caSQu Wenruo "invalid key objectid: has %llu expect %llu or [%llu, %llu] or %llu", 741496245caSQu Wenruo key->objectid, BTRFS_ROOT_TREE_DIR_OBJECTID, 742496245caSQu Wenruo BTRFS_FIRST_FREE_OBJECTID, 743496245caSQu Wenruo BTRFS_LAST_FREE_OBJECTID, 744496245caSQu Wenruo BTRFS_FREE_INO_OBJECTID); 745496245caSQu Wenruo return -EUCLEAN; 746496245caSQu Wenruo } 747496245caSQu Wenruo if (key->offset != 0) { 748496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 749496245caSQu Wenruo "invalid key offset: has %llu expect 0", 750496245caSQu Wenruo key->offset); 751496245caSQu Wenruo return -EUCLEAN; 752496245caSQu Wenruo } 753496245caSQu Wenruo iitem = btrfs_item_ptr(leaf, slot, struct btrfs_inode_item); 754496245caSQu Wenruo 755496245caSQu Wenruo /* Here we use super block generation + 1 to handle log tree */ 756496245caSQu Wenruo if (btrfs_inode_generation(leaf, iitem) > super_gen + 1) { 757496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 758496245caSQu Wenruo "invalid inode generation: has %llu expect (0, %llu]", 759496245caSQu Wenruo btrfs_inode_generation(leaf, iitem), 760496245caSQu Wenruo super_gen + 1); 761496245caSQu Wenruo return -EUCLEAN; 762496245caSQu Wenruo } 763496245caSQu Wenruo /* Note for ROOT_TREE_DIR_ITEM, mkfs could set its transid 0 */ 764496245caSQu Wenruo if (btrfs_inode_transid(leaf, iitem) > super_gen + 1) { 765496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 766496245caSQu Wenruo "invalid inode generation: has %llu expect [0, %llu]", 767496245caSQu Wenruo btrfs_inode_transid(leaf, iitem), super_gen + 1); 768496245caSQu Wenruo return -EUCLEAN; 769496245caSQu Wenruo } 770496245caSQu Wenruo 771496245caSQu Wenruo /* 772496245caSQu Wenruo * For size and nbytes it's better not to be too strict, as for dir 773496245caSQu Wenruo * item its size/nbytes can easily get wrong, but doesn't affect 774496245caSQu Wenruo * anything in the fs. So here we skip the check. 775496245caSQu Wenruo */ 776496245caSQu Wenruo mode = btrfs_inode_mode(leaf, iitem); 777496245caSQu Wenruo if (mode & ~valid_mask) { 778496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 779496245caSQu Wenruo "unknown mode bit detected: 0x%x", 780496245caSQu Wenruo mode & ~valid_mask); 781496245caSQu Wenruo return -EUCLEAN; 782496245caSQu Wenruo } 783496245caSQu Wenruo 784496245caSQu Wenruo /* 785496245caSQu Wenruo * S_IFMT is not bit mapped so we can't completely rely on is_power_of_2, 786496245caSQu Wenruo * but is_power_of_2() can save us from checking FIFO/CHR/DIR/REG. 787496245caSQu Wenruo * Only needs to check BLK, LNK and SOCKS 788496245caSQu Wenruo */ 789496245caSQu Wenruo if (!is_power_of_2(mode & S_IFMT)) { 790496245caSQu Wenruo if (!S_ISLNK(mode) && !S_ISBLK(mode) && !S_ISSOCK(mode)) { 791496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 792496245caSQu Wenruo "invalid mode: has 0%o expect valid S_IF* bit(s)", 793496245caSQu Wenruo mode & S_IFMT); 794496245caSQu Wenruo return -EUCLEAN; 795496245caSQu Wenruo } 796496245caSQu Wenruo } 797496245caSQu Wenruo if (S_ISDIR(mode) && btrfs_inode_nlink(leaf, iitem) > 1) { 798496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 799496245caSQu Wenruo "invalid nlink: has %u expect no more than 1 for dir", 800496245caSQu Wenruo btrfs_inode_nlink(leaf, iitem)); 801496245caSQu Wenruo return -EUCLEAN; 802496245caSQu Wenruo } 803496245caSQu Wenruo if (btrfs_inode_flags(leaf, iitem) & ~BTRFS_INODE_FLAG_MASK) { 804496245caSQu Wenruo inode_item_err(fs_info, leaf, slot, 805496245caSQu Wenruo "unknown flags detected: 0x%llx", 806496245caSQu Wenruo btrfs_inode_flags(leaf, iitem) & 807496245caSQu Wenruo ~BTRFS_INODE_FLAG_MASK); 808496245caSQu Wenruo return -EUCLEAN; 809496245caSQu Wenruo } 810496245caSQu Wenruo return 0; 811496245caSQu Wenruo } 812496245caSQu Wenruo 81382fc28fbSQu Wenruo /* 814557ea5ddSQu Wenruo * Common point to switch the item-specific validation. 815557ea5ddSQu Wenruo */ 8160076bc89SDavid Sterba static int check_leaf_item(struct extent_buffer *leaf, 817*4e9845efSFilipe Manana struct btrfs_key *key, int slot, 818*4e9845efSFilipe Manana struct btrfs_key *prev_key) 819557ea5ddSQu Wenruo { 820557ea5ddSQu Wenruo int ret = 0; 821075cb3c7SQu Wenruo struct btrfs_chunk *chunk; 822557ea5ddSQu Wenruo 823557ea5ddSQu Wenruo switch (key->type) { 824557ea5ddSQu Wenruo case BTRFS_EXTENT_DATA_KEY: 825*4e9845efSFilipe Manana ret = check_extent_data_item(leaf, key, slot, prev_key); 826557ea5ddSQu Wenruo break; 827557ea5ddSQu Wenruo case BTRFS_EXTENT_CSUM_KEY: 82868128ce7SDavid Sterba ret = check_csum_item(leaf, key, slot); 829557ea5ddSQu Wenruo break; 830ad7b0368SQu Wenruo case BTRFS_DIR_ITEM_KEY: 831ad7b0368SQu Wenruo case BTRFS_DIR_INDEX_KEY: 832ad7b0368SQu Wenruo case BTRFS_XATTR_ITEM_KEY: 833ce4252c0SDavid Sterba ret = check_dir_item(leaf, key, slot); 834ad7b0368SQu Wenruo break; 835fce466eaSQu Wenruo case BTRFS_BLOCK_GROUP_ITEM_KEY: 836af60ce2bSDavid Sterba ret = check_block_group_item(leaf, key, slot); 837fce466eaSQu Wenruo break; 838075cb3c7SQu Wenruo case BTRFS_CHUNK_ITEM_KEY: 839075cb3c7SQu Wenruo chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); 840ddaf1d5aSDavid Sterba ret = btrfs_check_chunk_valid(leaf, chunk, key->offset); 841075cb3c7SQu Wenruo break; 842ab4ba2e1SQu Wenruo case BTRFS_DEV_ITEM_KEY: 843412a2312SDavid Sterba ret = check_dev_item(leaf, key, slot); 844ab4ba2e1SQu Wenruo break; 845496245caSQu Wenruo case BTRFS_INODE_ITEM_KEY: 84639e57f49SDavid Sterba ret = check_inode_item(leaf, key, slot); 847496245caSQu Wenruo break; 848557ea5ddSQu Wenruo } 849557ea5ddSQu Wenruo return ret; 850557ea5ddSQu Wenruo } 851557ea5ddSQu Wenruo 852e2ccd361SDavid Sterba static int check_leaf(struct extent_buffer *leaf, bool check_item_data) 853557ea5ddSQu Wenruo { 854e2ccd361SDavid Sterba struct btrfs_fs_info *fs_info = leaf->fs_info; 855557ea5ddSQu Wenruo /* No valid key type is 0, so all key should be larger than this key */ 856557ea5ddSQu Wenruo struct btrfs_key prev_key = {0, 0, 0}; 857557ea5ddSQu Wenruo struct btrfs_key key; 858557ea5ddSQu Wenruo u32 nritems = btrfs_header_nritems(leaf); 859557ea5ddSQu Wenruo int slot; 860557ea5ddSQu Wenruo 861f556faa4SQu Wenruo if (btrfs_header_level(leaf) != 0) { 86286a6be3aSDavid Sterba generic_err(leaf, 0, 863f556faa4SQu Wenruo "invalid level for leaf, have %d expect 0", 864f556faa4SQu Wenruo btrfs_header_level(leaf)); 865f556faa4SQu Wenruo return -EUCLEAN; 866f556faa4SQu Wenruo } 867f556faa4SQu Wenruo 868557ea5ddSQu Wenruo /* 869557ea5ddSQu Wenruo * Extent buffers from a relocation tree have a owner field that 870557ea5ddSQu Wenruo * corresponds to the subvolume tree they are based on. So just from an 871557ea5ddSQu Wenruo * extent buffer alone we can not find out what is the id of the 872557ea5ddSQu Wenruo * corresponding subvolume tree, so we can not figure out if the extent 873557ea5ddSQu Wenruo * buffer corresponds to the root of the relocation tree or not. So 874557ea5ddSQu Wenruo * skip this check for relocation trees. 875557ea5ddSQu Wenruo */ 876557ea5ddSQu Wenruo if (nritems == 0 && !btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_RELOC)) { 877ba480dd4SQu Wenruo u64 owner = btrfs_header_owner(leaf); 878557ea5ddSQu Wenruo 879ba480dd4SQu Wenruo /* These trees must never be empty */ 880ba480dd4SQu Wenruo if (owner == BTRFS_ROOT_TREE_OBJECTID || 881ba480dd4SQu Wenruo owner == BTRFS_CHUNK_TREE_OBJECTID || 882ba480dd4SQu Wenruo owner == BTRFS_EXTENT_TREE_OBJECTID || 883ba480dd4SQu Wenruo owner == BTRFS_DEV_TREE_OBJECTID || 884ba480dd4SQu Wenruo owner == BTRFS_FS_TREE_OBJECTID || 885ba480dd4SQu Wenruo owner == BTRFS_DATA_RELOC_TREE_OBJECTID) { 88686a6be3aSDavid Sterba generic_err(leaf, 0, 887ba480dd4SQu Wenruo "invalid root, root %llu must never be empty", 888ba480dd4SQu Wenruo owner); 889ba480dd4SQu Wenruo return -EUCLEAN; 890ba480dd4SQu Wenruo } 891557ea5ddSQu Wenruo return 0; 892557ea5ddSQu Wenruo } 893557ea5ddSQu Wenruo 894557ea5ddSQu Wenruo if (nritems == 0) 895557ea5ddSQu Wenruo return 0; 896557ea5ddSQu Wenruo 897557ea5ddSQu Wenruo /* 898557ea5ddSQu Wenruo * Check the following things to make sure this is a good leaf, and 899557ea5ddSQu Wenruo * leaf users won't need to bother with similar sanity checks: 900557ea5ddSQu Wenruo * 901557ea5ddSQu Wenruo * 1) key ordering 902557ea5ddSQu Wenruo * 2) item offset and size 903557ea5ddSQu Wenruo * No overlap, no hole, all inside the leaf. 904557ea5ddSQu Wenruo * 3) item content 905557ea5ddSQu Wenruo * If possible, do comprehensive sanity check. 906557ea5ddSQu Wenruo * NOTE: All checks must only rely on the item data itself. 907557ea5ddSQu Wenruo */ 908557ea5ddSQu Wenruo for (slot = 0; slot < nritems; slot++) { 909557ea5ddSQu Wenruo u32 item_end_expected; 910557ea5ddSQu Wenruo int ret; 911557ea5ddSQu Wenruo 912557ea5ddSQu Wenruo btrfs_item_key_to_cpu(leaf, &key, slot); 913557ea5ddSQu Wenruo 914557ea5ddSQu Wenruo /* Make sure the keys are in the right order */ 915557ea5ddSQu Wenruo if (btrfs_comp_cpu_keys(&prev_key, &key) >= 0) { 91686a6be3aSDavid Sterba generic_err(leaf, slot, 917478d01b3SQu Wenruo "bad key order, prev (%llu %u %llu) current (%llu %u %llu)", 918478d01b3SQu Wenruo prev_key.objectid, prev_key.type, 919478d01b3SQu Wenruo prev_key.offset, key.objectid, key.type, 920478d01b3SQu Wenruo key.offset); 921557ea5ddSQu Wenruo return -EUCLEAN; 922557ea5ddSQu Wenruo } 923557ea5ddSQu Wenruo 924557ea5ddSQu Wenruo /* 925557ea5ddSQu Wenruo * Make sure the offset and ends are right, remember that the 926557ea5ddSQu Wenruo * item data starts at the end of the leaf and grows towards the 927557ea5ddSQu Wenruo * front. 928557ea5ddSQu Wenruo */ 929557ea5ddSQu Wenruo if (slot == 0) 930557ea5ddSQu Wenruo item_end_expected = BTRFS_LEAF_DATA_SIZE(fs_info); 931557ea5ddSQu Wenruo else 932557ea5ddSQu Wenruo item_end_expected = btrfs_item_offset_nr(leaf, 933557ea5ddSQu Wenruo slot - 1); 934557ea5ddSQu Wenruo if (btrfs_item_end_nr(leaf, slot) != item_end_expected) { 93586a6be3aSDavid Sterba generic_err(leaf, slot, 936478d01b3SQu Wenruo "unexpected item end, have %u expect %u", 937478d01b3SQu Wenruo btrfs_item_end_nr(leaf, slot), 938478d01b3SQu Wenruo item_end_expected); 939557ea5ddSQu Wenruo return -EUCLEAN; 940557ea5ddSQu Wenruo } 941557ea5ddSQu Wenruo 942557ea5ddSQu Wenruo /* 943557ea5ddSQu Wenruo * Check to make sure that we don't point outside of the leaf, 944557ea5ddSQu Wenruo * just in case all the items are consistent to each other, but 945557ea5ddSQu Wenruo * all point outside of the leaf. 946557ea5ddSQu Wenruo */ 947557ea5ddSQu Wenruo if (btrfs_item_end_nr(leaf, slot) > 948557ea5ddSQu Wenruo BTRFS_LEAF_DATA_SIZE(fs_info)) { 94986a6be3aSDavid Sterba generic_err(leaf, slot, 950478d01b3SQu Wenruo "slot end outside of leaf, have %u expect range [0, %u]", 951478d01b3SQu Wenruo btrfs_item_end_nr(leaf, slot), 952478d01b3SQu Wenruo BTRFS_LEAF_DATA_SIZE(fs_info)); 953557ea5ddSQu Wenruo return -EUCLEAN; 954557ea5ddSQu Wenruo } 955557ea5ddSQu Wenruo 956557ea5ddSQu Wenruo /* Also check if the item pointer overlaps with btrfs item. */ 957557ea5ddSQu Wenruo if (btrfs_item_nr_offset(slot) + sizeof(struct btrfs_item) > 958557ea5ddSQu Wenruo btrfs_item_ptr_offset(leaf, slot)) { 95986a6be3aSDavid Sterba generic_err(leaf, slot, 960478d01b3SQu Wenruo "slot overlaps with its data, item end %lu data start %lu", 961478d01b3SQu Wenruo btrfs_item_nr_offset(slot) + 962478d01b3SQu Wenruo sizeof(struct btrfs_item), 963478d01b3SQu Wenruo btrfs_item_ptr_offset(leaf, slot)); 964557ea5ddSQu Wenruo return -EUCLEAN; 965557ea5ddSQu Wenruo } 966557ea5ddSQu Wenruo 96769fc6cbbSQu Wenruo if (check_item_data) { 96869fc6cbbSQu Wenruo /* 96969fc6cbbSQu Wenruo * Check if the item size and content meet other 97069fc6cbbSQu Wenruo * criteria 97169fc6cbbSQu Wenruo */ 972*4e9845efSFilipe Manana ret = check_leaf_item(leaf, &key, slot, &prev_key); 973557ea5ddSQu Wenruo if (ret < 0) 974557ea5ddSQu Wenruo return ret; 97569fc6cbbSQu Wenruo } 976557ea5ddSQu Wenruo 977557ea5ddSQu Wenruo prev_key.objectid = key.objectid; 978557ea5ddSQu Wenruo prev_key.type = key.type; 979557ea5ddSQu Wenruo prev_key.offset = key.offset; 980557ea5ddSQu Wenruo } 981557ea5ddSQu Wenruo 982557ea5ddSQu Wenruo return 0; 983557ea5ddSQu Wenruo } 984557ea5ddSQu Wenruo 9851c4360eeSDavid Sterba int btrfs_check_leaf_full(struct extent_buffer *leaf) 98669fc6cbbSQu Wenruo { 987e2ccd361SDavid Sterba return check_leaf(leaf, true); 98869fc6cbbSQu Wenruo } 98902529d7aSQu Wenruo ALLOW_ERROR_INJECTION(btrfs_check_leaf_full, ERRNO); 99069fc6cbbSQu Wenruo 991cfdaad5eSDavid Sterba int btrfs_check_leaf_relaxed(struct extent_buffer *leaf) 9922f659546SQu Wenruo { 993e2ccd361SDavid Sterba return check_leaf(leaf, false); 9942f659546SQu Wenruo } 9952f659546SQu Wenruo 996813fd1dcSDavid Sterba int btrfs_check_node(struct extent_buffer *node) 997557ea5ddSQu Wenruo { 998813fd1dcSDavid Sterba struct btrfs_fs_info *fs_info = node->fs_info; 999557ea5ddSQu Wenruo unsigned long nr = btrfs_header_nritems(node); 1000557ea5ddSQu Wenruo struct btrfs_key key, next_key; 1001557ea5ddSQu Wenruo int slot; 1002f556faa4SQu Wenruo int level = btrfs_header_level(node); 1003557ea5ddSQu Wenruo u64 bytenr; 1004557ea5ddSQu Wenruo int ret = 0; 1005557ea5ddSQu Wenruo 1006f556faa4SQu Wenruo if (level <= 0 || level >= BTRFS_MAX_LEVEL) { 100786a6be3aSDavid Sterba generic_err(node, 0, 1008f556faa4SQu Wenruo "invalid level for node, have %d expect [1, %d]", 1009f556faa4SQu Wenruo level, BTRFS_MAX_LEVEL - 1); 1010f556faa4SQu Wenruo return -EUCLEAN; 1011f556faa4SQu Wenruo } 10122f659546SQu Wenruo if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(fs_info)) { 10132f659546SQu Wenruo btrfs_crit(fs_info, 1014bba4f298SQu Wenruo "corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%u]", 10152f659546SQu Wenruo btrfs_header_owner(node), node->start, 1016bba4f298SQu Wenruo nr == 0 ? "small" : "large", nr, 10172f659546SQu Wenruo BTRFS_NODEPTRS_PER_BLOCK(fs_info)); 1018bba4f298SQu Wenruo return -EUCLEAN; 1019557ea5ddSQu Wenruo } 1020557ea5ddSQu Wenruo 1021557ea5ddSQu Wenruo for (slot = 0; slot < nr - 1; slot++) { 1022557ea5ddSQu Wenruo bytenr = btrfs_node_blockptr(node, slot); 1023557ea5ddSQu Wenruo btrfs_node_key_to_cpu(node, &key, slot); 1024557ea5ddSQu Wenruo btrfs_node_key_to_cpu(node, &next_key, slot + 1); 1025557ea5ddSQu Wenruo 1026557ea5ddSQu Wenruo if (!bytenr) { 102786a6be3aSDavid Sterba generic_err(node, slot, 1028bba4f298SQu Wenruo "invalid NULL node pointer"); 1029bba4f298SQu Wenruo ret = -EUCLEAN; 1030bba4f298SQu Wenruo goto out; 1031bba4f298SQu Wenruo } 10322f659546SQu Wenruo if (!IS_ALIGNED(bytenr, fs_info->sectorsize)) { 103386a6be3aSDavid Sterba generic_err(node, slot, 1034bba4f298SQu Wenruo "unaligned pointer, have %llu should be aligned to %u", 10352f659546SQu Wenruo bytenr, fs_info->sectorsize); 1036bba4f298SQu Wenruo ret = -EUCLEAN; 1037557ea5ddSQu Wenruo goto out; 1038557ea5ddSQu Wenruo } 1039557ea5ddSQu Wenruo 1040557ea5ddSQu Wenruo if (btrfs_comp_cpu_keys(&key, &next_key) >= 0) { 104186a6be3aSDavid Sterba generic_err(node, slot, 1042bba4f298SQu Wenruo "bad key order, current (%llu %u %llu) next (%llu %u %llu)", 1043bba4f298SQu Wenruo key.objectid, key.type, key.offset, 1044bba4f298SQu Wenruo next_key.objectid, next_key.type, 1045bba4f298SQu Wenruo next_key.offset); 1046bba4f298SQu Wenruo ret = -EUCLEAN; 1047557ea5ddSQu Wenruo goto out; 1048557ea5ddSQu Wenruo } 1049557ea5ddSQu Wenruo } 1050557ea5ddSQu Wenruo out: 1051557ea5ddSQu Wenruo return ret; 1052557ea5ddSQu Wenruo } 105302529d7aSQu Wenruo ALLOW_ERROR_INJECTION(btrfs_check_node, ERRNO); 1054