diff options
Diffstat (limited to 'drivers/md/dm-stripe.c')
-rw-r--r-- | drivers/md/dm-stripe.c | 50 |
1 files changed, 29 insertions, 21 deletions
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index c297f6da91ea..3d80cf0c152d 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c | |||
@@ -39,23 +39,20 @@ struct stripe_c { | |||
39 | struct dm_target *ti; | 39 | struct dm_target *ti; |
40 | 40 | ||
41 | /* Work struct used for triggering events*/ | 41 | /* Work struct used for triggering events*/ |
42 | struct work_struct kstriped_ws; | 42 | struct work_struct trigger_event; |
43 | 43 | ||
44 | struct stripe stripe[0]; | 44 | struct stripe stripe[0]; |
45 | }; | 45 | }; |
46 | 46 | ||
47 | static struct workqueue_struct *kstriped; | ||
48 | |||
49 | /* | 47 | /* |
50 | * An event is triggered whenever a drive | 48 | * An event is triggered whenever a drive |
51 | * drops out of a stripe volume. | 49 | * drops out of a stripe volume. |
52 | */ | 50 | */ |
53 | static void trigger_event(struct work_struct *work) | 51 | static void trigger_event(struct work_struct *work) |
54 | { | 52 | { |
55 | struct stripe_c *sc = container_of(work, struct stripe_c, kstriped_ws); | 53 | struct stripe_c *sc = container_of(work, struct stripe_c, |
56 | 54 | trigger_event); | |
57 | dm_table_event(sc->ti->table); | 55 | dm_table_event(sc->ti->table); |
58 | |||
59 | } | 56 | } |
60 | 57 | ||
61 | static inline struct stripe_c *alloc_context(unsigned int stripes) | 58 | static inline struct stripe_c *alloc_context(unsigned int stripes) |
@@ -160,7 +157,7 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
160 | return -ENOMEM; | 157 | return -ENOMEM; |
161 | } | 158 | } |
162 | 159 | ||
163 | INIT_WORK(&sc->kstriped_ws, trigger_event); | 160 | INIT_WORK(&sc->trigger_event, trigger_event); |
164 | 161 | ||
165 | /* Set pointer to dm target; used in trigger_event */ | 162 | /* Set pointer to dm target; used in trigger_event */ |
166 | sc->ti = ti; | 163 | sc->ti = ti; |
@@ -211,7 +208,7 @@ static void stripe_dtr(struct dm_target *ti) | |||
211 | for (i = 0; i < sc->stripes; i++) | 208 | for (i = 0; i < sc->stripes; i++) |
212 | dm_put_device(ti, sc->stripe[i].dev); | 209 | dm_put_device(ti, sc->stripe[i].dev); |
213 | 210 | ||
214 | flush_workqueue(kstriped); | 211 | flush_work_sync(&sc->trigger_event); |
215 | kfree(sc); | 212 | kfree(sc); |
216 | } | 213 | } |
217 | 214 | ||
@@ -271,7 +268,7 @@ static int stripe_map(struct dm_target *ti, struct bio *bio, | |||
271 | uint32_t stripe; | 268 | uint32_t stripe; |
272 | unsigned target_request_nr; | 269 | unsigned target_request_nr; |
273 | 270 | ||
274 | if (unlikely(bio_empty_barrier(bio))) { | 271 | if (bio->bi_rw & REQ_FLUSH) { |
275 | target_request_nr = map_context->target_request_nr; | 272 | target_request_nr = map_context->target_request_nr; |
276 | BUG_ON(target_request_nr >= sc->stripes); | 273 | BUG_ON(target_request_nr >= sc->stripes); |
277 | bio->bi_bdev = sc->stripe[target_request_nr].dev->bdev; | 274 | bio->bi_bdev = sc->stripe[target_request_nr].dev->bdev; |
@@ -367,7 +364,7 @@ static int stripe_end_io(struct dm_target *ti, struct bio *bio, | |||
367 | atomic_inc(&(sc->stripe[i].error_count)); | 364 | atomic_inc(&(sc->stripe[i].error_count)); |
368 | if (atomic_read(&(sc->stripe[i].error_count)) < | 365 | if (atomic_read(&(sc->stripe[i].error_count)) < |
369 | DM_IO_ERROR_THRESHOLD) | 366 | DM_IO_ERROR_THRESHOLD) |
370 | queue_work(kstriped, &sc->kstriped_ws); | 367 | schedule_work(&sc->trigger_event); |
371 | } | 368 | } |
372 | 369 | ||
373 | return error; | 370 | return error; |
@@ -399,9 +396,29 @@ static void stripe_io_hints(struct dm_target *ti, | |||
399 | blk_limits_io_opt(limits, chunk_size * sc->stripes); | 396 | blk_limits_io_opt(limits, chunk_size * sc->stripes); |
400 | } | 397 | } |
401 | 398 | ||
399 | static int stripe_merge(struct dm_target *ti, struct bvec_merge_data *bvm, | ||
400 | struct bio_vec *biovec, int max_size) | ||
401 | { | ||
402 | struct stripe_c *sc = ti->private; | ||
403 | sector_t bvm_sector = bvm->bi_sector; | ||
404 | uint32_t stripe; | ||
405 | struct request_queue *q; | ||
406 | |||
407 | stripe_map_sector(sc, bvm_sector, &stripe, &bvm_sector); | ||
408 | |||
409 | q = bdev_get_queue(sc->stripe[stripe].dev->bdev); | ||
410 | if (!q->merge_bvec_fn) | ||
411 | return max_size; | ||
412 | |||
413 | bvm->bi_bdev = sc->stripe[stripe].dev->bdev; | ||
414 | bvm->bi_sector = sc->stripe[stripe].physical_start + bvm_sector; | ||
415 | |||
416 | return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); | ||
417 | } | ||
418 | |||
402 | static struct target_type stripe_target = { | 419 | static struct target_type stripe_target = { |
403 | .name = "striped", | 420 | .name = "striped", |
404 | .version = {1, 3, 0}, | 421 | .version = {1, 4, 0}, |
405 | .module = THIS_MODULE, | 422 | .module = THIS_MODULE, |
406 | .ctr = stripe_ctr, | 423 | .ctr = stripe_ctr, |
407 | .dtr = stripe_dtr, | 424 | .dtr = stripe_dtr, |
@@ -410,6 +427,7 @@ static struct target_type stripe_target = { | |||
410 | .status = stripe_status, | 427 | .status = stripe_status, |
411 | .iterate_devices = stripe_iterate_devices, | 428 | .iterate_devices = stripe_iterate_devices, |
412 | .io_hints = stripe_io_hints, | 429 | .io_hints = stripe_io_hints, |
430 | .merge = stripe_merge, | ||
413 | }; | 431 | }; |
414 | 432 | ||
415 | int __init dm_stripe_init(void) | 433 | int __init dm_stripe_init(void) |
@@ -422,20 +440,10 @@ int __init dm_stripe_init(void) | |||
422 | return r; | 440 | return r; |
423 | } | 441 | } |
424 | 442 | ||
425 | kstriped = create_singlethread_workqueue("kstriped"); | ||
426 | if (!kstriped) { | ||
427 | DMERR("failed to create workqueue kstriped"); | ||
428 | dm_unregister_target(&stripe_target); | ||
429 | return -ENOMEM; | ||
430 | } | ||
431 | |||
432 | return r; | 443 | return r; |
433 | } | 444 | } |
434 | 445 | ||
435 | void dm_stripe_exit(void) | 446 | void dm_stripe_exit(void) |
436 | { | 447 | { |
437 | dm_unregister_target(&stripe_target); | 448 | dm_unregister_target(&stripe_target); |
438 | destroy_workqueue(kstriped); | ||
439 | |||
440 | return; | ||
441 | } | 449 | } |