Btrfs: fix crash in scrub repair code when device is missing
authorStefan Behrens <sbehrens@giantdisaster.de>
Fri, 4 May 2012 19:16:07 +0000 (15:16 -0400)
committerChris Mason <chris.mason@oracle.com>
Fri, 4 May 2012 19:16:07 +0000 (15:16 -0400)
Fix that when scrub tries to repair an I/O or checksum error and one of
the devices containing the mirror is missing, it crashes in bio_add_page
because the bdev is a NULL pointer for missing devices.

Reported-by: Marco L. Crociani <marco.crociani@gmail.com>
Signed-off-by: Stefan Behrens <sbehrens@giantdisaster.de>
Signed-off-by: Chris Mason <chris.mason@oracle.com>

fs/btrfs/scrub.c

index b679bf6..7e487be 100644 (file)
@@ -998,6 +998,7 @@ static int scrub_setup_recheck_block(struct scrub_dev *sdev,
                        page = sblock->pagev + page_index;
                        page->logical = logical;
                        page->physical = bbio->stripes[mirror_index].physical;
+                       /* for missing devices, bdev is NULL */
                        page->bdev = bbio->stripes[mirror_index].dev->bdev;
                        page->mirror_num = mirror_index + 1;
                        page->page = alloc_page(GFP_NOFS);
@@ -1042,6 +1043,12 @@ static int scrub_recheck_block(struct btrfs_fs_info *fs_info,
                struct scrub_page *page = sblock->pagev + page_num;
                DECLARE_COMPLETION_ONSTACK(complete);
 
+               if (page->bdev == NULL) {
+                       page->io_error = 1;
+                       sblock->no_io_error_seen = 0;
+                       continue;
+               }
+
                BUG_ON(!page->page);
                bio = bio_alloc(GFP_NOFS, 1);
                if (!bio)