Btrfs, replace: write raid56 parity into the replace target device
authorMiao Xie <miaox@cn.fujitsu.com>
Fri, 14 Nov 2014 09:45:42 +0000 (17:45 +0800)
committerMiao Xie <miaox@cn.fujitsu.com>
Wed, 3 Dec 2014 02:18:46 +0000 (10:18 +0800)
This function reused the code of parity scrub, and we just write
the right parity or corrected parity into the target device before
the parity scrub end.

Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
fs/btrfs/raid56.c
fs/btrfs/scrub.c

index 89a8486c34b3ccced7d21ddb863013f58c559a5a..5ece565bc5f0cda1c38f4ad319e8fb52e24eacba 100644 (file)
@@ -2318,7 +2318,9 @@ static void raid_write_parity_end_io(struct bio *bio, int err)
 static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio,
                                         int need_check)
 {
+       struct btrfs_bio *bbio = rbio->bbio;
        void *pointers[rbio->real_stripes];
+       DECLARE_BITMAP(pbitmap, rbio->stripe_npages);
        int nr_data = rbio->nr_data;
        int stripe;
        int pagenr;
@@ -2328,6 +2330,7 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio,
        struct page *q_page = NULL;
        struct bio_list bio_list;
        struct bio *bio;
+       int is_replace = 0;
        int ret;
 
        bio_list_init(&bio_list);
@@ -2341,6 +2344,11 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio,
                BUG();
        }
 
+       if (bbio->num_tgtdevs && bbio->tgtdev_map[rbio->scrubp]) {
+               is_replace = 1;
+               bitmap_copy(pbitmap, rbio->dbitmap, rbio->stripe_npages);
+       }
+
        /*
         * Because the higher layers(scrubber) are unlikely to
         * use this area of the disk again soon, so don't cache
@@ -2429,6 +2437,21 @@ writeback:
                        goto cleanup;
        }
 
+       if (!is_replace)
+               goto submit_write;
+
+       for_each_set_bit(pagenr, pbitmap, rbio->stripe_npages) {
+               struct page *page;
+
+               page = rbio_stripe_page(rbio, rbio->scrubp, pagenr);
+               ret = rbio_add_io_page(rbio, &bio_list, page,
+                                      bbio->tgtdev_map[rbio->scrubp],
+                                      pagenr, rbio->stripe_len);
+               if (ret)
+                       goto cleanup;
+       }
+
+submit_write:
        nr_data = bio_list_size(&bio_list);
        if (!nr_data) {
                /* Every parity is right */
index 7f95afcf9fd3d8976598daa2d88dd8f9b45a4279..0ae837fd676df4cb92dd7cd200fce2c42bf42c8d 100644 (file)
@@ -2714,7 +2714,7 @@ static void scrub_parity_check_and_repair(struct scrub_parity *sparity)
                goto out;
 
        length = sparity->logic_end - sparity->logic_start + 1;
-       ret = btrfs_map_sblock(sctx->dev_root->fs_info, REQ_GET_READ_MIRRORS,
+       ret = btrfs_map_sblock(sctx->dev_root->fs_info, WRITE,
                               sparity->logic_start,
                               &length, &bbio, 0, &raid_map);
        if (ret || !bbio || !raid_map)