summaryrefslogtreecommitdiff
path: root/drivers/md/raid1.c
diff options
context:
space:
mode:
authorShaohua Li <shli@fb.com>2017-08-24 17:50:40 -0700
committerShaohua Li <shli@fb.com>2017-08-25 10:21:44 -0700
commit208410b546207cfc4c832635fa46419cfa86b4cd (patch)
tree39b87caad9074f3dc4748b109fa216568fad2d99 /drivers/md/raid1.c
parent9c72a18e46ebe0f09484cce8ebf847abdab58498 (diff)
md/raid1/10: reset bio allocated from mempool
Data allocated from mempool doesn't always get initialized, this happens when the data is reused instead of fresh allocation. In the raid1/10 case, we must reinitialize the bios. Reported-by: Jonathan G. Underwood <jonathan.underwood@gmail.com> Fixes: f0250618361d(md: raid10: don't use bio's vec table to manage resync pages) Fixes: 98d30c5812c3(md: raid1: don't use bio's vec table to manage resync pages) Cc: stable@vger.kernel.org (4.12+) Cc: Ming Lei <ming.lei@redhat.com> Signed-off-by: Shaohua Li <shli@fb.com>
Diffstat (limited to 'drivers/md/raid1.c')
-rw-r--r--drivers/md/raid1.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index f50958ded9f0..79474f47eeef 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -2564,6 +2564,23 @@ static int init_resync(struct r1conf *conf)
return 0;
}
+static struct r1bio *raid1_alloc_init_r1buf(struct r1conf *conf)
+{
+ struct r1bio *r1bio = mempool_alloc(conf->r1buf_pool, GFP_NOIO);
+ struct resync_pages *rps;
+ struct bio *bio;
+ int i;
+
+ for (i = conf->poolinfo->raid_disks; i--; ) {
+ bio = r1bio->bios[i];
+ rps = bio->bi_private;
+ bio_reset(bio);
+ bio->bi_private = rps;
+ }
+ r1bio->master_bio = NULL;
+ return r1bio;
+}
+
/*
* perform a "sync" on one "block"
*
@@ -2649,7 +2666,7 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr,
bitmap_cond_end_sync(mddev->bitmap, sector_nr,
mddev_is_clustered(mddev) && (sector_nr + 2 * RESYNC_SECTORS > conf->cluster_sync_high));
- r1_bio = mempool_alloc(conf->r1buf_pool, GFP_NOIO);
+ r1_bio = raid1_alloc_init_r1buf(conf);
raise_barrier(conf, sector_nr);