aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/linear.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/linear.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/linear.c')
-rw-r--r--drivers/md/linear.c6
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 */
63static int linear_mergeable_bvec(struct request_queue *q, 63static 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
366static int __init linear_init (void) 364static int __init linear_init (void)