Btrfs: make tree checker detect checksum items with overlapping ranges
commitad1d8c4399
upstream. Having checksum items, either on the checksums tree or in a log tree, that represent ranges that overlap each other is a sign of a corruption. Such case confuses the checksum lookup code and can result in not being able to find checksums or find stale checksums. So add a check for such case. This is motivated by a recent fix for a case where a log tree had checksum items covering ranges that overlap each other due to extent cloning, and resulted in missing checksums after replaying the log tree. It also helps detect past issues such as stale and outdated checksums due to overlapping, commit27b9a8122f
("Btrfs: fix csum tree corruption, duplicate and outdated checksums"). CC: stable@vger.kernel.org # 4.4+ Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: David Sterba <dsterba@suse.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
e3fb5bb7eb
commit
2bfffc24da
|
@ -243,7 +243,7 @@ static int check_extent_data_item(struct extent_buffer *leaf,
|
|||
}
|
||||
|
||||
static int check_csum_item(struct extent_buffer *leaf, struct btrfs_key *key,
|
||||
int slot)
|
||||
int slot, struct btrfs_key *prev_key)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = leaf->fs_info;
|
||||
u32 sectorsize = fs_info->sectorsize;
|
||||
|
@ -267,6 +267,20 @@ static int check_csum_item(struct extent_buffer *leaf, struct btrfs_key *key,
|
|||
btrfs_item_size_nr(leaf, slot), csumsize);
|
||||
return -EUCLEAN;
|
||||
}
|
||||
if (slot > 0 && prev_key->type == BTRFS_EXTENT_CSUM_KEY) {
|
||||
u64 prev_csum_end;
|
||||
u32 prev_item_size;
|
||||
|
||||
prev_item_size = btrfs_item_size_nr(leaf, slot - 1);
|
||||
prev_csum_end = (prev_item_size / csumsize) * sectorsize;
|
||||
prev_csum_end += prev_key->offset;
|
||||
if (prev_csum_end > key->offset) {
|
||||
generic_err(leaf, slot - 1,
|
||||
"csum end range (%llu) goes beyond the start range (%llu) of the next csum item",
|
||||
prev_csum_end, key->offset);
|
||||
return -EUCLEAN;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1239,7 +1253,7 @@ static int check_leaf_item(struct extent_buffer *leaf,
|
|||
ret = check_extent_data_item(leaf, key, slot, prev_key);
|
||||
break;
|
||||
case BTRFS_EXTENT_CSUM_KEY:
|
||||
ret = check_csum_item(leaf, key, slot);
|
||||
ret = check_csum_item(leaf, key, slot, prev_key);
|
||||
break;
|
||||
case BTRFS_DIR_ITEM_KEY:
|
||||
case BTRFS_DIR_INDEX_KEY:
|
||||
|
|
Loading…
Reference in New Issue