btrfs: do not try to repair bio that has no mirror set
authorJosef Bacik <josef@toxicpanda.com>
Fri, 18 Feb 2022 15:03:28 +0000 (10:03 -0500)
committerDavid Sterba <dsterba@suse.com>
Mon, 14 Mar 2022 12:13:52 +0000 (13:13 +0100)
If we fail to submit a bio for whatever reason, we may not have setup a
mirror_num for that bio.  This means we shouldn't try to do the repair
workflow, if we do we'll hit an BUG_ON(!failrec->this_mirror) in
clean_io_failure.  Instead simply skip the repair workflow if we have no
mirror set, and add an assert to btrfs_check_repairable() to make it
easier to catch what is happening in the future.

Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/extent_io.c

index 13155e57e8c239eec51559bb7564b4bdb619e638..6a095e9962219f1ab73f9aedad15f8ff7d4565b5 100644 (file)
@@ -2610,6 +2610,7 @@ static bool btrfs_check_repairable(struct inode *inode,
         * a good copy of the failed sector and if we succeed, we have setup
         * everything for repair_io_failure to do the rest for us.
         */
+       ASSERT(failed_mirror);
        failrec->failed_mirror = failed_mirror;
        failrec->this_mirror++;
        if (failrec->this_mirror == failed_mirror)
@@ -3067,6 +3068,14 @@ static void end_bio_extent_readpage(struct bio *bio)
                        goto readpage_ok;
 
                if (is_data_inode(inode)) {
+                       /*
+                        * If we failed to submit the IO at all we'll have a
+                        * mirror_num == 0, in which case we need to just mark
+                        * the page with an error and unlock it and carry on.
+                        */
+                       if (mirror == 0)
+                               goto readpage_ok;
+
                        /*
                         * btrfs_submit_read_repair() will handle all the good
                         * and bad sectors, we just continue to the next bvec.