diff options
Diffstat (limited to 'fs/btrfs/tree-checker.c')
| -rw-r--r-- | fs/btrfs/tree-checker.c | 25 | 
1 files changed, 23 insertions, 2 deletions
diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c index 9e0e0ae2288c..43f905ab0a18 100644 --- a/fs/btrfs/tree-checker.c +++ b/fs/btrfs/tree-checker.c @@ -1233,7 +1233,8 @@ static void extent_err(const struct extent_buffer *eb, int slot,  }  static int check_extent_item(struct extent_buffer *leaf, -			     struct btrfs_key *key, int slot) +			     struct btrfs_key *key, int slot, +			     struct btrfs_key *prev_key)  {  	struct btrfs_fs_info *fs_info = leaf->fs_info;  	struct btrfs_extent_item *ei; @@ -1453,6 +1454,26 @@ static int check_extent_item(struct extent_buffer *leaf,  			   total_refs, inline_refs);  		return -EUCLEAN;  	} + +	if ((prev_key->type == BTRFS_EXTENT_ITEM_KEY) || +	    (prev_key->type == BTRFS_METADATA_ITEM_KEY)) { +		u64 prev_end = prev_key->objectid; + +		if (prev_key->type == BTRFS_METADATA_ITEM_KEY) +			prev_end += fs_info->nodesize; +		else +			prev_end += prev_key->offset; + +		if (unlikely(prev_end > key->objectid)) { +			extent_err(leaf, slot, +	"previous extent [%llu %u %llu] overlaps current extent [%llu %u %llu]", +				   prev_key->objectid, prev_key->type, +				   prev_key->offset, key->objectid, key->type, +				   key->offset); +			return -EUCLEAN; +		} +	} +  	return 0;  } @@ -1621,7 +1642,7 @@ static int check_leaf_item(struct extent_buffer *leaf,  		break;  	case BTRFS_EXTENT_ITEM_KEY:  	case BTRFS_METADATA_ITEM_KEY: -		ret = check_extent_item(leaf, key, slot); +		ret = check_extent_item(leaf, key, slot, prev_key);  		break;  	case BTRFS_TREE_BLOCK_REF_KEY:  	case BTRFS_SHARED_DATA_REF_KEY:  | 
