Skip to content

Commit 899b7f6

Browse files
josefbacikkdave
authored andcommitted
btrfs: tree-checker: check for overlapping extent items
We're seeing a weird problem in production where we have overlapping extent items in the extent tree. It's unclear where these are coming from, and in debugging we realized there's no check in the tree checker for this sort of problem. Add a check to the tree-checker to make sure that the extents do not overlap each other. Reviewed-by: Qu Wenruo <[email protected]> Signed-off-by: Josef Bacik <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 769030e commit 899b7f6

File tree

1 file changed

+23
-2
lines changed

1 file changed

+23
-2
lines changed

fs/btrfs/tree-checker.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,7 +1233,8 @@ static void extent_err(const struct extent_buffer *eb, int slot,
12331233
}
12341234

12351235
static int check_extent_item(struct extent_buffer *leaf,
1236-
struct btrfs_key *key, int slot)
1236+
struct btrfs_key *key, int slot,
1237+
struct btrfs_key *prev_key)
12371238
{
12381239
struct btrfs_fs_info *fs_info = leaf->fs_info;
12391240
struct btrfs_extent_item *ei;
@@ -1453,6 +1454,26 @@ static int check_extent_item(struct extent_buffer *leaf,
14531454
total_refs, inline_refs);
14541455
return -EUCLEAN;
14551456
}
1457+
1458+
if ((prev_key->type == BTRFS_EXTENT_ITEM_KEY) ||
1459+
(prev_key->type == BTRFS_METADATA_ITEM_KEY)) {
1460+
u64 prev_end = prev_key->objectid;
1461+
1462+
if (prev_key->type == BTRFS_METADATA_ITEM_KEY)
1463+
prev_end += fs_info->nodesize;
1464+
else
1465+
prev_end += prev_key->offset;
1466+
1467+
if (unlikely(prev_end > key->objectid)) {
1468+
extent_err(leaf, slot,
1469+
"previous extent [%llu %u %llu] overlaps current extent [%llu %u %llu]",
1470+
prev_key->objectid, prev_key->type,
1471+
prev_key->offset, key->objectid, key->type,
1472+
key->offset);
1473+
return -EUCLEAN;
1474+
}
1475+
}
1476+
14561477
return 0;
14571478
}
14581479

@@ -1621,7 +1642,7 @@ static int check_leaf_item(struct extent_buffer *leaf,
16211642
break;
16221643
case BTRFS_EXTENT_ITEM_KEY:
16231644
case BTRFS_METADATA_ITEM_KEY:
1624-
ret = check_extent_item(leaf, key, slot);
1645+
ret = check_extent_item(leaf, key, slot, prev_key);
16251646
break;
16261647
case BTRFS_TREE_BLOCK_REF_KEY:
16271648
case BTRFS_SHARED_DATA_REF_KEY:

0 commit comments

Comments
 (0)