aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid0.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2014-12-14 20:56:57 -0500
committerNeilBrown <neilb@suse.de>2015-02-03 16:35:52 -0500
commit64590f45ddc7147fa1968147a1f5b5c436b728fe (patch)
treec33e8ce09d739bac929e8ca943a253cb03cafd12 /drivers/md/raid0.c
parent5c675f83c68fbdf9c0e103c1090b06be747fa62c (diff)
md: make merge_bvec_fn more robust in face of personality changes.
There is no locking around calls to merge_bvec_fn(), so it is possible that calls which coincide with a level (or personality) change could go wrong. So create a central dispatch point for these functions and use rcu_read_lock(). If the array is suspended, reject any merge that can be rejected. If not, we know it is safe to call the function. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/raid0.c')
-rw-r--r--drivers/md/raid0.c7
1 files changed, 3 insertions, 4 deletions
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 4b521eac5b69..3770c9675b17 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -350,17 +350,16 @@ static struct md_rdev *map_sector(struct mddev *mddev, struct strip_zone *zone,
350 350
351/** 351/**
352 * raid0_mergeable_bvec -- tell bio layer if two requests can be merged 352 * raid0_mergeable_bvec -- tell bio layer if two requests can be merged
353 * @q: request queue 353 * @mddev: the md device
354 * @bvm: properties of new bio 354 * @bvm: properties of new bio
355 * @biovec: the request that could be merged to it. 355 * @biovec: the request that could be merged to it.
356 * 356 *
357 * Return amount of bytes we can accept at this offset 357 * Return amount of bytes we can accept at this offset
358 */ 358 */
359static int raid0_mergeable_bvec(struct request_queue *q, 359static int raid0_mergeable_bvec(struct mddev *mddev,
360 struct bvec_merge_data *bvm, 360 struct bvec_merge_data *bvm,
361 struct bio_vec *biovec) 361 struct bio_vec *biovec)
362{ 362{
363 struct mddev *mddev = q->queuedata;
364 struct r0conf *conf = mddev->private; 363 struct r0conf *conf = mddev->private;
365 sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev); 364 sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
366 sector_t sector_offset = sector; 365 sector_t sector_offset = sector;
@@ -465,7 +464,6 @@ static int raid0_run(struct mddev *mddev)
465 mddev->queue->backing_dev_info.ra_pages = 2* stripe; 464 mddev->queue->backing_dev_info.ra_pages = 2* stripe;
466 } 465 }
467 466
468 blk_queue_merge_bvec(mddev->queue, raid0_mergeable_bvec);
469 dump_zones(mddev); 467 dump_zones(mddev);
470 468
471 ret = md_integrity_register(mddev); 469 ret = md_integrity_register(mddev);
@@ -724,6 +722,7 @@ static struct md_personality raid0_personality=
724 .takeover = raid0_takeover, 722 .takeover = raid0_takeover,
725 .quiesce = raid0_quiesce, 723 .quiesce = raid0_quiesce,
726 .congested = raid0_congested, 724 .congested = raid0_congested,
725 .mergeable_bvec = raid0_mergeable_bvec,
727}; 726};
728 727
729static int __init raid0_init (void) 728static int __init raid0_init (void)