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/linear.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/linear.c')
-rw-r--r-- | drivers/md/linear.c | 6 |
1 files changed, 2 insertions, 4 deletions
diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 05108510d9cd..4c2a92ce2b0b 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c | |||
@@ -60,11 +60,10 @@ static inline struct dev_info *which_dev(struct mddev *mddev, sector_t sector) | |||
60 | * | 60 | * |
61 | * Return amount of bytes we can take at this offset | 61 | * Return amount of bytes we can take at this offset |
62 | */ | 62 | */ |
63 | static int linear_mergeable_bvec(struct request_queue *q, | 63 | static int linear_mergeable_bvec(struct mddev *mddev, |
64 | struct bvec_merge_data *bvm, | 64 | struct bvec_merge_data *bvm, |
65 | struct bio_vec *biovec) | 65 | struct bio_vec *biovec) |
66 | { | 66 | { |
67 | struct mddev *mddev = q->queuedata; | ||
68 | struct dev_info *dev0; | 67 | struct dev_info *dev0; |
69 | unsigned long maxsectors, bio_sectors = bvm->bi_size >> 9; | 68 | unsigned long maxsectors, bio_sectors = bvm->bi_size >> 9; |
70 | sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev); | 69 | sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev); |
@@ -213,8 +212,6 @@ static int linear_run (struct mddev *mddev) | |||
213 | mddev->private = conf; | 212 | mddev->private = conf; |
214 | md_set_array_sectors(mddev, linear_size(mddev, 0, 0)); | 213 | md_set_array_sectors(mddev, linear_size(mddev, 0, 0)); |
215 | 214 | ||
216 | blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec); | ||
217 | |||
218 | ret = md_integrity_register(mddev); | 215 | ret = md_integrity_register(mddev); |
219 | if (ret) { | 216 | if (ret) { |
220 | kfree(conf); | 217 | kfree(conf); |
@@ -361,6 +358,7 @@ static struct md_personality linear_personality = | |||
361 | .hot_add_disk = linear_add, | 358 | .hot_add_disk = linear_add, |
362 | .size = linear_size, | 359 | .size = linear_size, |
363 | .congested = linear_congested, | 360 | .congested = linear_congested, |
361 | .mergeable_bvec = linear_mergeable_bvec, | ||
364 | }; | 362 | }; |
365 | 363 | ||
366 | static int __init linear_init (void) | 364 | static int __init linear_init (void) |