fprintf(stderr, ", bad file extent");
if (errors & I_ERR_FILE_EXTENT_OVERLAP)
fprintf(stderr, ", file extent overlap");
+ if (errors & I_ERR_FILE_EXTENT_TOO_LARGE)
+ fprintf(stderr, ", inline file extent too large");
if (errors & I_ERR_FILE_EXTENT_DISCOUNT)
fprintf(stderr, ", file extent discount");
if (errors & I_ERR_DIR_ISIZE_WRONG)
u64 disk_bytenr = 0;
u64 extent_offset = 0;
u64 mask = root->fs_info->sectorsize - 1;
+ u32 max_inline_size = min_t(u32, mask,
+ BTRFS_MAX_INLINE_DATA_SIZE(root->fs_info));
int extent_type;
int ret;
extent_type = btrfs_file_extent_type(eb, fi);
if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
+ u8 compression = btrfs_file_extent_compression(eb, fi);
+ struct btrfs_item *item = btrfs_item_nr(slot);
+
num_bytes = btrfs_file_extent_inline_len(eb, slot, fi);
if (num_bytes == 0)
rec->errors |= I_ERR_BAD_FILE_EXTENT;
+ if (compression) {
+ if (btrfs_file_extent_inline_item_len(eb, item) >
+ max_inline_size ||
+ num_bytes > root->fs_info->sectorsize)
+ rec->errors |= I_ERR_FILE_EXTENT_TOO_LARGE;
+ } else {
+ if (num_bytes > max_inline_size)
+ rec->errors |= I_ERR_FILE_EXTENT_TOO_LARGE;
+ }
rec->found_size += num_bytes;
num_bytes = (num_bytes + mask) & ~mask;
} else if (extent_type == BTRFS_FILE_EXTENT_REG ||
if (found < num_bytes)
rec->some_csum_missing = 1;
} else if (extent_type == BTRFS_FILE_EXTENT_PREALLOC) {
- if (found > 0)
- rec->errors |= I_ERR_ODD_CSUM_ITEM;
+ if (found > 0) {
+ ret = check_prealloc_extent_written(root->fs_info,
+ disk_bytenr,
+ num_bytes);
+ if (ret < 0)
+ return ret;
+ if (ret == 0)
+ rec->errors |= I_ERR_ODD_CSUM_ITEM;
+ }
}
}
return 0;
int ret;
u64 data_len;
unsigned long leaf_offset;
+ bool verify_csum = !!check_data_csum;
root = root->fs_info->csum_root;
if (!extent_buffer_uptodate(root->node)) {
path.slots[0]--;
ret = 0;
+ /*
+ * For metadata dump (btrfs-image) all data is wiped so verifying data
+ * csum is meaningless and will always report csum error.
+ */
+ if (check_data_csum && (btrfs_super_flags(root->fs_info->super_copy) &
+ (BTRFS_SUPER_FLAG_METADUMP | BTRFS_SUPER_FLAG_METADUMP_V2))) {
+ printf("skip data csum verification for metadata dump\n");
+ verify_csum = false;
+ }
+
while (1) {
if (path.slots[0] >= btrfs_header_nritems(path.nodes[0])) {
ret = btrfs_next_leaf(root, &path);
data_len = (btrfs_item_size_nr(leaf, path.slots[0]) /
csum_size) * root->fs_info->sectorsize;
- if (!check_data_csum)
+ if (!verify_csum)
goto skip_csum_check;
leaf_offset = btrfs_item_ptr_offset(leaf, path.slots[0]);
ret = check_extent_csums(root, key.offset, data_len,
goto out;
if (btrfs_is_leaf(buf)) {
- btree_space_waste += btrfs_leaf_free_space(root, buf);
+ btree_space_waste += btrfs_leaf_free_space(fs_info, buf);
for (i = 0; i < nritems; i++) {
struct btrfs_file_extent_item *fi;
}
} else {
int level;
- struct btrfs_key first_key;
-
- first_key.objectid = 0;
- if (nritems > 0)
- btrfs_item_key_to_cpu(buf, &first_key, 0);
level = btrfs_header_level(buf);
for (i = 0; i < nritems; i++) {
struct extent_record tmpl;