| From 51f981f544dd7ff161131d7dc11cdbc28622a7cb Mon Sep 17 00:00:00 2001 |
| From: Qu Wenruo <wqu@suse.com> |
| Date: Wed, 28 Aug 2019 10:33:13 +0800 |
| Subject: [PATCH] btrfs: tree-checker: Fix wrong check on max devid |
| |
| commit 8bb177d18f114358a57d8ae7e206861b48b8b4de upstream. |
| |
| [BUG] |
| The following script will cause false alert on devid check. |
| #!/bin/bash |
| |
| dev1=/dev/test/test |
| dev2=/dev/test/scratch1 |
| mnt=/mnt/btrfs |
| |
| umount $dev1 &> /dev/null |
| umount $dev2 &> /dev/null |
| umount $mnt &> /dev/null |
| |
| mkfs.btrfs -f $dev1 |
| |
| mount $dev1 $mnt |
| |
| _fail() |
| { |
| echo "!!! FAILED !!!" |
| exit 1 |
| } |
| |
| for ((i = 0; i < 4096; i++)); do |
| btrfs dev add -f $dev2 $mnt || _fail |
| btrfs dev del $dev1 $mnt || _fail |
| dev_tmp=$dev1 |
| dev1=$dev2 |
| dev2=$dev_tmp |
| done |
| |
| [CAUSE] |
| Tree-checker uses BTRFS_MAX_DEVS() and BTRFS_MAX_DEVS_SYS_CHUNK() as |
| upper limit for devid. But we can have devid holes just like above |
| script. |
| |
| So the check for devid is incorrect and could cause false alert. |
| |
| [FIX] |
| Just remove the whole devid check. We don't have any hard requirement |
| for devid assignment. |
| |
| Furthermore, even devid could get corrupted by a bitflip, we still have |
| dev extents verification at mount time, so corrupted data won't sneak |
| in. |
| |
| This fixes fstests btrfs/194. |
| |
| Reported-by: Anand Jain <anand.jain@oracle.com> |
| Fixes: ab4ba2e13346 ("btrfs: tree-checker: Verify dev item") |
| CC: stable@vger.kernel.org # 5.2+ |
| Signed-off-by: Qu Wenruo <wqu@suse.com> |
| Reviewed-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c |
| index 9634cae1e1b1..24f36e2dac06 100644 |
| --- a/fs/btrfs/tree-checker.c |
| +++ b/fs/btrfs/tree-checker.c |
| @@ -686,9 +686,7 @@ static void dev_item_err(const struct extent_buffer *eb, int slot, |
| static int check_dev_item(struct extent_buffer *leaf, |
| struct btrfs_key *key, int slot) |
| { |
| - struct btrfs_fs_info *fs_info = leaf->fs_info; |
| struct btrfs_dev_item *ditem; |
| - u64 max_devid = max(BTRFS_MAX_DEVS(fs_info), BTRFS_MAX_DEVS_SYS_CHUNK); |
| |
| if (key->objectid != BTRFS_DEV_ITEMS_OBJECTID) { |
| dev_item_err(leaf, slot, |
| @@ -696,12 +694,6 @@ static int check_dev_item(struct extent_buffer *leaf, |
| key->objectid, BTRFS_DEV_ITEMS_OBJECTID); |
| return -EUCLEAN; |
| } |
| - if (key->offset > max_devid) { |
| - dev_item_err(leaf, slot, |
| - "invalid devid: has=%llu expect=[0, %llu]", |
| - key->offset, max_devid); |
| - return -EUCLEAN; |
| - } |
| ditem = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item); |
| if (btrfs_device_id(leaf, ditem) != key->offset) { |
| dev_item_err(leaf, slot, |
| -- |
| 2.7.4 |
| |