Btrfs: fix BUG() in scrub when first superblock reading gives EIO
authorStefan Behrens <sbehrens@giantdisaster.de>
Wed, 14 Nov 2012 18:57:29 +0000 (18:57 +0000)
committerChris Mason <chris.mason@fusionio.com>
Mon, 17 Dec 2012 01:46:28 +0000 (20:46 -0500)
This fixes a very special case that can be reproduced by just
disconnecting a disk at runtime, and without unmounting the
filesystem first, start scrub on the filesystem with the
disconnected disk. All read and write EIOs are handled
correctly, only the first superblock is an exception and gives
a BUG() in a subfunction. The BUG() is correct, it would crash
later otherwise. The subfunction must not be called for
superblocks and this is what the fix changes.

Reported-by: Joeri Vanthienen <mail@joerivanthienen.be>
Signed-off-by: Stefan Behrens <sbehrens@giantdisaster.de>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
fs/btrfs/scrub.c

index 8db6a6413a5fdee2974103500e24acfb9e24e221..bdbb94f245c9070802c65acb6eba392ba1a4c932 100644 (file)
@@ -785,6 +785,17 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
 
        BUG_ON(sblock_to_check->page_count < 1);
        fs_info = sctx->dev_root->fs_info;
+       if (sblock_to_check->pagev[0]->flags & BTRFS_EXTENT_FLAG_SUPER) {
+               /*
+                * if we find an error in a super block, we just report it.
+                * They will get written with the next transaction commit
+                * anyway
+                */
+               spin_lock(&sctx->stat_lock);
+               ++sctx->stat.super_errors;
+               spin_unlock(&sctx->stat_lock);
+               return 0;
+       }
        length = sblock_to_check->page_count * PAGE_SIZE;
        logical = sblock_to_check->pagev[0]->logical;
        generation = sblock_to_check->pagev[0]->generation;