diff options
Diffstat (limited to 'drivers/md/linear.c')
-rw-r--r-- | drivers/md/linear.c | 67 |
1 files changed, 20 insertions, 47 deletions
diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 64713b77df1c..fa7d577f3d12 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c | |||
@@ -34,7 +34,7 @@ static inline struct dev_info *which_dev(struct mddev *mddev, sector_t sector) | |||
34 | 34 | ||
35 | lo = 0; | 35 | lo = 0; |
36 | hi = mddev->raid_disks - 1; | 36 | hi = mddev->raid_disks - 1; |
37 | conf = rcu_dereference(mddev->private); | 37 | conf = mddev->private; |
38 | 38 | ||
39 | /* | 39 | /* |
40 | * Binary Search | 40 | * Binary Search |
@@ -60,18 +60,16 @@ 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); |
71 | int maxbytes = biovec->bv_len; | 70 | int maxbytes = biovec->bv_len; |
72 | struct request_queue *subq; | 71 | struct request_queue *subq; |
73 | 72 | ||
74 | rcu_read_lock(); | ||
75 | dev0 = which_dev(mddev, sector); | 73 | dev0 = which_dev(mddev, sector); |
76 | maxsectors = dev0->end_sector - sector; | 74 | maxsectors = dev0->end_sector - sector; |
77 | subq = bdev_get_queue(dev0->rdev->bdev); | 75 | subq = bdev_get_queue(dev0->rdev->bdev); |
@@ -81,7 +79,6 @@ static int linear_mergeable_bvec(struct request_queue *q, | |||
81 | maxbytes = min(maxbytes, subq->merge_bvec_fn(subq, bvm, | 79 | maxbytes = min(maxbytes, subq->merge_bvec_fn(subq, bvm, |
82 | biovec)); | 80 | biovec)); |
83 | } | 81 | } |
84 | rcu_read_unlock(); | ||
85 | 82 | ||
86 | if (maxsectors < bio_sectors) | 83 | if (maxsectors < bio_sectors) |
87 | maxsectors = 0; | 84 | maxsectors = 0; |
@@ -97,24 +94,18 @@ static int linear_mergeable_bvec(struct request_queue *q, | |||
97 | return maxsectors << 9; | 94 | return maxsectors << 9; |
98 | } | 95 | } |
99 | 96 | ||
100 | static int linear_congested(void *data, int bits) | 97 | static int linear_congested(struct mddev *mddev, int bits) |
101 | { | 98 | { |
102 | struct mddev *mddev = data; | ||
103 | struct linear_conf *conf; | 99 | struct linear_conf *conf; |
104 | int i, ret = 0; | 100 | int i, ret = 0; |
105 | 101 | ||
106 | if (mddev_congested(mddev, bits)) | 102 | conf = mddev->private; |
107 | return 1; | ||
108 | |||
109 | rcu_read_lock(); | ||
110 | conf = rcu_dereference(mddev->private); | ||
111 | 103 | ||
112 | for (i = 0; i < mddev->raid_disks && !ret ; i++) { | 104 | for (i = 0; i < mddev->raid_disks && !ret ; i++) { |
113 | struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev); | 105 | struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev); |
114 | ret |= bdi_congested(&q->backing_dev_info, bits); | 106 | ret |= bdi_congested(&q->backing_dev_info, bits); |
115 | } | 107 | } |
116 | 108 | ||
117 | rcu_read_unlock(); | ||
118 | return ret; | 109 | return ret; |
119 | } | 110 | } |
120 | 111 | ||
@@ -123,12 +114,10 @@ static sector_t linear_size(struct mddev *mddev, sector_t sectors, int raid_disk | |||
123 | struct linear_conf *conf; | 114 | struct linear_conf *conf; |
124 | sector_t array_sectors; | 115 | sector_t array_sectors; |
125 | 116 | ||
126 | rcu_read_lock(); | 117 | conf = mddev->private; |
127 | conf = rcu_dereference(mddev->private); | ||
128 | WARN_ONCE(sectors || raid_disks, | 118 | WARN_ONCE(sectors || raid_disks, |
129 | "%s does not support generic reshape\n", __func__); | 119 | "%s does not support generic reshape\n", __func__); |
130 | array_sectors = conf->array_sectors; | 120 | array_sectors = conf->array_sectors; |
131 | rcu_read_unlock(); | ||
132 | 121 | ||
133 | return array_sectors; | 122 | return array_sectors; |
134 | } | 123 | } |
@@ -217,10 +206,6 @@ static int linear_run (struct mddev *mddev) | |||
217 | mddev->private = conf; | 206 | mddev->private = conf; |
218 | md_set_array_sectors(mddev, linear_size(mddev, 0, 0)); | 207 | md_set_array_sectors(mddev, linear_size(mddev, 0, 0)); |
219 | 208 | ||
220 | blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec); | ||
221 | mddev->queue->backing_dev_info.congested_fn = linear_congested; | ||
222 | mddev->queue->backing_dev_info.congested_data = mddev; | ||
223 | |||
224 | ret = md_integrity_register(mddev); | 209 | ret = md_integrity_register(mddev); |
225 | if (ret) { | 210 | if (ret) { |
226 | kfree(conf); | 211 | kfree(conf); |
@@ -252,38 +237,23 @@ static int linear_add(struct mddev *mddev, struct md_rdev *rdev) | |||
252 | if (!newconf) | 237 | if (!newconf) |
253 | return -ENOMEM; | 238 | return -ENOMEM; |
254 | 239 | ||
255 | oldconf = rcu_dereference_protected(mddev->private, | 240 | mddev_suspend(mddev); |
256 | lockdep_is_held( | 241 | oldconf = mddev->private; |
257 | &mddev->reconfig_mutex)); | ||
258 | mddev->raid_disks++; | 242 | mddev->raid_disks++; |
259 | rcu_assign_pointer(mddev->private, newconf); | 243 | mddev->private = newconf; |
260 | md_set_array_sectors(mddev, linear_size(mddev, 0, 0)); | 244 | md_set_array_sectors(mddev, linear_size(mddev, 0, 0)); |
261 | set_capacity(mddev->gendisk, mddev->array_sectors); | 245 | set_capacity(mddev->gendisk, mddev->array_sectors); |
246 | mddev_resume(mddev); | ||
262 | revalidate_disk(mddev->gendisk); | 247 | revalidate_disk(mddev->gendisk); |
263 | kfree_rcu(oldconf, rcu); | 248 | kfree(oldconf); |
264 | return 0; | 249 | return 0; |
265 | } | 250 | } |
266 | 251 | ||
267 | static int linear_stop (struct mddev *mddev) | 252 | static void linear_free(struct mddev *mddev, void *priv) |
268 | { | 253 | { |
269 | struct linear_conf *conf = | 254 | struct linear_conf *conf = priv; |
270 | rcu_dereference_protected(mddev->private, | ||
271 | lockdep_is_held( | ||
272 | &mddev->reconfig_mutex)); | ||
273 | 255 | ||
274 | /* | ||
275 | * We do not require rcu protection here since | ||
276 | * we hold reconfig_mutex for both linear_add and | ||
277 | * linear_stop, so they cannot race. | ||
278 | * We should make sure any old 'conf's are properly | ||
279 | * freed though. | ||
280 | */ | ||
281 | rcu_barrier(); | ||
282 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ | ||
283 | kfree(conf); | 256 | kfree(conf); |
284 | mddev->private = NULL; | ||
285 | |||
286 | return 0; | ||
287 | } | 257 | } |
288 | 258 | ||
289 | static void linear_make_request(struct mddev *mddev, struct bio *bio) | 259 | static void linear_make_request(struct mddev *mddev, struct bio *bio) |
@@ -299,16 +269,12 @@ static void linear_make_request(struct mddev *mddev, struct bio *bio) | |||
299 | } | 269 | } |
300 | 270 | ||
301 | do { | 271 | do { |
302 | rcu_read_lock(); | ||
303 | |||
304 | tmp_dev = which_dev(mddev, bio->bi_iter.bi_sector); | 272 | tmp_dev = which_dev(mddev, bio->bi_iter.bi_sector); |
305 | start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors; | 273 | start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors; |
306 | end_sector = tmp_dev->end_sector; | 274 | end_sector = tmp_dev->end_sector; |
307 | data_offset = tmp_dev->rdev->data_offset; | 275 | data_offset = tmp_dev->rdev->data_offset; |
308 | bio->bi_bdev = tmp_dev->rdev->bdev; | 276 | bio->bi_bdev = tmp_dev->rdev->bdev; |
309 | 277 | ||
310 | rcu_read_unlock(); | ||
311 | |||
312 | if (unlikely(bio->bi_iter.bi_sector >= end_sector || | 278 | if (unlikely(bio->bi_iter.bi_sector >= end_sector || |
313 | bio->bi_iter.bi_sector < start_sector)) | 279 | bio->bi_iter.bi_sector < start_sector)) |
314 | goto out_of_bounds; | 280 | goto out_of_bounds; |
@@ -355,6 +321,10 @@ static void linear_status (struct seq_file *seq, struct mddev *mddev) | |||
355 | seq_printf(seq, " %dk rounding", mddev->chunk_sectors / 2); | 321 | seq_printf(seq, " %dk rounding", mddev->chunk_sectors / 2); |
356 | } | 322 | } |
357 | 323 | ||
324 | static void linear_quiesce(struct mddev *mddev, int state) | ||
325 | { | ||
326 | } | ||
327 | |||
358 | static struct md_personality linear_personality = | 328 | static struct md_personality linear_personality = |
359 | { | 329 | { |
360 | .name = "linear", | 330 | .name = "linear", |
@@ -362,10 +332,13 @@ static struct md_personality linear_personality = | |||
362 | .owner = THIS_MODULE, | 332 | .owner = THIS_MODULE, |
363 | .make_request = linear_make_request, | 333 | .make_request = linear_make_request, |
364 | .run = linear_run, | 334 | .run = linear_run, |
365 | .stop = linear_stop, | 335 | .free = linear_free, |
366 | .status = linear_status, | 336 | .status = linear_status, |
367 | .hot_add_disk = linear_add, | 337 | .hot_add_disk = linear_add, |
368 | .size = linear_size, | 338 | .size = linear_size, |
339 | .quiesce = linear_quiesce, | ||
340 | .congested = linear_congested, | ||
341 | .mergeable_bvec = linear_mergeable_bvec, | ||
369 | }; | 342 | }; |
370 | 343 | ||
371 | static int __init linear_init (void) | 344 | static int __init linear_init (void) |