summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnand Jain <anand.jain@oracle.com>2019-08-27 03:40:44 -0400
committerDavid Sterba <dsterba@suse.com>2019-09-09 08:59:14 -0400
commita06dee4d7eb67c35e7b7da0b84216424d60a87d3 (patch)
treeab632aea6ca82855894441b0d84251e5fa5cf96a
parent3acd48507dc43eeeb0a1fe965b8bad91cab904a7 (diff)
btrfs: proper error handling when invalid device is found in find_next_devid
In a corrupted tree, if search for next devid finds the device with devid = -1, then report the error -EUCLEAN back to the parent function to fail gracefully. The tree checker will not catch this in case the devids are created using the following script: umount /btrfs dev1=/dev/sdb dev2=/dev/sdc mkfs.btrfs -fq -dsingle -msingle $dev1 mount $dev1 /btrfs _fail() { echo $1 exit 1 } while true; do btrfs dev add -f $dev2 /btrfs || _fail "add failed" btrfs dev del $dev1 /btrfs || _fail "del failed" dev_tmp=$dev1 dev1=$dev2 dev2=$dev_tmp done With output: BTRFS critical (device sdb): corrupt leaf: root=3 block=313739198464 slot=1 devid=1 invalid devid: has=507 expect=[0, 506] BTRFS error (device sdb): block=313739198464 write time tree block corruption detected BTRFS: error (device sdb) in btrfs_commit_transaction:2268: errno=-5 IO failure (Error while writing out transaction) BTRFS warning (device sdb): Skipping commit of aborted transaction. BTRFS: error (device sdb) in cleanup_transaction:1827: errno=-5 IO failure Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> Reviewed-by: Qu Wenruo <wqu@suse.com> Reviewed-by: Nikolay Borisov <nborisov@suse.com> Signed-off-by: Anand Jain <anand.jain@oracle.com> [ add script and messages ] Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/volumes.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index e2de7c7b674a..c7a08fe26672 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1849,7 +1849,12 @@ static noinline int find_next_devid(struct btrfs_fs_info *fs_info,
1849 if (ret < 0) 1849 if (ret < 0)
1850 goto error; 1850 goto error;
1851 1851
1852 BUG_ON(ret == 0); /* Corruption */ 1852 if (ret == 0) {
1853 /* Corruption */
1854 btrfs_err(fs_info, "corrupted chunk tree devid -1 matched");
1855 ret = -EUCLEAN;
1856 goto error;
1857 }
1853 1858
1854 ret = btrfs_previous_item(fs_info->chunk_root, path, 1859 ret = btrfs_previous_item(fs_info->chunk_root, path,
1855 BTRFS_DEV_ITEMS_OBJECTID, 1860 BTRFS_DEV_ITEMS_OBJECTID,