Enhance btrfs_verify_dev_extents() to remember previous checked dev
extents, so it can check if one dev extent overlaps with previous dev extent.

Reported-by: Hans van Kranenburg <hans.van.kranenb...@mendix.com>
Signed-off-by: Qu Wenruo <w...@suse.com>
---
 fs/btrfs/volumes.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index da86706123ff..bf0b2c16847a 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -7462,6 +7462,8 @@ int btrfs_verify_dev_extents(struct btrfs_fs_info 
*fs_info)
        struct btrfs_path *path;
        struct btrfs_root *root = fs_info->dev_root;
        struct btrfs_key key;
+       u64 prev_devid = 0;
+       u64 prev_dev_ext_end = 0;
        int ret = 0;
 
        key.objectid = 1;
@@ -7506,10 +7508,22 @@ int btrfs_verify_dev_extents(struct btrfs_fs_info 
*fs_info)
                chunk_offset = btrfs_dev_extent_chunk_offset(leaf, dext);
                physical_len = btrfs_dev_extent_length(leaf, dext);
 
+               /* Check if this dev extent over lap with previous one */
+               if (devid == prev_devid && physical_offset < prev_dev_ext_end) {
+                       btrfs_err(fs_info,
+"dev extent devid %llu physical offset %llu overlap with previous dev extent 
end %llu",
+                                 devid, physical_offset, prev_dev_ext_end);
+                       ret = -EUCLEAN;
+                       goto out;
+               }
+
                ret = verify_one_dev_extent(fs_info, chunk_offset, devid,
                                            physical_offset, physical_len);
                if (ret < 0)
                        goto out;
+               prev_devid = devid;
+               prev_dev_ext_end = physical_offset + physical_len;
+
                ret = btrfs_next_item(root, path);
                if (ret < 0)
                        goto out;
-- 
2.19.0

Reply via email to