summaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2014-11-14 17:45:42 +0800
committerMiao Xie <miaox@cn.fujitsu.com>2014-12-03 10:18:46 +0800
commit7603597690147a16b5cc77047d7570fa22a22673 (patch)
tree6fc1618acba90230ea06986eee104c962475795a /fs/btrfs
parent2c8cdd6ee4e7f637b0486c6798117e7859dee586 (diff)
downloadop-kernel-dev-7603597690147a16b5cc77047d7570fa22a22673.zip
op-kernel-dev-7603597690147a16b5cc77047d7570fa22a22673.tar.gz
Btrfs, replace: write raid56 parity into the replace target device
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>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/raid56.c23
-rw-r--r--fs/btrfs/scrub.c2
2 files changed, 24 insertions, 1 deletions
diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index 89a8486..5ece565 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -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 */
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 7f95afc..0ae837f 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -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)
OpenPOWER on IntegriCloud