diff options
author | NeilBrown <neilb@suse.de> | 2014-12-14 20:56:57 -0500 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2015-02-03 16:35:52 -0500 |
commit | 64590f45ddc7147fa1968147a1f5b5c436b728fe (patch) | |
tree | c33e8ce09d739bac929e8ca943a253cb03cafd12 /drivers/md/raid0.c | |
parent | 5c675f83c68fbdf9c0e103c1090b06be747fa62c (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.c | 7 |
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 | */ |
359 | static int raid0_mergeable_bvec(struct request_queue *q, | 359 | static 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 | ||
729 | static int __init raid0_init (void) | 728 | static int __init raid0_init (void) |