OSDN Git Service

Btrfs: replace: cache rbio when rebuild data on missing device
[uclinux-h8/linux.git] / fs / btrfs / raid56.c
index dec0907..c3a2bc8 100644 (file)
@@ -1370,6 +1370,7 @@ static int find_bio_stripe(struct btrfs_raid_bio *rbio,
                stripe_start = stripe->physical;
                if (physical >= stripe_start &&
                    physical < stripe_start + rbio->stripe_len &&
+                   stripe->dev->bdev &&
                    bio->bi_disk == stripe->dev->bdev->bd_disk &&
                    bio->bi_partno == stripe->dev->bdev->bd_partno) {
                        return i;
@@ -1986,7 +1987,13 @@ cleanup:
        kfree(pointers);
 
 cleanup_io:
-       if (rbio->operation == BTRFS_RBIO_READ_REBUILD) {
+       /*
+        * Similar to READ_REBUILD, REBUILD_MISSING at this point also has a
+        * valid rbio which is consistent with ondisk content, thus such a
+        * valid rbio can be cached to avoid further disk reads.
+        */
+       if (rbio->operation == BTRFS_RBIO_READ_REBUILD ||
+           rbio->operation == BTRFS_RBIO_REBUILD_MISSING) {
                /*
                 * - In case of two failures, where rbio->failb != -1:
                 *
@@ -2008,8 +2015,6 @@ cleanup_io:
                        clear_bit(RBIO_CACHE_READY_BIT, &rbio->flags);
 
                rbio_orig_end_io(rbio, err);
-       } else if (rbio->operation == BTRFS_RBIO_REBUILD_MISSING) {
-               rbio_orig_end_io(rbio, err);
        } else if (err == BLK_STS_OK) {
                rbio->faila = -1;
                rbio->failb = -1;
@@ -2767,24 +2772,8 @@ raid56_alloc_missing_rbio(struct btrfs_fs_info *fs_info, struct bio *bio,
        return rbio;
 }
 
-static void missing_raid56_work(struct btrfs_work *work)
-{
-       struct btrfs_raid_bio *rbio;
-
-       rbio = container_of(work, struct btrfs_raid_bio, work);
-       __raid56_parity_recover(rbio);
-}
-
-static void async_missing_raid56(struct btrfs_raid_bio *rbio)
-{
-       btrfs_init_work(&rbio->work, btrfs_rmw_helper,
-                       missing_raid56_work, NULL, NULL);
-
-       btrfs_queue_work(rbio->fs_info->rmw_workers, &rbio->work);
-}
-
 void raid56_submit_missing_rbio(struct btrfs_raid_bio *rbio)
 {
        if (!lock_stripe_add(rbio))
-               async_missing_raid56(rbio);
+               async_read_rebuild(rbio);
 }