diff options
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/Kconfig | 12 | ||||
-rw-r--r-- | drivers/md/Makefile | 6 | ||||
-rw-r--r-- | drivers/md/dm-bio-list.h | 5 | ||||
-rw-r--r-- | drivers/md/dm-crypt.c | 172 | ||||
-rw-r--r-- | drivers/md/dm-delay.c | 23 | ||||
-rw-r--r-- | drivers/md/dm-emc.c | 8 | ||||
-rw-r--r-- | drivers/md/dm-hw-handler.c | 6 | ||||
-rw-r--r-- | drivers/md/dm-hw-handler.h | 1 | ||||
-rw-r--r-- | drivers/md/dm-ioctl.c | 40 | ||||
-rw-r--r-- | drivers/md/dm-log.c | 2 | ||||
-rw-r--r-- | drivers/md/dm-log.h | 3 | ||||
-rw-r--r-- | drivers/md/dm-mpath-hp-sw.c | 248 | ||||
-rw-r--r-- | drivers/md/dm-mpath-rdac.c | 15 | ||||
-rw-r--r-- | drivers/md/dm-mpath.c | 88 | ||||
-rw-r--r-- | drivers/md/dm-path-selector.c | 6 | ||||
-rw-r--r-- | drivers/md/dm-raid1.c | 35 | ||||
-rw-r--r-- | drivers/md/dm-snap.c | 3 | ||||
-rw-r--r-- | drivers/md/dm-stripe.c | 3 | ||||
-rw-r--r-- | drivers/md/dm-table.c | 3 | ||||
-rw-r--r-- | drivers/md/dm-target.c | 6 | ||||
-rw-r--r-- | drivers/md/dm-uevent.c | 222 | ||||
-rw-r--r-- | drivers/md/dm-uevent.h | 59 | ||||
-rw-r--r-- | drivers/md/dm.c | 79 | ||||
-rw-r--r-- | drivers/md/kcopyd.c | 8 | ||||
-rw-r--r-- | drivers/md/raid1.c | 2 |
25 files changed, 883 insertions, 172 deletions
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 34a8c60a254a..9b6fbf044fd8 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig | |||
@@ -267,6 +267,12 @@ config DM_MULTIPATH_RDAC | |||
267 | ---help--- | 267 | ---help--- |
268 | Multipath support for LSI/Engenio RDAC. | 268 | Multipath support for LSI/Engenio RDAC. |
269 | 269 | ||
270 | config DM_MULTIPATH_HP | ||
271 | tristate "HP MSA multipath support (EXPERIMENTAL)" | ||
272 | depends on DM_MULTIPATH && BLK_DEV_DM && EXPERIMENTAL | ||
273 | ---help--- | ||
274 | Multipath support for HP MSA (Active/Passive) series hardware. | ||
275 | |||
270 | config DM_DELAY | 276 | config DM_DELAY |
271 | tristate "I/O delaying target (EXPERIMENTAL)" | 277 | tristate "I/O delaying target (EXPERIMENTAL)" |
272 | depends on BLK_DEV_DM && EXPERIMENTAL | 278 | depends on BLK_DEV_DM && EXPERIMENTAL |
@@ -276,4 +282,10 @@ config DM_DELAY | |||
276 | 282 | ||
277 | If unsure, say N. | 283 | If unsure, say N. |
278 | 284 | ||
285 | config DM_UEVENT | ||
286 | bool "DM uevents (EXPERIMENTAL)" | ||
287 | depends on BLK_DEV_DM && EXPERIMENTAL | ||
288 | ---help--- | ||
289 | Generate udev events for DM events. | ||
290 | |||
279 | endif # MD | 291 | endif # MD |
diff --git a/drivers/md/Makefile b/drivers/md/Makefile index c49366cdc05d..d9aa7edb8780 100644 --- a/drivers/md/Makefile +++ b/drivers/md/Makefile | |||
@@ -8,6 +8,7 @@ dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o | |||
8 | dm-snapshot-objs := dm-snap.o dm-exception-store.o | 8 | dm-snapshot-objs := dm-snap.o dm-exception-store.o |
9 | dm-mirror-objs := dm-log.o dm-raid1.o | 9 | dm-mirror-objs := dm-log.o dm-raid1.o |
10 | dm-rdac-objs := dm-mpath-rdac.o | 10 | dm-rdac-objs := dm-mpath-rdac.o |
11 | dm-hp-sw-objs := dm-mpath-hp-sw.o | ||
11 | md-mod-objs := md.o bitmap.o | 12 | md-mod-objs := md.o bitmap.o |
12 | raid456-objs := raid5.o raid6algos.o raid6recov.o raid6tables.o \ | 13 | raid456-objs := raid5.o raid6algos.o raid6recov.o raid6tables.o \ |
13 | raid6int1.o raid6int2.o raid6int4.o \ | 14 | raid6int1.o raid6int2.o raid6int4.o \ |
@@ -35,6 +36,7 @@ obj-$(CONFIG_DM_CRYPT) += dm-crypt.o | |||
35 | obj-$(CONFIG_DM_DELAY) += dm-delay.o | 36 | obj-$(CONFIG_DM_DELAY) += dm-delay.o |
36 | obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o | 37 | obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o |
37 | obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc.o | 38 | obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc.o |
39 | obj-$(CONFIG_DM_MULTIPATH_HP) += dm-hp-sw.o | ||
38 | obj-$(CONFIG_DM_MULTIPATH_RDAC) += dm-rdac.o | 40 | obj-$(CONFIG_DM_MULTIPATH_RDAC) += dm-rdac.o |
39 | obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o | 41 | obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o |
40 | obj-$(CONFIG_DM_MIRROR) += dm-mirror.o | 42 | obj-$(CONFIG_DM_MIRROR) += dm-mirror.o |
@@ -48,6 +50,10 @@ ifeq ($(CONFIG_ALTIVEC),y) | |||
48 | altivec_flags := -maltivec -mabi=altivec | 50 | altivec_flags := -maltivec -mabi=altivec |
49 | endif | 51 | endif |
50 | 52 | ||
53 | ifeq ($(CONFIG_DM_UEVENT),y) | ||
54 | dm-mod-objs += dm-uevent.o | ||
55 | endif | ||
56 | |||
51 | targets += raid6int1.c | 57 | targets += raid6int1.c |
52 | $(obj)/raid6int1.c: UNROLL := 1 | 58 | $(obj)/raid6int1.c: UNROLL := 1 |
53 | $(obj)/raid6int1.c: $(src)/raid6int.uc $(src)/unroll.pl FORCE | 59 | $(obj)/raid6int1.c: $(src)/raid6int.uc $(src)/unroll.pl FORCE |
diff --git a/drivers/md/dm-bio-list.h b/drivers/md/dm-bio-list.h index 3f7b827649e3..d4509be0fe67 100644 --- a/drivers/md/dm-bio-list.h +++ b/drivers/md/dm-bio-list.h | |||
@@ -21,11 +21,6 @@ static inline int bio_list_empty(const struct bio_list *bl) | |||
21 | return bl->head == NULL; | 21 | return bl->head == NULL; |
22 | } | 22 | } |
23 | 23 | ||
24 | #define BIO_LIST_INIT { .head = NULL, .tail = NULL } | ||
25 | |||
26 | #define BIO_LIST(bl) \ | ||
27 | struct bio_list bl = BIO_LIST_INIT | ||
28 | |||
29 | static inline void bio_list_init(struct bio_list *bl) | 24 | static inline void bio_list_init(struct bio_list *bl) |
30 | { | 25 | { |
31 | bl->head = bl->tail = NULL; | 26 | bl->head = bl->tail = NULL; |
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 64fee90bb68b..0eb5416798bd 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
@@ -36,7 +36,6 @@ struct dm_crypt_io { | |||
36 | struct work_struct work; | 36 | struct work_struct work; |
37 | atomic_t pending; | 37 | atomic_t pending; |
38 | int error; | 38 | int error; |
39 | int post_process; | ||
40 | }; | 39 | }; |
41 | 40 | ||
42 | /* | 41 | /* |
@@ -57,7 +56,7 @@ struct crypt_config; | |||
57 | 56 | ||
58 | struct crypt_iv_operations { | 57 | struct crypt_iv_operations { |
59 | int (*ctr)(struct crypt_config *cc, struct dm_target *ti, | 58 | int (*ctr)(struct crypt_config *cc, struct dm_target *ti, |
60 | const char *opts); | 59 | const char *opts); |
61 | void (*dtr)(struct crypt_config *cc); | 60 | void (*dtr)(struct crypt_config *cc); |
62 | const char *(*status)(struct crypt_config *cc); | 61 | const char *(*status)(struct crypt_config *cc); |
63 | int (*generator)(struct crypt_config *cc, u8 *iv, sector_t sector); | 62 | int (*generator)(struct crypt_config *cc, u8 *iv, sector_t sector); |
@@ -80,6 +79,8 @@ struct crypt_config { | |||
80 | mempool_t *page_pool; | 79 | mempool_t *page_pool; |
81 | struct bio_set *bs; | 80 | struct bio_set *bs; |
82 | 81 | ||
82 | struct workqueue_struct *io_queue; | ||
83 | struct workqueue_struct *crypt_queue; | ||
83 | /* | 84 | /* |
84 | * crypto related data | 85 | * crypto related data |
85 | */ | 86 | */ |
@@ -112,7 +113,7 @@ static void clone_init(struct dm_crypt_io *, struct bio *); | |||
112 | * Different IV generation algorithms: | 113 | * Different IV generation algorithms: |
113 | * | 114 | * |
114 | * plain: the initial vector is the 32-bit little-endian version of the sector | 115 | * plain: the initial vector is the 32-bit little-endian version of the sector |
115 | * number, padded with zeros if neccessary. | 116 | * number, padded with zeros if necessary. |
116 | * | 117 | * |
117 | * essiv: "encrypted sector|salt initial vector", the sector number is | 118 | * essiv: "encrypted sector|salt initial vector", the sector number is |
118 | * encrypted with the bulk cipher using a salt as key. The salt | 119 | * encrypted with the bulk cipher using a salt as key. The salt |
@@ -137,7 +138,7 @@ static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv, sector_t sector) | |||
137 | } | 138 | } |
138 | 139 | ||
139 | static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, | 140 | static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, |
140 | const char *opts) | 141 | const char *opts) |
141 | { | 142 | { |
142 | struct crypto_cipher *essiv_tfm; | 143 | struct crypto_cipher *essiv_tfm; |
143 | struct crypto_hash *hash_tfm; | 144 | struct crypto_hash *hash_tfm; |
@@ -175,6 +176,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, | |||
175 | 176 | ||
176 | if (err) { | 177 | if (err) { |
177 | ti->error = "Error calculating hash in ESSIV"; | 178 | ti->error = "Error calculating hash in ESSIV"; |
179 | kfree(salt); | ||
178 | return err; | 180 | return err; |
179 | } | 181 | } |
180 | 182 | ||
@@ -188,7 +190,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, | |||
188 | if (crypto_cipher_blocksize(essiv_tfm) != | 190 | if (crypto_cipher_blocksize(essiv_tfm) != |
189 | crypto_blkcipher_ivsize(cc->tfm)) { | 191 | crypto_blkcipher_ivsize(cc->tfm)) { |
190 | ti->error = "Block size of ESSIV cipher does " | 192 | ti->error = "Block size of ESSIV cipher does " |
191 | "not match IV size of block cipher"; | 193 | "not match IV size of block cipher"; |
192 | crypto_free_cipher(essiv_tfm); | 194 | crypto_free_cipher(essiv_tfm); |
193 | kfree(salt); | 195 | kfree(salt); |
194 | return -EINVAL; | 196 | return -EINVAL; |
@@ -319,10 +321,10 @@ crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, | |||
319 | return r; | 321 | return r; |
320 | } | 322 | } |
321 | 323 | ||
322 | static void | 324 | static void crypt_convert_init(struct crypt_config *cc, |
323 | crypt_convert_init(struct crypt_config *cc, struct convert_context *ctx, | 325 | struct convert_context *ctx, |
324 | struct bio *bio_out, struct bio *bio_in, | 326 | struct bio *bio_out, struct bio *bio_in, |
325 | sector_t sector, int write) | 327 | sector_t sector, int write) |
326 | { | 328 | { |
327 | ctx->bio_in = bio_in; | 329 | ctx->bio_in = bio_in; |
328 | ctx->bio_out = bio_out; | 330 | ctx->bio_out = bio_out; |
@@ -338,7 +340,7 @@ crypt_convert_init(struct crypt_config *cc, struct convert_context *ctx, | |||
338 | * Encrypt / decrypt data from one bio to another one (can be the same one) | 340 | * Encrypt / decrypt data from one bio to another one (can be the same one) |
339 | */ | 341 | */ |
340 | static int crypt_convert(struct crypt_config *cc, | 342 | static int crypt_convert(struct crypt_config *cc, |
341 | struct convert_context *ctx) | 343 | struct convert_context *ctx) |
342 | { | 344 | { |
343 | int r = 0; | 345 | int r = 0; |
344 | 346 | ||
@@ -370,7 +372,7 @@ static int crypt_convert(struct crypt_config *cc, | |||
370 | } | 372 | } |
371 | 373 | ||
372 | r = crypt_convert_scatterlist(cc, &sg_out, &sg_in, sg_in.length, | 374 | r = crypt_convert_scatterlist(cc, &sg_out, &sg_in, sg_in.length, |
373 | ctx->write, ctx->sector); | 375 | ctx->write, ctx->sector); |
374 | if (r < 0) | 376 | if (r < 0) |
375 | break; | 377 | break; |
376 | 378 | ||
@@ -380,13 +382,13 @@ static int crypt_convert(struct crypt_config *cc, | |||
380 | return r; | 382 | return r; |
381 | } | 383 | } |
382 | 384 | ||
383 | static void dm_crypt_bio_destructor(struct bio *bio) | 385 | static void dm_crypt_bio_destructor(struct bio *bio) |
384 | { | 386 | { |
385 | struct dm_crypt_io *io = bio->bi_private; | 387 | struct dm_crypt_io *io = bio->bi_private; |
386 | struct crypt_config *cc = io->target->private; | 388 | struct crypt_config *cc = io->target->private; |
387 | 389 | ||
388 | bio_free(bio, cc->bs); | 390 | bio_free(bio, cc->bs); |
389 | } | 391 | } |
390 | 392 | ||
391 | /* | 393 | /* |
392 | * Generate a new unfragmented bio with the given size | 394 | * Generate a new unfragmented bio with the given size |
@@ -458,7 +460,7 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone) | |||
458 | * One of the bios was finished. Check for completion of | 460 | * One of the bios was finished. Check for completion of |
459 | * the whole request and correctly clean up the buffer. | 461 | * the whole request and correctly clean up the buffer. |
460 | */ | 462 | */ |
461 | static void dec_pending(struct dm_crypt_io *io, int error) | 463 | static void crypt_dec_pending(struct dm_crypt_io *io, int error) |
462 | { | 464 | { |
463 | struct crypt_config *cc = (struct crypt_config *) io->target->private; | 465 | struct crypt_config *cc = (struct crypt_config *) io->target->private; |
464 | 466 | ||
@@ -474,18 +476,36 @@ static void dec_pending(struct dm_crypt_io *io, int error) | |||
474 | } | 476 | } |
475 | 477 | ||
476 | /* | 478 | /* |
477 | * kcryptd: | 479 | * kcryptd/kcryptd_io: |
478 | * | 480 | * |
479 | * Needed because it would be very unwise to do decryption in an | 481 | * Needed because it would be very unwise to do decryption in an |
480 | * interrupt context. | 482 | * interrupt context. |
483 | * | ||
484 | * kcryptd performs the actual encryption or decryption. | ||
485 | * | ||
486 | * kcryptd_io performs the IO submission. | ||
487 | * | ||
488 | * They must be separated as otherwise the final stages could be | ||
489 | * starved by new requests which can block in the first stages due | ||
490 | * to memory allocation. | ||
481 | */ | 491 | */ |
482 | static struct workqueue_struct *_kcryptd_workqueue; | ||
483 | static void kcryptd_do_work(struct work_struct *work); | 492 | static void kcryptd_do_work(struct work_struct *work); |
493 | static void kcryptd_do_crypt(struct work_struct *work); | ||
484 | 494 | ||
485 | static void kcryptd_queue_io(struct dm_crypt_io *io) | 495 | static void kcryptd_queue_io(struct dm_crypt_io *io) |
486 | { | 496 | { |
497 | struct crypt_config *cc = io->target->private; | ||
498 | |||
487 | INIT_WORK(&io->work, kcryptd_do_work); | 499 | INIT_WORK(&io->work, kcryptd_do_work); |
488 | queue_work(_kcryptd_workqueue, &io->work); | 500 | queue_work(cc->io_queue, &io->work); |
501 | } | ||
502 | |||
503 | static void kcryptd_queue_crypt(struct dm_crypt_io *io) | ||
504 | { | ||
505 | struct crypt_config *cc = io->target->private; | ||
506 | |||
507 | INIT_WORK(&io->work, kcryptd_do_crypt); | ||
508 | queue_work(cc->crypt_queue, &io->work); | ||
489 | } | 509 | } |
490 | 510 | ||
491 | static void crypt_endio(struct bio *clone, int error) | 511 | static void crypt_endio(struct bio *clone, int error) |
@@ -508,13 +528,12 @@ static void crypt_endio(struct bio *clone, int error) | |||
508 | } | 528 | } |
509 | 529 | ||
510 | bio_put(clone); | 530 | bio_put(clone); |
511 | io->post_process = 1; | 531 | kcryptd_queue_crypt(io); |
512 | kcryptd_queue_io(io); | ||
513 | return; | 532 | return; |
514 | 533 | ||
515 | out: | 534 | out: |
516 | bio_put(clone); | 535 | bio_put(clone); |
517 | dec_pending(io, error); | 536 | crypt_dec_pending(io, error); |
518 | } | 537 | } |
519 | 538 | ||
520 | static void clone_init(struct dm_crypt_io *io, struct bio *clone) | 539 | static void clone_init(struct dm_crypt_io *io, struct bio *clone) |
@@ -544,7 +563,7 @@ static void process_read(struct dm_crypt_io *io) | |||
544 | */ | 563 | */ |
545 | clone = bio_alloc_bioset(GFP_NOIO, bio_segments(base_bio), cc->bs); | 564 | clone = bio_alloc_bioset(GFP_NOIO, bio_segments(base_bio), cc->bs); |
546 | if (unlikely(!clone)) { | 565 | if (unlikely(!clone)) { |
547 | dec_pending(io, -ENOMEM); | 566 | crypt_dec_pending(io, -ENOMEM); |
548 | return; | 567 | return; |
549 | } | 568 | } |
550 | 569 | ||
@@ -579,7 +598,7 @@ static void process_write(struct dm_crypt_io *io) | |||
579 | while (remaining) { | 598 | while (remaining) { |
580 | clone = crypt_alloc_buffer(io, remaining); | 599 | clone = crypt_alloc_buffer(io, remaining); |
581 | if (unlikely(!clone)) { | 600 | if (unlikely(!clone)) { |
582 | dec_pending(io, -ENOMEM); | 601 | crypt_dec_pending(io, -ENOMEM); |
583 | return; | 602 | return; |
584 | } | 603 | } |
585 | 604 | ||
@@ -589,7 +608,7 @@ static void process_write(struct dm_crypt_io *io) | |||
589 | if (unlikely(crypt_convert(cc, &ctx) < 0)) { | 608 | if (unlikely(crypt_convert(cc, &ctx) < 0)) { |
590 | crypt_free_buffer_pages(cc, clone); | 609 | crypt_free_buffer_pages(cc, clone); |
591 | bio_put(clone); | 610 | bio_put(clone); |
592 | dec_pending(io, -EIO); | 611 | crypt_dec_pending(io, -EIO); |
593 | return; | 612 | return; |
594 | } | 613 | } |
595 | 614 | ||
@@ -624,17 +643,23 @@ static void process_read_endio(struct dm_crypt_io *io) | |||
624 | crypt_convert_init(cc, &ctx, io->base_bio, io->base_bio, | 643 | crypt_convert_init(cc, &ctx, io->base_bio, io->base_bio, |
625 | io->base_bio->bi_sector - io->target->begin, 0); | 644 | io->base_bio->bi_sector - io->target->begin, 0); |
626 | 645 | ||
627 | dec_pending(io, crypt_convert(cc, &ctx)); | 646 | crypt_dec_pending(io, crypt_convert(cc, &ctx)); |
628 | } | 647 | } |
629 | 648 | ||
630 | static void kcryptd_do_work(struct work_struct *work) | 649 | static void kcryptd_do_work(struct work_struct *work) |
631 | { | 650 | { |
632 | struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work); | 651 | struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work); |
633 | 652 | ||
634 | if (io->post_process) | 653 | if (bio_data_dir(io->base_bio) == READ) |
635 | process_read_endio(io); | ||
636 | else if (bio_data_dir(io->base_bio) == READ) | ||
637 | process_read(io); | 654 | process_read(io); |
655 | } | ||
656 | |||
657 | static void kcryptd_do_crypt(struct work_struct *work) | ||
658 | { | ||
659 | struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work); | ||
660 | |||
661 | if (bio_data_dir(io->base_bio) == READ) | ||
662 | process_read_endio(io); | ||
638 | else | 663 | else |
639 | process_write(io); | 664 | process_write(io); |
640 | } | 665 | } |
@@ -690,7 +715,7 @@ static int crypt_set_key(struct crypt_config *cc, char *key) | |||
690 | cc->key_size = key_size; /* initial settings */ | 715 | cc->key_size = key_size; /* initial settings */ |
691 | 716 | ||
692 | if ((!key_size && strcmp(key, "-")) || | 717 | if ((!key_size && strcmp(key, "-")) || |
693 | (key_size && crypt_decode_key(cc->key, key, key_size) < 0)) | 718 | (key_size && crypt_decode_key(cc->key, key, key_size) < 0)) |
694 | return -EINVAL; | 719 | return -EINVAL; |
695 | 720 | ||
696 | set_bit(DM_CRYPT_KEY_VALID, &cc->flags); | 721 | set_bit(DM_CRYPT_KEY_VALID, &cc->flags); |
@@ -746,7 +771,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
746 | 771 | ||
747 | if (crypt_set_key(cc, argv[1])) { | 772 | if (crypt_set_key(cc, argv[1])) { |
748 | ti->error = "Error decoding key"; | 773 | ti->error = "Error decoding key"; |
749 | goto bad1; | 774 | goto bad_cipher; |
750 | } | 775 | } |
751 | 776 | ||
752 | /* Compatiblity mode for old dm-crypt cipher strings */ | 777 | /* Compatiblity mode for old dm-crypt cipher strings */ |
@@ -757,19 +782,19 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
757 | 782 | ||
758 | if (strcmp(chainmode, "ecb") && !ivmode) { | 783 | if (strcmp(chainmode, "ecb") && !ivmode) { |
759 | ti->error = "This chaining mode requires an IV mechanism"; | 784 | ti->error = "This chaining mode requires an IV mechanism"; |
760 | goto bad1; | 785 | goto bad_cipher; |
761 | } | 786 | } |
762 | 787 | ||
763 | if (snprintf(cc->cipher, CRYPTO_MAX_ALG_NAME, "%s(%s)", chainmode, | 788 | if (snprintf(cc->cipher, CRYPTO_MAX_ALG_NAME, "%s(%s)", |
764 | cipher) >= CRYPTO_MAX_ALG_NAME) { | 789 | chainmode, cipher) >= CRYPTO_MAX_ALG_NAME) { |
765 | ti->error = "Chain mode + cipher name is too long"; | 790 | ti->error = "Chain mode + cipher name is too long"; |
766 | goto bad1; | 791 | goto bad_cipher; |
767 | } | 792 | } |
768 | 793 | ||
769 | tfm = crypto_alloc_blkcipher(cc->cipher, 0, CRYPTO_ALG_ASYNC); | 794 | tfm = crypto_alloc_blkcipher(cc->cipher, 0, CRYPTO_ALG_ASYNC); |
770 | if (IS_ERR(tfm)) { | 795 | if (IS_ERR(tfm)) { |
771 | ti->error = "Error allocating crypto tfm"; | 796 | ti->error = "Error allocating crypto tfm"; |
772 | goto bad1; | 797 | goto bad_cipher; |
773 | } | 798 | } |
774 | 799 | ||
775 | strcpy(cc->cipher, cipher); | 800 | strcpy(cc->cipher, cipher); |
@@ -793,18 +818,18 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
793 | cc->iv_gen_ops = &crypt_iv_null_ops; | 818 | cc->iv_gen_ops = &crypt_iv_null_ops; |
794 | else { | 819 | else { |
795 | ti->error = "Invalid IV mode"; | 820 | ti->error = "Invalid IV mode"; |
796 | goto bad2; | 821 | goto bad_ivmode; |
797 | } | 822 | } |
798 | 823 | ||
799 | if (cc->iv_gen_ops && cc->iv_gen_ops->ctr && | 824 | if (cc->iv_gen_ops && cc->iv_gen_ops->ctr && |
800 | cc->iv_gen_ops->ctr(cc, ti, ivopts) < 0) | 825 | cc->iv_gen_ops->ctr(cc, ti, ivopts) < 0) |
801 | goto bad2; | 826 | goto bad_ivmode; |
802 | 827 | ||
803 | cc->iv_size = crypto_blkcipher_ivsize(tfm); | 828 | cc->iv_size = crypto_blkcipher_ivsize(tfm); |
804 | if (cc->iv_size) | 829 | if (cc->iv_size) |
805 | /* at least a 64 bit sector number should fit in our buffer */ | 830 | /* at least a 64 bit sector number should fit in our buffer */ |
806 | cc->iv_size = max(cc->iv_size, | 831 | cc->iv_size = max(cc->iv_size, |
807 | (unsigned int)(sizeof(u64) / sizeof(u8))); | 832 | (unsigned int)(sizeof(u64) / sizeof(u8))); |
808 | else { | 833 | else { |
809 | if (cc->iv_gen_ops) { | 834 | if (cc->iv_gen_ops) { |
810 | DMWARN("Selected cipher does not support IVs"); | 835 | DMWARN("Selected cipher does not support IVs"); |
@@ -817,13 +842,13 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
817 | cc->io_pool = mempool_create_slab_pool(MIN_IOS, _crypt_io_pool); | 842 | cc->io_pool = mempool_create_slab_pool(MIN_IOS, _crypt_io_pool); |
818 | if (!cc->io_pool) { | 843 | if (!cc->io_pool) { |
819 | ti->error = "Cannot allocate crypt io mempool"; | 844 | ti->error = "Cannot allocate crypt io mempool"; |
820 | goto bad3; | 845 | goto bad_slab_pool; |
821 | } | 846 | } |
822 | 847 | ||
823 | cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0); | 848 | cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0); |
824 | if (!cc->page_pool) { | 849 | if (!cc->page_pool) { |
825 | ti->error = "Cannot allocate page mempool"; | 850 | ti->error = "Cannot allocate page mempool"; |
826 | goto bad4; | 851 | goto bad_page_pool; |
827 | } | 852 | } |
828 | 853 | ||
829 | cc->bs = bioset_create(MIN_IOS, MIN_IOS); | 854 | cc->bs = bioset_create(MIN_IOS, MIN_IOS); |
@@ -834,25 +859,25 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
834 | 859 | ||
835 | if (crypto_blkcipher_setkey(tfm, cc->key, key_size) < 0) { | 860 | if (crypto_blkcipher_setkey(tfm, cc->key, key_size) < 0) { |
836 | ti->error = "Error setting key"; | 861 | ti->error = "Error setting key"; |
837 | goto bad5; | 862 | goto bad_device; |
838 | } | 863 | } |
839 | 864 | ||
840 | if (sscanf(argv[2], "%llu", &tmpll) != 1) { | 865 | if (sscanf(argv[2], "%llu", &tmpll) != 1) { |
841 | ti->error = "Invalid iv_offset sector"; | 866 | ti->error = "Invalid iv_offset sector"; |
842 | goto bad5; | 867 | goto bad_device; |
843 | } | 868 | } |
844 | cc->iv_offset = tmpll; | 869 | cc->iv_offset = tmpll; |
845 | 870 | ||
846 | if (sscanf(argv[4], "%llu", &tmpll) != 1) { | 871 | if (sscanf(argv[4], "%llu", &tmpll) != 1) { |
847 | ti->error = "Invalid device sector"; | 872 | ti->error = "Invalid device sector"; |
848 | goto bad5; | 873 | goto bad_device; |
849 | } | 874 | } |
850 | cc->start = tmpll; | 875 | cc->start = tmpll; |
851 | 876 | ||
852 | if (dm_get_device(ti, argv[3], cc->start, ti->len, | 877 | if (dm_get_device(ti, argv[3], cc->start, ti->len, |
853 | dm_table_get_mode(ti->table), &cc->dev)) { | 878 | dm_table_get_mode(ti->table), &cc->dev)) { |
854 | ti->error = "Device lookup failed"; | 879 | ti->error = "Device lookup failed"; |
855 | goto bad5; | 880 | goto bad_device; |
856 | } | 881 | } |
857 | 882 | ||
858 | if (ivmode && cc->iv_gen_ops) { | 883 | if (ivmode && cc->iv_gen_ops) { |
@@ -861,27 +886,45 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
861 | cc->iv_mode = kmalloc(strlen(ivmode) + 1, GFP_KERNEL); | 886 | cc->iv_mode = kmalloc(strlen(ivmode) + 1, GFP_KERNEL); |
862 | if (!cc->iv_mode) { | 887 | if (!cc->iv_mode) { |
863 | ti->error = "Error kmallocing iv_mode string"; | 888 | ti->error = "Error kmallocing iv_mode string"; |
864 | goto bad5; | 889 | goto bad_ivmode_string; |
865 | } | 890 | } |
866 | strcpy(cc->iv_mode, ivmode); | 891 | strcpy(cc->iv_mode, ivmode); |
867 | } else | 892 | } else |
868 | cc->iv_mode = NULL; | 893 | cc->iv_mode = NULL; |
869 | 894 | ||
895 | cc->io_queue = create_singlethread_workqueue("kcryptd_io"); | ||
896 | if (!cc->io_queue) { | ||
897 | ti->error = "Couldn't create kcryptd io queue"; | ||
898 | goto bad_io_queue; | ||
899 | } | ||
900 | |||
901 | cc->crypt_queue = create_singlethread_workqueue("kcryptd"); | ||
902 | if (!cc->crypt_queue) { | ||
903 | ti->error = "Couldn't create kcryptd queue"; | ||
904 | goto bad_crypt_queue; | ||
905 | } | ||
906 | |||
870 | ti->private = cc; | 907 | ti->private = cc; |
871 | return 0; | 908 | return 0; |
872 | 909 | ||
873 | bad5: | 910 | bad_crypt_queue: |
911 | destroy_workqueue(cc->io_queue); | ||
912 | bad_io_queue: | ||
913 | kfree(cc->iv_mode); | ||
914 | bad_ivmode_string: | ||
915 | dm_put_device(ti, cc->dev); | ||
916 | bad_device: | ||
874 | bioset_free(cc->bs); | 917 | bioset_free(cc->bs); |
875 | bad_bs: | 918 | bad_bs: |
876 | mempool_destroy(cc->page_pool); | 919 | mempool_destroy(cc->page_pool); |
877 | bad4: | 920 | bad_page_pool: |
878 | mempool_destroy(cc->io_pool); | 921 | mempool_destroy(cc->io_pool); |
879 | bad3: | 922 | bad_slab_pool: |
880 | if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) | 923 | if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) |
881 | cc->iv_gen_ops->dtr(cc); | 924 | cc->iv_gen_ops->dtr(cc); |
882 | bad2: | 925 | bad_ivmode: |
883 | crypto_free_blkcipher(tfm); | 926 | crypto_free_blkcipher(tfm); |
884 | bad1: | 927 | bad_cipher: |
885 | /* Must zero key material before freeing */ | 928 | /* Must zero key material before freeing */ |
886 | memset(cc, 0, sizeof(*cc) + cc->key_size * sizeof(u8)); | 929 | memset(cc, 0, sizeof(*cc) + cc->key_size * sizeof(u8)); |
887 | kfree(cc); | 930 | kfree(cc); |
@@ -892,7 +935,8 @@ static void crypt_dtr(struct dm_target *ti) | |||
892 | { | 935 | { |
893 | struct crypt_config *cc = (struct crypt_config *) ti->private; | 936 | struct crypt_config *cc = (struct crypt_config *) ti->private; |
894 | 937 | ||
895 | flush_workqueue(_kcryptd_workqueue); | 938 | destroy_workqueue(cc->io_queue); |
939 | destroy_workqueue(cc->crypt_queue); | ||
896 | 940 | ||
897 | bioset_free(cc->bs); | 941 | bioset_free(cc->bs); |
898 | mempool_destroy(cc->page_pool); | 942 | mempool_destroy(cc->page_pool); |
@@ -918,9 +962,13 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, | |||
918 | io = mempool_alloc(cc->io_pool, GFP_NOIO); | 962 | io = mempool_alloc(cc->io_pool, GFP_NOIO); |
919 | io->target = ti; | 963 | io->target = ti; |
920 | io->base_bio = bio; | 964 | io->base_bio = bio; |
921 | io->error = io->post_process = 0; | 965 | io->error = 0; |
922 | atomic_set(&io->pending, 0); | 966 | atomic_set(&io->pending, 0); |
923 | kcryptd_queue_io(io); | 967 | |
968 | if (bio_data_dir(io->base_bio) == READ) | ||
969 | kcryptd_queue_io(io); | ||
970 | else | ||
971 | kcryptd_queue_crypt(io); | ||
924 | 972 | ||
925 | return DM_MAPIO_SUBMITTED; | 973 | return DM_MAPIO_SUBMITTED; |
926 | } | 974 | } |
@@ -1037,25 +1085,12 @@ static int __init dm_crypt_init(void) | |||
1037 | if (!_crypt_io_pool) | 1085 | if (!_crypt_io_pool) |
1038 | return -ENOMEM; | 1086 | return -ENOMEM; |
1039 | 1087 | ||
1040 | _kcryptd_workqueue = create_workqueue("kcryptd"); | ||
1041 | if (!_kcryptd_workqueue) { | ||
1042 | r = -ENOMEM; | ||
1043 | DMERR("couldn't create kcryptd"); | ||
1044 | goto bad1; | ||
1045 | } | ||
1046 | |||
1047 | r = dm_register_target(&crypt_target); | 1088 | r = dm_register_target(&crypt_target); |
1048 | if (r < 0) { | 1089 | if (r < 0) { |
1049 | DMERR("register failed %d", r); | 1090 | DMERR("register failed %d", r); |
1050 | goto bad2; | 1091 | kmem_cache_destroy(_crypt_io_pool); |
1051 | } | 1092 | } |
1052 | 1093 | ||
1053 | return 0; | ||
1054 | |||
1055 | bad2: | ||
1056 | destroy_workqueue(_kcryptd_workqueue); | ||
1057 | bad1: | ||
1058 | kmem_cache_destroy(_crypt_io_pool); | ||
1059 | return r; | 1094 | return r; |
1060 | } | 1095 | } |
1061 | 1096 | ||
@@ -1066,7 +1101,6 @@ static void __exit dm_crypt_exit(void) | |||
1066 | if (r < 0) | 1101 | if (r < 0) |
1067 | DMERR("unregister failed %d", r); | 1102 | DMERR("unregister failed %d", r); |
1068 | 1103 | ||
1069 | destroy_workqueue(_kcryptd_workqueue); | ||
1070 | kmem_cache_destroy(_crypt_io_pool); | 1104 | kmem_cache_destroy(_crypt_io_pool); |
1071 | } | 1105 | } |
1072 | 1106 | ||
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c index 6928c136d3c5..bdd37f881c42 100644 --- a/drivers/md/dm-delay.c +++ b/drivers/md/dm-delay.c | |||
@@ -83,7 +83,7 @@ static struct bio *flush_delayed_bios(struct delay_c *dc, int flush_all) | |||
83 | struct dm_delay_info *delayed, *next; | 83 | struct dm_delay_info *delayed, *next; |
84 | unsigned long next_expires = 0; | 84 | unsigned long next_expires = 0; |
85 | int start_timer = 0; | 85 | int start_timer = 0; |
86 | BIO_LIST(flush_bios); | 86 | struct bio_list flush_bios = { }; |
87 | 87 | ||
88 | mutex_lock(&delayed_bios_lock); | 88 | mutex_lock(&delayed_bios_lock); |
89 | list_for_each_entry_safe(delayed, next, &dc->delayed_bios, list) { | 89 | list_for_each_entry_safe(delayed, next, &dc->delayed_bios, list) { |
@@ -163,34 +163,32 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
163 | goto bad; | 163 | goto bad; |
164 | } | 164 | } |
165 | 165 | ||
166 | if (argc == 3) { | 166 | dc->dev_write = NULL; |
167 | dc->dev_write = NULL; | 167 | if (argc == 3) |
168 | goto out; | 168 | goto out; |
169 | } | ||
170 | 169 | ||
171 | if (sscanf(argv[4], "%llu", &tmpll) != 1) { | 170 | if (sscanf(argv[4], "%llu", &tmpll) != 1) { |
172 | ti->error = "Invalid write device sector"; | 171 | ti->error = "Invalid write device sector"; |
173 | goto bad; | 172 | goto bad_dev_read; |
174 | } | 173 | } |
175 | dc->start_write = tmpll; | 174 | dc->start_write = tmpll; |
176 | 175 | ||
177 | if (sscanf(argv[5], "%u", &dc->write_delay) != 1) { | 176 | if (sscanf(argv[5], "%u", &dc->write_delay) != 1) { |
178 | ti->error = "Invalid write delay"; | 177 | ti->error = "Invalid write delay"; |
179 | goto bad; | 178 | goto bad_dev_read; |
180 | } | 179 | } |
181 | 180 | ||
182 | if (dm_get_device(ti, argv[3], dc->start_write, ti->len, | 181 | if (dm_get_device(ti, argv[3], dc->start_write, ti->len, |
183 | dm_table_get_mode(ti->table), &dc->dev_write)) { | 182 | dm_table_get_mode(ti->table), &dc->dev_write)) { |
184 | ti->error = "Write device lookup failed"; | 183 | ti->error = "Write device lookup failed"; |
185 | dm_put_device(ti, dc->dev_read); | 184 | goto bad_dev_read; |
186 | goto bad; | ||
187 | } | 185 | } |
188 | 186 | ||
189 | out: | 187 | out: |
190 | dc->delayed_pool = mempool_create_slab_pool(128, delayed_cache); | 188 | dc->delayed_pool = mempool_create_slab_pool(128, delayed_cache); |
191 | if (!dc->delayed_pool) { | 189 | if (!dc->delayed_pool) { |
192 | DMERR("Couldn't create delayed bio pool."); | 190 | DMERR("Couldn't create delayed bio pool."); |
193 | goto bad; | 191 | goto bad_dev_write; |
194 | } | 192 | } |
195 | 193 | ||
196 | setup_timer(&dc->delay_timer, handle_delayed_timer, (unsigned long)dc); | 194 | setup_timer(&dc->delay_timer, handle_delayed_timer, (unsigned long)dc); |
@@ -203,6 +201,11 @@ out: | |||
203 | ti->private = dc; | 201 | ti->private = dc; |
204 | return 0; | 202 | return 0; |
205 | 203 | ||
204 | bad_dev_write: | ||
205 | if (dc->dev_write) | ||
206 | dm_put_device(ti, dc->dev_write); | ||
207 | bad_dev_read: | ||
208 | dm_put_device(ti, dc->dev_read); | ||
206 | bad: | 209 | bad: |
207 | kfree(dc); | 210 | kfree(dc); |
208 | return -EINVAL; | 211 | return -EINVAL; |
@@ -305,7 +308,7 @@ static int delay_status(struct dm_target *ti, status_type_t type, | |||
305 | (unsigned long long) dc->start_read, | 308 | (unsigned long long) dc->start_read, |
306 | dc->read_delay); | 309 | dc->read_delay); |
307 | if (dc->dev_write) | 310 | if (dc->dev_write) |
308 | DMEMIT("%s %llu %u", dc->dev_write->name, | 311 | DMEMIT(" %s %llu %u", dc->dev_write->name, |
309 | (unsigned long long) dc->start_write, | 312 | (unsigned long long) dc->start_write, |
310 | dc->write_delay); | 313 | dc->write_delay); |
311 | break; | 314 | break; |
diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c index 342517261ece..6b91b9ab1d41 100644 --- a/drivers/md/dm-emc.c +++ b/drivers/md/dm-emc.c | |||
@@ -81,7 +81,7 @@ static struct bio *get_failover_bio(struct dm_path *path, unsigned data_size) | |||
81 | } | 81 | } |
82 | 82 | ||
83 | if (bio_add_page(bio, page, data_size, 0) != data_size) { | 83 | if (bio_add_page(bio, page, data_size, 0) != data_size) { |
84 | DMERR("get_failover_bio: alloc_page() failed."); | 84 | DMERR("get_failover_bio: bio_add_page() failed."); |
85 | __free_page(page); | 85 | __free_page(page); |
86 | bio_put(bio); | 86 | bio_put(bio); |
87 | return NULL; | 87 | return NULL; |
@@ -211,12 +211,10 @@ fail_path: | |||
211 | 211 | ||
212 | static struct emc_handler *alloc_emc_handler(void) | 212 | static struct emc_handler *alloc_emc_handler(void) |
213 | { | 213 | { |
214 | struct emc_handler *h = kmalloc(sizeof(*h), GFP_KERNEL); | 214 | struct emc_handler *h = kzalloc(sizeof(*h), GFP_KERNEL); |
215 | 215 | ||
216 | if (h) { | 216 | if (h) |
217 | memset(h, 0, sizeof(*h)); | ||
218 | spin_lock_init(&h->lock); | 217 | spin_lock_init(&h->lock); |
219 | } | ||
220 | 218 | ||
221 | return h; | 219 | return h; |
222 | } | 220 | } |
diff --git a/drivers/md/dm-hw-handler.c b/drivers/md/dm-hw-handler.c index baafaaba4d4b..2ee84d8aa0bf 100644 --- a/drivers/md/dm-hw-handler.c +++ b/drivers/md/dm-hw-handler.c | |||
@@ -91,12 +91,10 @@ void dm_put_hw_handler(struct hw_handler_type *hwht) | |||
91 | 91 | ||
92 | static struct hwh_internal *_alloc_hw_handler(struct hw_handler_type *hwht) | 92 | static struct hwh_internal *_alloc_hw_handler(struct hw_handler_type *hwht) |
93 | { | 93 | { |
94 | struct hwh_internal *hwhi = kmalloc(sizeof(*hwhi), GFP_KERNEL); | 94 | struct hwh_internal *hwhi = kzalloc(sizeof(*hwhi), GFP_KERNEL); |
95 | 95 | ||
96 | if (hwhi) { | 96 | if (hwhi) |
97 | memset(hwhi, 0, sizeof(*hwhi)); | ||
98 | hwhi->hwht = *hwht; | 97 | hwhi->hwht = *hwht; |
99 | } | ||
100 | 98 | ||
101 | return hwhi; | 99 | return hwhi; |
102 | } | 100 | } |
diff --git a/drivers/md/dm-hw-handler.h b/drivers/md/dm-hw-handler.h index e0832e6fcf36..46809dcb121a 100644 --- a/drivers/md/dm-hw-handler.h +++ b/drivers/md/dm-hw-handler.h | |||
@@ -58,5 +58,6 @@ unsigned dm_scsi_err_handler(struct hw_handler *hwh, struct bio *bio); | |||
58 | #define MP_FAIL_PATH 1 | 58 | #define MP_FAIL_PATH 1 |
59 | #define MP_BYPASS_PG 2 | 59 | #define MP_BYPASS_PG 2 |
60 | #define MP_ERROR_IO 4 /* Don't retry this I/O */ | 60 | #define MP_ERROR_IO 4 /* Don't retry this I/O */ |
61 | #define MP_RETRY 8 | ||
61 | 62 | ||
62 | #endif | 63 | #endif |
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index b441d82c338a..138200bf5e0b 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c | |||
@@ -700,7 +700,7 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size) | |||
700 | int r; | 700 | int r; |
701 | char *new_name = (char *) param + param->data_start; | 701 | char *new_name = (char *) param + param->data_start; |
702 | 702 | ||
703 | if (new_name < (char *) (param + 1) || | 703 | if (new_name < (char *) param->data || |
704 | invalid_str(new_name, (void *) param + param_size)) { | 704 | invalid_str(new_name, (void *) param + param_size)) { |
705 | DMWARN("Invalid new logical volume name supplied."); | 705 | DMWARN("Invalid new logical volume name supplied."); |
706 | return -EINVAL; | 706 | return -EINVAL; |
@@ -726,7 +726,7 @@ static int dev_set_geometry(struct dm_ioctl *param, size_t param_size) | |||
726 | if (!md) | 726 | if (!md) |
727 | return -ENXIO; | 727 | return -ENXIO; |
728 | 728 | ||
729 | if (geostr < (char *) (param + 1) || | 729 | if (geostr < (char *) param->data || |
730 | invalid_str(geostr, (void *) param + param_size)) { | 730 | invalid_str(geostr, (void *) param + param_size)) { |
731 | DMWARN("Invalid geometry supplied."); | 731 | DMWARN("Invalid geometry supplied."); |
732 | goto out; | 732 | goto out; |
@@ -1233,7 +1233,7 @@ static int target_message(struct dm_ioctl *param, size_t param_size) | |||
1233 | if (r) | 1233 | if (r) |
1234 | goto out; | 1234 | goto out; |
1235 | 1235 | ||
1236 | if (tmsg < (struct dm_target_msg *) (param + 1) || | 1236 | if (tmsg < (struct dm_target_msg *) param->data || |
1237 | invalid_str(tmsg->message, (void *) param + param_size)) { | 1237 | invalid_str(tmsg->message, (void *) param + param_size)) { |
1238 | DMWARN("Invalid target message parameters."); | 1238 | DMWARN("Invalid target message parameters."); |
1239 | r = -EINVAL; | 1239 | r = -EINVAL; |
@@ -1358,7 +1358,7 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param) | |||
1358 | if (tmp.data_size < sizeof(tmp)) | 1358 | if (tmp.data_size < sizeof(tmp)) |
1359 | return -EINVAL; | 1359 | return -EINVAL; |
1360 | 1360 | ||
1361 | dmi = (struct dm_ioctl *) vmalloc(tmp.data_size); | 1361 | dmi = vmalloc(tmp.data_size); |
1362 | if (!dmi) | 1362 | if (!dmi) |
1363 | return -ENOMEM; | 1363 | return -ENOMEM; |
1364 | 1364 | ||
@@ -1515,3 +1515,35 @@ void dm_interface_exit(void) | |||
1515 | 1515 | ||
1516 | dm_hash_exit(); | 1516 | dm_hash_exit(); |
1517 | } | 1517 | } |
1518 | |||
1519 | /** | ||
1520 | * dm_copy_name_and_uuid - Copy mapped device name & uuid into supplied buffers | ||
1521 | * @md: Pointer to mapped_device | ||
1522 | * @name: Buffer (size DM_NAME_LEN) for name | ||
1523 | * @uuid: Buffer (size DM_UUID_LEN) for uuid or empty string if uuid not defined | ||
1524 | */ | ||
1525 | int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid) | ||
1526 | { | ||
1527 | int r = 0; | ||
1528 | struct hash_cell *hc; | ||
1529 | |||
1530 | if (!md) | ||
1531 | return -ENXIO; | ||
1532 | |||
1533 | dm_get(md); | ||
1534 | down_read(&_hash_lock); | ||
1535 | hc = dm_get_mdptr(md); | ||
1536 | if (!hc || hc->md != md) { | ||
1537 | r = -ENXIO; | ||
1538 | goto out; | ||
1539 | } | ||
1540 | |||
1541 | strcpy(name, hc->name); | ||
1542 | strcpy(uuid, hc->uuid ? : ""); | ||
1543 | |||
1544 | out: | ||
1545 | up_read(&_hash_lock); | ||
1546 | dm_put(md); | ||
1547 | |||
1548 | return r; | ||
1549 | } | ||
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index a66428d860fe..072ee4353eab 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c | |||
@@ -696,7 +696,7 @@ static struct dirty_log_type _disk_type = { | |||
696 | .module = THIS_MODULE, | 696 | .module = THIS_MODULE, |
697 | .ctr = disk_ctr, | 697 | .ctr = disk_ctr, |
698 | .dtr = disk_dtr, | 698 | .dtr = disk_dtr, |
699 | .suspend = disk_flush, | 699 | .postsuspend = disk_flush, |
700 | .resume = disk_resume, | 700 | .resume = disk_resume, |
701 | .get_region_size = core_get_region_size, | 701 | .get_region_size = core_get_region_size, |
702 | .is_clean = core_is_clean, | 702 | .is_clean = core_is_clean, |
diff --git a/drivers/md/dm-log.h b/drivers/md/dm-log.h index 86a301c8daf1..3fae87eb5963 100644 --- a/drivers/md/dm-log.h +++ b/drivers/md/dm-log.h | |||
@@ -32,7 +32,8 @@ struct dirty_log_type { | |||
32 | * There are times when we don't want the log to touch | 32 | * There are times when we don't want the log to touch |
33 | * the disk. | 33 | * the disk. |
34 | */ | 34 | */ |
35 | int (*suspend)(struct dirty_log *log); | 35 | int (*presuspend)(struct dirty_log *log); |
36 | int (*postsuspend)(struct dirty_log *log); | ||
36 | int (*resume)(struct dirty_log *log); | 37 | int (*resume)(struct dirty_log *log); |
37 | 38 | ||
38 | /* | 39 | /* |
diff --git a/drivers/md/dm-mpath-hp-sw.c b/drivers/md/dm-mpath-hp-sw.c new file mode 100644 index 000000000000..204bf42c9449 --- /dev/null +++ b/drivers/md/dm-mpath-hp-sw.c | |||
@@ -0,0 +1,248 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 Mike Christie, All rights reserved. | ||
3 | * Copyright (C) 2007 Red Hat, Inc. All rights reserved. | ||
4 | * Authors: Mike Christie | ||
5 | * Dave Wysochanski | ||
6 | * | ||
7 | * This file is released under the GPL. | ||
8 | * | ||
9 | * This module implements the specific path activation code for | ||
10 | * HP StorageWorks and FSC FibreCat Asymmetric (Active/Passive) | ||
11 | * storage arrays. | ||
12 | * These storage arrays have controller-based failover, not | ||
13 | * LUN-based failover. However, LUN-based failover is the design | ||
14 | * of dm-multipath. Thus, this module is written for LUN-based failover. | ||
15 | */ | ||
16 | #include <linux/blkdev.h> | ||
17 | #include <linux/list.h> | ||
18 | #include <linux/types.h> | ||
19 | #include <scsi/scsi.h> | ||
20 | #include <scsi/scsi_cmnd.h> | ||
21 | #include <scsi/scsi_dbg.h> | ||
22 | |||
23 | #include "dm.h" | ||
24 | #include "dm-hw-handler.h" | ||
25 | |||
26 | #define DM_MSG_PREFIX "multipath hp-sw" | ||
27 | #define DM_HP_HWH_NAME "hp-sw" | ||
28 | #define DM_HP_HWH_VER "1.0.0" | ||
29 | |||
30 | struct hp_sw_context { | ||
31 | unsigned char sense[SCSI_SENSE_BUFFERSIZE]; | ||
32 | }; | ||
33 | |||
34 | /* | ||
35 | * hp_sw_error_is_retryable - Is an HP-specific check condition retryable? | ||
36 | * @req: path activation request | ||
37 | * | ||
38 | * Examine error codes of request and determine whether the error is retryable. | ||
39 | * Some error codes are already retried by scsi-ml (see | ||
40 | * scsi_decide_disposition), but some HP specific codes are not. | ||
41 | * The intent of this routine is to supply the logic for the HP specific | ||
42 | * check conditions. | ||
43 | * | ||
44 | * Returns: | ||
45 | * 1 - command completed with retryable error | ||
46 | * 0 - command completed with non-retryable error | ||
47 | * | ||
48 | * Possible optimizations | ||
49 | * 1. More hardware-specific error codes | ||
50 | */ | ||
51 | static int hp_sw_error_is_retryable(struct request *req) | ||
52 | { | ||
53 | /* | ||
54 | * NOT_READY is known to be retryable | ||
55 | * For now we just dump out the sense data and call it retryable | ||
56 | */ | ||
57 | if (status_byte(req->errors) == CHECK_CONDITION) | ||
58 | __scsi_print_sense(DM_HP_HWH_NAME, req->sense, req->sense_len); | ||
59 | |||
60 | /* | ||
61 | * At this point we don't have complete information about all the error | ||
62 | * codes from this hardware, so we are just conservative and retry | ||
63 | * when in doubt. | ||
64 | */ | ||
65 | return 1; | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * hp_sw_end_io - Completion handler for HP path activation. | ||
70 | * @req: path activation request | ||
71 | * @error: scsi-ml error | ||
72 | * | ||
73 | * Check sense data, free request structure, and notify dm that | ||
74 | * pg initialization has completed. | ||
75 | * | ||
76 | * Context: scsi-ml softirq | ||
77 | * | ||
78 | */ | ||
79 | static void hp_sw_end_io(struct request *req, int error) | ||
80 | { | ||
81 | struct dm_path *path = req->end_io_data; | ||
82 | unsigned err_flags = 0; | ||
83 | |||
84 | if (!error) { | ||
85 | DMDEBUG("%s path activation command - success", | ||
86 | path->dev->name); | ||
87 | goto out; | ||
88 | } | ||
89 | |||
90 | if (hp_sw_error_is_retryable(req)) { | ||
91 | DMDEBUG("%s path activation command - retry", | ||
92 | path->dev->name); | ||
93 | err_flags = MP_RETRY; | ||
94 | goto out; | ||
95 | } | ||
96 | |||
97 | DMWARN("%s path activation fail - error=0x%x", | ||
98 | path->dev->name, error); | ||
99 | err_flags = MP_FAIL_PATH; | ||
100 | |||
101 | out: | ||
102 | req->end_io_data = NULL; | ||
103 | __blk_put_request(req->q, req); | ||
104 | dm_pg_init_complete(path, err_flags); | ||
105 | } | ||
106 | |||
107 | /* | ||
108 | * hp_sw_get_request - Allocate an HP specific path activation request | ||
109 | * @path: path on which request will be sent (needed for request queue) | ||
110 | * | ||
111 | * The START command is used for path activation request. | ||
112 | * These arrays are controller-based failover, not LUN based. | ||
113 | * One START command issued to a single path will fail over all | ||
114 | * LUNs for the same controller. | ||
115 | * | ||
116 | * Possible optimizations | ||
117 | * 1. Make timeout configurable | ||
118 | * 2. Preallocate request | ||
119 | */ | ||
120 | static struct request *hp_sw_get_request(struct dm_path *path) | ||
121 | { | ||
122 | struct request *req; | ||
123 | struct block_device *bdev = path->dev->bdev; | ||
124 | struct request_queue *q = bdev_get_queue(bdev); | ||
125 | struct hp_sw_context *h = path->hwhcontext; | ||
126 | |||
127 | req = blk_get_request(q, WRITE, GFP_NOIO); | ||
128 | if (!req) | ||
129 | goto out; | ||
130 | |||
131 | req->timeout = 60 * HZ; | ||
132 | |||
133 | req->errors = 0; | ||
134 | req->cmd_type = REQ_TYPE_BLOCK_PC; | ||
135 | req->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE; | ||
136 | req->end_io_data = path; | ||
137 | req->sense = h->sense; | ||
138 | memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE); | ||
139 | |||
140 | memset(&req->cmd, 0, BLK_MAX_CDB); | ||
141 | req->cmd[0] = START_STOP; | ||
142 | req->cmd[4] = 1; | ||
143 | req->cmd_len = COMMAND_SIZE(req->cmd[0]); | ||
144 | |||
145 | out: | ||
146 | return req; | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * hp_sw_pg_init - HP path activation implementation. | ||
151 | * @hwh: hardware handler specific data | ||
152 | * @bypassed: unused; is the path group bypassed? (see dm-mpath.c) | ||
153 | * @path: path to send initialization command | ||
154 | * | ||
155 | * Send an HP-specific path activation command on 'path'. | ||
156 | * Do not try to optimize in any way, just send the activation command. | ||
157 | * More than one path activation command may be sent to the same controller. | ||
158 | * This seems to work fine for basic failover support. | ||
159 | * | ||
160 | * Possible optimizations | ||
161 | * 1. Detect an in-progress activation request and avoid submitting another one | ||
162 | * 2. Model the controller and only send a single activation request at a time | ||
163 | * 3. Determine the state of a path before sending an activation request | ||
164 | * | ||
165 | * Context: kmpathd (see process_queued_ios() in dm-mpath.c) | ||
166 | */ | ||
167 | static void hp_sw_pg_init(struct hw_handler *hwh, unsigned bypassed, | ||
168 | struct dm_path *path) | ||
169 | { | ||
170 | struct request *req; | ||
171 | struct hp_sw_context *h; | ||
172 | |||
173 | path->hwhcontext = hwh->context; | ||
174 | h = hwh->context; | ||
175 | |||
176 | req = hp_sw_get_request(path); | ||
177 | if (!req) { | ||
178 | DMERR("%s path activation command - allocation fail", | ||
179 | path->dev->name); | ||
180 | goto retry; | ||
181 | } | ||
182 | |||
183 | DMDEBUG("%s path activation command - sent", path->dev->name); | ||
184 | |||
185 | blk_execute_rq_nowait(req->q, NULL, req, 1, hp_sw_end_io); | ||
186 | return; | ||
187 | |||
188 | retry: | ||
189 | dm_pg_init_complete(path, MP_RETRY); | ||
190 | } | ||
191 | |||
192 | static int hp_sw_create(struct hw_handler *hwh, unsigned argc, char **argv) | ||
193 | { | ||
194 | struct hp_sw_context *h; | ||
195 | |||
196 | h = kmalloc(sizeof(*h), GFP_KERNEL); | ||
197 | if (!h) | ||
198 | return -ENOMEM; | ||
199 | |||
200 | hwh->context = h; | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static void hp_sw_destroy(struct hw_handler *hwh) | ||
206 | { | ||
207 | struct hp_sw_context *h = hwh->context; | ||
208 | |||
209 | kfree(h); | ||
210 | } | ||
211 | |||
212 | static struct hw_handler_type hp_sw_hwh = { | ||
213 | .name = DM_HP_HWH_NAME, | ||
214 | .module = THIS_MODULE, | ||
215 | .create = hp_sw_create, | ||
216 | .destroy = hp_sw_destroy, | ||
217 | .pg_init = hp_sw_pg_init, | ||
218 | }; | ||
219 | |||
220 | static int __init hp_sw_init(void) | ||
221 | { | ||
222 | int r; | ||
223 | |||
224 | r = dm_register_hw_handler(&hp_sw_hwh); | ||
225 | if (r < 0) | ||
226 | DMERR("register failed %d", r); | ||
227 | else | ||
228 | DMINFO("version " DM_HP_HWH_VER " loaded"); | ||
229 | |||
230 | return r; | ||
231 | } | ||
232 | |||
233 | static void __exit hp_sw_exit(void) | ||
234 | { | ||
235 | int r; | ||
236 | |||
237 | r = dm_unregister_hw_handler(&hp_sw_hwh); | ||
238 | if (r < 0) | ||
239 | DMERR("unregister failed %d", r); | ||
240 | } | ||
241 | |||
242 | module_init(hp_sw_init); | ||
243 | module_exit(hp_sw_exit); | ||
244 | |||
245 | MODULE_DESCRIPTION("DM Multipath HP StorageWorks / FSC FibreCat (A/P) support"); | ||
246 | MODULE_AUTHOR("Mike Christie, Dave Wysochanski <dm-devel@redhat.com>"); | ||
247 | MODULE_LICENSE("GPL"); | ||
248 | MODULE_VERSION(DM_HP_HWH_VER); | ||
diff --git a/drivers/md/dm-mpath-rdac.c b/drivers/md/dm-mpath-rdac.c index 16b161345775..e04eb5c697fb 100644 --- a/drivers/md/dm-mpath-rdac.c +++ b/drivers/md/dm-mpath-rdac.c | |||
@@ -664,20 +664,21 @@ static struct hw_handler_type rdac_handler = { | |||
664 | 664 | ||
665 | static int __init rdac_init(void) | 665 | static int __init rdac_init(void) |
666 | { | 666 | { |
667 | int r = dm_register_hw_handler(&rdac_handler); | 667 | int r; |
668 | |||
669 | if (r < 0) { | ||
670 | DMERR("%s: register failed %d", RDAC_DM_HWH_NAME, r); | ||
671 | return r; | ||
672 | } | ||
673 | 668 | ||
674 | rdac_wkqd = create_singlethread_workqueue("rdac_wkqd"); | 669 | rdac_wkqd = create_singlethread_workqueue("rdac_wkqd"); |
675 | if (!rdac_wkqd) { | 670 | if (!rdac_wkqd) { |
676 | DMERR("Failed to create workqueue rdac_wkqd."); | 671 | DMERR("Failed to create workqueue rdac_wkqd."); |
677 | dm_unregister_hw_handler(&rdac_handler); | ||
678 | return -ENOMEM; | 672 | return -ENOMEM; |
679 | } | 673 | } |
680 | 674 | ||
675 | r = dm_register_hw_handler(&rdac_handler); | ||
676 | if (r < 0) { | ||
677 | DMERR("%s: register failed %d", RDAC_DM_HWH_NAME, r); | ||
678 | destroy_workqueue(rdac_wkqd); | ||
679 | return r; | ||
680 | } | ||
681 | |||
681 | DMINFO("%s: version %s loaded", RDAC_DM_HWH_NAME, RDAC_DM_HWH_VER); | 682 | DMINFO("%s: version %s loaded", RDAC_DM_HWH_NAME, RDAC_DM_HWH_VER); |
682 | return 0; | 683 | return 0; |
683 | } | 684 | } |
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 31056abca89d..24b2b1e32fae 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include "dm-hw-handler.h" | 10 | #include "dm-hw-handler.h" |
11 | #include "dm-bio-list.h" | 11 | #include "dm-bio-list.h" |
12 | #include "dm-bio-record.h" | 12 | #include "dm-bio-record.h" |
13 | #include "dm-uevent.h" | ||
13 | 14 | ||
14 | #include <linux/ctype.h> | 15 | #include <linux/ctype.h> |
15 | #include <linux/init.h> | 16 | #include <linux/init.h> |
@@ -75,6 +76,8 @@ struct multipath { | |||
75 | unsigned queue_io; /* Must we queue all I/O? */ | 76 | unsigned queue_io; /* Must we queue all I/O? */ |
76 | unsigned queue_if_no_path; /* Queue I/O if last path fails? */ | 77 | unsigned queue_if_no_path; /* Queue I/O if last path fails? */ |
77 | unsigned saved_queue_if_no_path;/* Saved state during suspension */ | 78 | unsigned saved_queue_if_no_path;/* Saved state during suspension */ |
79 | unsigned pg_init_retries; /* Number of times to retry pg_init */ | ||
80 | unsigned pg_init_count; /* Number of times pg_init called */ | ||
78 | 81 | ||
79 | struct work_struct process_queued_ios; | 82 | struct work_struct process_queued_ios; |
80 | struct bio_list queued_ios; | 83 | struct bio_list queued_ios; |
@@ -225,6 +228,8 @@ static void __switch_pg(struct multipath *m, struct pgpath *pgpath) | |||
225 | m->pg_init_required = 0; | 228 | m->pg_init_required = 0; |
226 | m->queue_io = 0; | 229 | m->queue_io = 0; |
227 | } | 230 | } |
231 | |||
232 | m->pg_init_count = 0; | ||
228 | } | 233 | } |
229 | 234 | ||
230 | static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg) | 235 | static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg) |
@@ -424,6 +429,7 @@ static void process_queued_ios(struct work_struct *work) | |||
424 | must_queue = 0; | 429 | must_queue = 0; |
425 | 430 | ||
426 | if (m->pg_init_required && !m->pg_init_in_progress) { | 431 | if (m->pg_init_required && !m->pg_init_in_progress) { |
432 | m->pg_init_count++; | ||
427 | m->pg_init_required = 0; | 433 | m->pg_init_required = 0; |
428 | m->pg_init_in_progress = 1; | 434 | m->pg_init_in_progress = 1; |
429 | init_required = 1; | 435 | init_required = 1; |
@@ -689,9 +695,11 @@ static int parse_features(struct arg_set *as, struct multipath *m) | |||
689 | int r; | 695 | int r; |
690 | unsigned argc; | 696 | unsigned argc; |
691 | struct dm_target *ti = m->ti; | 697 | struct dm_target *ti = m->ti; |
698 | const char *param_name; | ||
692 | 699 | ||
693 | static struct param _params[] = { | 700 | static struct param _params[] = { |
694 | {0, 1, "invalid number of feature args"}, | 701 | {0, 3, "invalid number of feature args"}, |
702 | {1, 50, "pg_init_retries must be between 1 and 50"}, | ||
695 | }; | 703 | }; |
696 | 704 | ||
697 | r = read_param(_params, shift(as), &argc, &ti->error); | 705 | r = read_param(_params, shift(as), &argc, &ti->error); |
@@ -701,12 +709,28 @@ static int parse_features(struct arg_set *as, struct multipath *m) | |||
701 | if (!argc) | 709 | if (!argc) |
702 | return 0; | 710 | return 0; |
703 | 711 | ||
704 | if (!strnicmp(shift(as), MESG_STR("queue_if_no_path"))) | 712 | do { |
705 | return queue_if_no_path(m, 1, 0); | 713 | param_name = shift(as); |
706 | else { | 714 | argc--; |
715 | |||
716 | if (!strnicmp(param_name, MESG_STR("queue_if_no_path"))) { | ||
717 | r = queue_if_no_path(m, 1, 0); | ||
718 | continue; | ||
719 | } | ||
720 | |||
721 | if (!strnicmp(param_name, MESG_STR("pg_init_retries")) && | ||
722 | (argc >= 1)) { | ||
723 | r = read_param(_params + 1, shift(as), | ||
724 | &m->pg_init_retries, &ti->error); | ||
725 | argc--; | ||
726 | continue; | ||
727 | } | ||
728 | |||
707 | ti->error = "Unrecognised multipath feature request"; | 729 | ti->error = "Unrecognised multipath feature request"; |
708 | return -EINVAL; | 730 | r = -EINVAL; |
709 | } | 731 | } while (argc && !r); |
732 | |||
733 | return r; | ||
710 | } | 734 | } |
711 | 735 | ||
712 | static int multipath_ctr(struct dm_target *ti, unsigned int argc, | 736 | static int multipath_ctr(struct dm_target *ti, unsigned int argc, |
@@ -834,6 +858,9 @@ static int fail_path(struct pgpath *pgpath) | |||
834 | if (pgpath == m->current_pgpath) | 858 | if (pgpath == m->current_pgpath) |
835 | m->current_pgpath = NULL; | 859 | m->current_pgpath = NULL; |
836 | 860 | ||
861 | dm_path_uevent(DM_UEVENT_PATH_FAILED, m->ti, | ||
862 | pgpath->path.dev->name, m->nr_valid_paths); | ||
863 | |||
837 | queue_work(kmultipathd, &m->trigger_event); | 864 | queue_work(kmultipathd, &m->trigger_event); |
838 | 865 | ||
839 | out: | 866 | out: |
@@ -873,6 +900,9 @@ static int reinstate_path(struct pgpath *pgpath) | |||
873 | if (!m->nr_valid_paths++ && m->queue_size) | 900 | if (!m->nr_valid_paths++ && m->queue_size) |
874 | queue_work(kmultipathd, &m->process_queued_ios); | 901 | queue_work(kmultipathd, &m->process_queued_ios); |
875 | 902 | ||
903 | dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti, | ||
904 | pgpath->path.dev->name, m->nr_valid_paths); | ||
905 | |||
876 | queue_work(kmultipathd, &m->trigger_event); | 906 | queue_work(kmultipathd, &m->trigger_event); |
877 | 907 | ||
878 | out: | 908 | out: |
@@ -976,6 +1006,26 @@ static int bypass_pg_num(struct multipath *m, const char *pgstr, int bypassed) | |||
976 | } | 1006 | } |
977 | 1007 | ||
978 | /* | 1008 | /* |
1009 | * Should we retry pg_init immediately? | ||
1010 | */ | ||
1011 | static int pg_init_limit_reached(struct multipath *m, struct pgpath *pgpath) | ||
1012 | { | ||
1013 | unsigned long flags; | ||
1014 | int limit_reached = 0; | ||
1015 | |||
1016 | spin_lock_irqsave(&m->lock, flags); | ||
1017 | |||
1018 | if (m->pg_init_count <= m->pg_init_retries) | ||
1019 | m->pg_init_required = 1; | ||
1020 | else | ||
1021 | limit_reached = 1; | ||
1022 | |||
1023 | spin_unlock_irqrestore(&m->lock, flags); | ||
1024 | |||
1025 | return limit_reached; | ||
1026 | } | ||
1027 | |||
1028 | /* | ||
979 | * pg_init must call this when it has completed its initialisation | 1029 | * pg_init must call this when it has completed its initialisation |
980 | */ | 1030 | */ |
981 | void dm_pg_init_complete(struct dm_path *path, unsigned err_flags) | 1031 | void dm_pg_init_complete(struct dm_path *path, unsigned err_flags) |
@@ -985,8 +1035,14 @@ void dm_pg_init_complete(struct dm_path *path, unsigned err_flags) | |||
985 | struct multipath *m = pg->m; | 1035 | struct multipath *m = pg->m; |
986 | unsigned long flags; | 1036 | unsigned long flags; |
987 | 1037 | ||
988 | /* We insist on failing the path if the PG is already bypassed. */ | 1038 | /* |
989 | if (err_flags && pg->bypassed) | 1039 | * If requested, retry pg_init until maximum number of retries exceeded. |
1040 | * If retry not requested and PG already bypassed, always fail the path. | ||
1041 | */ | ||
1042 | if (err_flags & MP_RETRY) { | ||
1043 | if (pg_init_limit_reached(m, pgpath)) | ||
1044 | err_flags |= MP_FAIL_PATH; | ||
1045 | } else if (err_flags && pg->bypassed) | ||
990 | err_flags |= MP_FAIL_PATH; | 1046 | err_flags |= MP_FAIL_PATH; |
991 | 1047 | ||
992 | if (err_flags & MP_FAIL_PATH) | 1048 | if (err_flags & MP_FAIL_PATH) |
@@ -996,7 +1052,7 @@ void dm_pg_init_complete(struct dm_path *path, unsigned err_flags) | |||
996 | bypass_pg(m, pg, 1); | 1052 | bypass_pg(m, pg, 1); |
997 | 1053 | ||
998 | spin_lock_irqsave(&m->lock, flags); | 1054 | spin_lock_irqsave(&m->lock, flags); |
999 | if (err_flags) { | 1055 | if (err_flags & ~MP_RETRY) { |
1000 | m->current_pgpath = NULL; | 1056 | m->current_pgpath = NULL; |
1001 | m->current_pg = NULL; | 1057 | m->current_pg = NULL; |
1002 | } else if (!m->pg_init_required) | 1058 | } else if (!m->pg_init_required) |
@@ -1148,11 +1204,15 @@ static int multipath_status(struct dm_target *ti, status_type_t type, | |||
1148 | 1204 | ||
1149 | /* Features */ | 1205 | /* Features */ |
1150 | if (type == STATUSTYPE_INFO) | 1206 | if (type == STATUSTYPE_INFO) |
1151 | DMEMIT("1 %u ", m->queue_size); | 1207 | DMEMIT("2 %u %u ", m->queue_size, m->pg_init_count); |
1152 | else if (m->queue_if_no_path) | 1208 | else { |
1153 | DMEMIT("1 queue_if_no_path "); | 1209 | DMEMIT("%u ", m->queue_if_no_path + |
1154 | else | 1210 | (m->pg_init_retries > 0) * 2); |
1155 | DMEMIT("0 "); | 1211 | if (m->queue_if_no_path) |
1212 | DMEMIT("queue_if_no_path "); | ||
1213 | if (m->pg_init_retries) | ||
1214 | DMEMIT("pg_init_retries %u ", m->pg_init_retries); | ||
1215 | } | ||
1156 | 1216 | ||
1157 | if (hwh->type && hwh->type->status) | 1217 | if (hwh->type && hwh->type->status) |
1158 | sz += hwh->type->status(hwh, type, result + sz, maxlen - sz); | 1218 | sz += hwh->type->status(hwh, type, result + sz, maxlen - sz); |
diff --git a/drivers/md/dm-path-selector.c b/drivers/md/dm-path-selector.c index f10a0c89b3f4..ca1bb636a3e4 100644 --- a/drivers/md/dm-path-selector.c +++ b/drivers/md/dm-path-selector.c | |||
@@ -94,12 +94,10 @@ out: | |||
94 | 94 | ||
95 | static struct ps_internal *_alloc_path_selector(struct path_selector_type *pst) | 95 | static struct ps_internal *_alloc_path_selector(struct path_selector_type *pst) |
96 | { | 96 | { |
97 | struct ps_internal *psi = kmalloc(sizeof(*psi), GFP_KERNEL); | 97 | struct ps_internal *psi = kzalloc(sizeof(*psi), GFP_KERNEL); |
98 | 98 | ||
99 | if (psi) { | 99 | if (psi) |
100 | memset(psi, 0, sizeof(*psi)); | ||
101 | psi->pst = *pst; | 100 | psi->pst = *pst; |
102 | } | ||
103 | 101 | ||
104 | return psi; | 102 | return psi; |
105 | } | 103 | } |
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index d09ff15490a5..31123d4a6b9c 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/time.h> | 19 | #include <linux/time.h> |
20 | #include <linux/vmalloc.h> | 20 | #include <linux/vmalloc.h> |
21 | #include <linux/workqueue.h> | 21 | #include <linux/workqueue.h> |
22 | #include <linux/log2.h> | ||
22 | 23 | ||
23 | #define DM_MSG_PREFIX "raid1" | 24 | #define DM_MSG_PREFIX "raid1" |
24 | #define DM_IO_PAGES 64 | 25 | #define DM_IO_PAGES 64 |
@@ -113,6 +114,7 @@ struct region { | |||
113 | * Mirror set structures. | 114 | * Mirror set structures. |
114 | *---------------------------------------------------------------*/ | 115 | *---------------------------------------------------------------*/ |
115 | struct mirror { | 116 | struct mirror { |
117 | struct mirror_set *ms; | ||
116 | atomic_t error_count; | 118 | atomic_t error_count; |
117 | struct dm_dev *dev; | 119 | struct dm_dev *dev; |
118 | sector_t offset; | 120 | sector_t offset; |
@@ -974,6 +976,7 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors, | |||
974 | 976 | ||
975 | if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) { | 977 | if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) { |
976 | ti->error = "Error creating dirty region hash"; | 978 | ti->error = "Error creating dirty region hash"; |
979 | dm_io_client_destroy(ms->io_client); | ||
977 | kfree(ms); | 980 | kfree(ms); |
978 | return NULL; | 981 | return NULL; |
979 | } | 982 | } |
@@ -994,7 +997,7 @@ static void free_context(struct mirror_set *ms, struct dm_target *ti, | |||
994 | 997 | ||
995 | static inline int _check_region_size(struct dm_target *ti, uint32_t size) | 998 | static inline int _check_region_size(struct dm_target *ti, uint32_t size) |
996 | { | 999 | { |
997 | return !(size % (PAGE_SIZE >> 9) || (size & (size - 1)) || | 1000 | return !(size % (PAGE_SIZE >> 9) || !is_power_of_2(size) || |
998 | size > ti->len); | 1001 | size > ti->len); |
999 | } | 1002 | } |
1000 | 1003 | ||
@@ -1015,6 +1018,7 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti, | |||
1015 | return -ENXIO; | 1018 | return -ENXIO; |
1016 | } | 1019 | } |
1017 | 1020 | ||
1021 | ms->mirror[mirror].ms = ms; | ||
1018 | ms->mirror[mirror].offset = offset; | 1022 | ms->mirror[mirror].offset = offset; |
1019 | 1023 | ||
1020 | return 0; | 1024 | return 0; |
@@ -1163,16 +1167,14 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1163 | ms->kmirrord_wq = create_singlethread_workqueue("kmirrord"); | 1167 | ms->kmirrord_wq = create_singlethread_workqueue("kmirrord"); |
1164 | if (!ms->kmirrord_wq) { | 1168 | if (!ms->kmirrord_wq) { |
1165 | DMERR("couldn't start kmirrord"); | 1169 | DMERR("couldn't start kmirrord"); |
1166 | free_context(ms, ti, m); | 1170 | r = -ENOMEM; |
1167 | return -ENOMEM; | 1171 | goto err_free_context; |
1168 | } | 1172 | } |
1169 | INIT_WORK(&ms->kmirrord_work, do_mirror); | 1173 | INIT_WORK(&ms->kmirrord_work, do_mirror); |
1170 | 1174 | ||
1171 | r = parse_features(ms, argc, argv, &args_used); | 1175 | r = parse_features(ms, argc, argv, &args_used); |
1172 | if (r) { | 1176 | if (r) |
1173 | free_context(ms, ti, ms->nr_mirrors); | 1177 | goto err_destroy_wq; |
1174 | return r; | ||
1175 | } | ||
1176 | 1178 | ||
1177 | argv += args_used; | 1179 | argv += args_used; |
1178 | argc -= args_used; | 1180 | argc -= args_used; |
@@ -1188,19 +1190,22 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1188 | 1190 | ||
1189 | if (argc) { | 1191 | if (argc) { |
1190 | ti->error = "Too many mirror arguments"; | 1192 | ti->error = "Too many mirror arguments"; |
1191 | free_context(ms, ti, ms->nr_mirrors); | 1193 | r = -EINVAL; |
1192 | return -EINVAL; | 1194 | goto err_destroy_wq; |
1193 | } | 1195 | } |
1194 | 1196 | ||
1195 | r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client); | 1197 | r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client); |
1196 | if (r) { | 1198 | if (r) |
1197 | destroy_workqueue(ms->kmirrord_wq); | 1199 | goto err_destroy_wq; |
1198 | free_context(ms, ti, ms->nr_mirrors); | ||
1199 | return r; | ||
1200 | } | ||
1201 | 1200 | ||
1202 | wake(ms); | 1201 | wake(ms); |
1203 | return 0; | 1202 | return 0; |
1203 | |||
1204 | err_destroy_wq: | ||
1205 | destroy_workqueue(ms->kmirrord_wq); | ||
1206 | err_free_context: | ||
1207 | free_context(ms, ti, ms->nr_mirrors); | ||
1208 | return r; | ||
1204 | } | 1209 | } |
1205 | 1210 | ||
1206 | static void mirror_dtr(struct dm_target *ti) | 1211 | static void mirror_dtr(struct dm_target *ti) |
@@ -1302,7 +1307,7 @@ static void mirror_postsuspend(struct dm_target *ti) | |||
1302 | wait_event(_kmirrord_recovery_stopped, | 1307 | wait_event(_kmirrord_recovery_stopped, |
1303 | !atomic_read(&ms->rh.recovery_in_flight)); | 1308 | !atomic_read(&ms->rh.recovery_in_flight)); |
1304 | 1309 | ||
1305 | if (log->type->suspend && log->type->suspend(log)) | 1310 | if (log->type->postsuspend && log->type->postsuspend(log)) |
1306 | /* FIXME: need better error handling */ | 1311 | /* FIXME: need better error handling */ |
1307 | DMWARN("log suspend failed"); | 1312 | DMWARN("log suspend failed"); |
1308 | } | 1313 | } |
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 98a633f3d6b0..cee16fadd9ee 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/vmalloc.h> | 19 | #include <linux/vmalloc.h> |
20 | #include <linux/log2.h> | ||
20 | 21 | ||
21 | #include "dm-snap.h" | 22 | #include "dm-snap.h" |
22 | #include "dm-bio-list.h" | 23 | #include "dm-bio-list.h" |
@@ -415,7 +416,7 @@ static int set_chunk_size(struct dm_snapshot *s, const char *chunk_size_arg, | |||
415 | chunk_size = round_up(chunk_size, PAGE_SIZE >> 9); | 416 | chunk_size = round_up(chunk_size, PAGE_SIZE >> 9); |
416 | 417 | ||
417 | /* Check chunk_size is a power of 2 */ | 418 | /* Check chunk_size is a power of 2 */ |
418 | if (chunk_size & (chunk_size - 1)) { | 419 | if (!is_power_of_2(chunk_size)) { |
419 | *error = "Chunk size is not a power of 2"; | 420 | *error = "Chunk size is not a power of 2"; |
420 | return -EINVAL; | 421 | return -EINVAL; |
421 | } | 422 | } |
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 51f5e0760012..969944a8aba2 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/blkdev.h> | 11 | #include <linux/blkdev.h> |
12 | #include <linux/bio.h> | 12 | #include <linux/bio.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/log2.h> | ||
14 | 15 | ||
15 | #define DM_MSG_PREFIX "striped" | 16 | #define DM_MSG_PREFIX "striped" |
16 | 17 | ||
@@ -99,7 +100,7 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
99 | /* | 100 | /* |
100 | * chunk_size is a power of two | 101 | * chunk_size is a power of two |
101 | */ | 102 | */ |
102 | if (!chunk_size || (chunk_size & (chunk_size - 1)) || | 103 | if (!is_power_of_2(chunk_size) || |
103 | (chunk_size < (PAGE_SIZE >> SECTOR_SHIFT))) { | 104 | (chunk_size < (PAGE_SIZE >> SECTOR_SHIFT))) { |
104 | ti->error = "Invalid chunk size"; | 105 | ti->error = "Invalid chunk size"; |
105 | return -EINVAL; | 106 | return -EINVAL; |
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index fbe477bb2c68..8939e6105088 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
@@ -213,12 +213,11 @@ static int alloc_targets(struct dm_table *t, unsigned int num) | |||
213 | int dm_table_create(struct dm_table **result, int mode, | 213 | int dm_table_create(struct dm_table **result, int mode, |
214 | unsigned num_targets, struct mapped_device *md) | 214 | unsigned num_targets, struct mapped_device *md) |
215 | { | 215 | { |
216 | struct dm_table *t = kmalloc(sizeof(*t), GFP_KERNEL); | 216 | struct dm_table *t = kzalloc(sizeof(*t), GFP_KERNEL); |
217 | 217 | ||
218 | if (!t) | 218 | if (!t) |
219 | return -ENOMEM; | 219 | return -ENOMEM; |
220 | 220 | ||
221 | memset(t, 0, sizeof(*t)); | ||
222 | INIT_LIST_HEAD(&t->devices); | 221 | INIT_LIST_HEAD(&t->devices); |
223 | atomic_set(&t->holders, 1); | 222 | atomic_set(&t->holders, 1); |
224 | 223 | ||
diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c index 477a041a41cf..835cf95b857f 100644 --- a/drivers/md/dm-target.c +++ b/drivers/md/dm-target.c | |||
@@ -88,12 +88,10 @@ void dm_put_target_type(struct target_type *t) | |||
88 | 88 | ||
89 | static struct tt_internal *alloc_target(struct target_type *t) | 89 | static struct tt_internal *alloc_target(struct target_type *t) |
90 | { | 90 | { |
91 | struct tt_internal *ti = kmalloc(sizeof(*ti), GFP_KERNEL); | 91 | struct tt_internal *ti = kzalloc(sizeof(*ti), GFP_KERNEL); |
92 | 92 | ||
93 | if (ti) { | 93 | if (ti) |
94 | memset(ti, 0, sizeof(*ti)); | ||
95 | ti->tt = *t; | 94 | ti->tt = *t; |
96 | } | ||
97 | 95 | ||
98 | return ti; | 96 | return ti; |
99 | } | 97 | } |
diff --git a/drivers/md/dm-uevent.c b/drivers/md/dm-uevent.c new file mode 100644 index 000000000000..50377e5dc2a3 --- /dev/null +++ b/drivers/md/dm-uevent.c | |||
@@ -0,0 +1,222 @@ | |||
1 | /* | ||
2 | * Device Mapper Uevent Support (dm-uevent) | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
17 | * | ||
18 | * Copyright IBM Corporation, 2007 | ||
19 | * Author: Mike Anderson <andmike@linux.vnet.ibm.com> | ||
20 | */ | ||
21 | #include <linux/list.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/kobject.h> | ||
24 | #include <linux/dm-ioctl.h> | ||
25 | |||
26 | #include "dm.h" | ||
27 | #include "dm-uevent.h" | ||
28 | |||
29 | #define DM_MSG_PREFIX "uevent" | ||
30 | |||
31 | static const struct { | ||
32 | enum dm_uevent_type type; | ||
33 | enum kobject_action action; | ||
34 | char *name; | ||
35 | } _dm_uevent_type_names[] = { | ||
36 | {DM_UEVENT_PATH_FAILED, KOBJ_CHANGE, "PATH_FAILED"}, | ||
37 | {DM_UEVENT_PATH_REINSTATED, KOBJ_CHANGE, "PATH_REINSTATED"}, | ||
38 | }; | ||
39 | |||
40 | static struct kmem_cache *_dm_event_cache; | ||
41 | |||
42 | struct dm_uevent { | ||
43 | struct mapped_device *md; | ||
44 | enum kobject_action action; | ||
45 | struct kobj_uevent_env ku_env; | ||
46 | struct list_head elist; | ||
47 | char name[DM_NAME_LEN]; | ||
48 | char uuid[DM_UUID_LEN]; | ||
49 | }; | ||
50 | |||
51 | static void dm_uevent_free(struct dm_uevent *event) | ||
52 | { | ||
53 | kmem_cache_free(_dm_event_cache, event); | ||
54 | } | ||
55 | |||
56 | static struct dm_uevent *dm_uevent_alloc(struct mapped_device *md) | ||
57 | { | ||
58 | struct dm_uevent *event; | ||
59 | |||
60 | event = kmem_cache_zalloc(_dm_event_cache, GFP_ATOMIC); | ||
61 | if (!event) | ||
62 | return NULL; | ||
63 | |||
64 | INIT_LIST_HEAD(&event->elist); | ||
65 | event->md = md; | ||
66 | |||
67 | return event; | ||
68 | } | ||
69 | |||
70 | static struct dm_uevent *dm_build_path_uevent(struct mapped_device *md, | ||
71 | struct dm_target *ti, | ||
72 | enum kobject_action action, | ||
73 | const char *dm_action, | ||
74 | const char *path, | ||
75 | unsigned nr_valid_paths) | ||
76 | { | ||
77 | struct dm_uevent *event; | ||
78 | |||
79 | event = dm_uevent_alloc(md); | ||
80 | if (!event) { | ||
81 | DMERR("%s: dm_uevent_alloc() failed", __FUNCTION__); | ||
82 | goto err_nomem; | ||
83 | } | ||
84 | |||
85 | event->action = action; | ||
86 | |||
87 | if (add_uevent_var(&event->ku_env, "DM_TARGET=%s", ti->type->name)) { | ||
88 | DMERR("%s: add_uevent_var() for DM_TARGET failed", | ||
89 | __FUNCTION__); | ||
90 | goto err_add; | ||
91 | } | ||
92 | |||
93 | if (add_uevent_var(&event->ku_env, "DM_ACTION=%s", dm_action)) { | ||
94 | DMERR("%s: add_uevent_var() for DM_ACTION failed", | ||
95 | __FUNCTION__); | ||
96 | goto err_add; | ||
97 | } | ||
98 | |||
99 | if (add_uevent_var(&event->ku_env, "DM_SEQNUM=%u", | ||
100 | dm_next_uevent_seq(md))) { | ||
101 | DMERR("%s: add_uevent_var() for DM_SEQNUM failed", | ||
102 | __FUNCTION__); | ||
103 | goto err_add; | ||
104 | } | ||
105 | |||
106 | if (add_uevent_var(&event->ku_env, "DM_PATH=%s", path)) { | ||
107 | DMERR("%s: add_uevent_var() for DM_PATH failed", __FUNCTION__); | ||
108 | goto err_add; | ||
109 | } | ||
110 | |||
111 | if (add_uevent_var(&event->ku_env, "DM_NR_VALID_PATHS=%d", | ||
112 | nr_valid_paths)) { | ||
113 | DMERR("%s: add_uevent_var() for DM_NR_VALID_PATHS failed", | ||
114 | __FUNCTION__); | ||
115 | goto err_add; | ||
116 | } | ||
117 | |||
118 | return event; | ||
119 | |||
120 | err_add: | ||
121 | dm_uevent_free(event); | ||
122 | err_nomem: | ||
123 | return ERR_PTR(-ENOMEM); | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * dm_send_uevents - send uevents for given list | ||
128 | * | ||
129 | * @events: list of events to send | ||
130 | * @kobj: kobject generating event | ||
131 | * | ||
132 | */ | ||
133 | void dm_send_uevents(struct list_head *events, struct kobject *kobj) | ||
134 | { | ||
135 | int r; | ||
136 | struct dm_uevent *event, *next; | ||
137 | |||
138 | list_for_each_entry_safe(event, next, events, elist) { | ||
139 | list_del_init(&event->elist); | ||
140 | |||
141 | /* | ||
142 | * Need to call dm_copy_name_and_uuid from here for now. | ||
143 | * Context of previous var adds and locking used for | ||
144 | * hash_cell not compatable. | ||
145 | */ | ||
146 | if (dm_copy_name_and_uuid(event->md, event->name, | ||
147 | event->uuid)) { | ||
148 | DMERR("%s: dm_copy_name_and_uuid() failed", | ||
149 | __FUNCTION__); | ||
150 | goto uevent_free; | ||
151 | } | ||
152 | |||
153 | if (add_uevent_var(&event->ku_env, "DM_NAME=%s", event->name)) { | ||
154 | DMERR("%s: add_uevent_var() for DM_NAME failed", | ||
155 | __FUNCTION__); | ||
156 | goto uevent_free; | ||
157 | } | ||
158 | |||
159 | if (add_uevent_var(&event->ku_env, "DM_UUID=%s", event->uuid)) { | ||
160 | DMERR("%s: add_uevent_var() for DM_UUID failed", | ||
161 | __FUNCTION__); | ||
162 | goto uevent_free; | ||
163 | } | ||
164 | |||
165 | r = kobject_uevent_env(kobj, event->action, event->ku_env.envp); | ||
166 | if (r) | ||
167 | DMERR("%s: kobject_uevent_env failed", __FUNCTION__); | ||
168 | uevent_free: | ||
169 | dm_uevent_free(event); | ||
170 | } | ||
171 | } | ||
172 | EXPORT_SYMBOL_GPL(dm_send_uevents); | ||
173 | |||
174 | /** | ||
175 | * dm_path_uevent - called to create a new path event and queue it | ||
176 | * | ||
177 | * @event_type: path event type enum | ||
178 | * @ti: pointer to a dm_target | ||
179 | * @path: string containing pathname | ||
180 | * @nr_valid_paths: number of valid paths remaining | ||
181 | * | ||
182 | */ | ||
183 | void dm_path_uevent(enum dm_uevent_type event_type, struct dm_target *ti, | ||
184 | const char *path, unsigned nr_valid_paths) | ||
185 | { | ||
186 | struct mapped_device *md = dm_table_get_md(ti->table); | ||
187 | struct dm_uevent *event; | ||
188 | |||
189 | if (event_type >= ARRAY_SIZE(_dm_uevent_type_names)) { | ||
190 | DMERR("%s: Invalid event_type %d", __FUNCTION__, event_type); | ||
191 | goto out; | ||
192 | } | ||
193 | |||
194 | event = dm_build_path_uevent(md, ti, | ||
195 | _dm_uevent_type_names[event_type].action, | ||
196 | _dm_uevent_type_names[event_type].name, | ||
197 | path, nr_valid_paths); | ||
198 | if (IS_ERR(event)) | ||
199 | goto out; | ||
200 | |||
201 | dm_uevent_add(md, &event->elist); | ||
202 | |||
203 | out: | ||
204 | dm_put(md); | ||
205 | } | ||
206 | EXPORT_SYMBOL_GPL(dm_path_uevent); | ||
207 | |||
208 | int dm_uevent_init(void) | ||
209 | { | ||
210 | _dm_event_cache = KMEM_CACHE(dm_uevent, 0); | ||
211 | if (!_dm_event_cache) | ||
212 | return -ENOMEM; | ||
213 | |||
214 | DMINFO("version 1.0.3"); | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | void dm_uevent_exit(void) | ||
220 | { | ||
221 | kmem_cache_destroy(_dm_event_cache); | ||
222 | } | ||
diff --git a/drivers/md/dm-uevent.h b/drivers/md/dm-uevent.h new file mode 100644 index 000000000000..2eccc8bd671a --- /dev/null +++ b/drivers/md/dm-uevent.h | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * Device Mapper Uevent Support | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
17 | * | ||
18 | * Copyright IBM Corporation, 2007 | ||
19 | * Author: Mike Anderson <andmike@linux.vnet.ibm.com> | ||
20 | */ | ||
21 | #ifndef DM_UEVENT_H | ||
22 | #define DM_UEVENT_H | ||
23 | |||
24 | enum dm_uevent_type { | ||
25 | DM_UEVENT_PATH_FAILED, | ||
26 | DM_UEVENT_PATH_REINSTATED, | ||
27 | }; | ||
28 | |||
29 | #ifdef CONFIG_DM_UEVENT | ||
30 | |||
31 | extern int dm_uevent_init(void); | ||
32 | extern void dm_uevent_exit(void); | ||
33 | extern void dm_send_uevents(struct list_head *events, struct kobject *kobj); | ||
34 | extern void dm_path_uevent(enum dm_uevent_type event_type, | ||
35 | struct dm_target *ti, const char *path, | ||
36 | unsigned nr_valid_paths); | ||
37 | |||
38 | #else | ||
39 | |||
40 | static inline int dm_uevent_init(void) | ||
41 | { | ||
42 | return 0; | ||
43 | } | ||
44 | static inline void dm_uevent_exit(void) | ||
45 | { | ||
46 | } | ||
47 | static inline void dm_send_uevents(struct list_head *events, | ||
48 | struct kobject *kobj) | ||
49 | { | ||
50 | } | ||
51 | static inline void dm_path_uevent(enum dm_uevent_type event_type, | ||
52 | struct dm_target *ti, const char *path, | ||
53 | unsigned nr_valid_paths) | ||
54 | { | ||
55 | } | ||
56 | |||
57 | #endif /* CONFIG_DM_UEVENT */ | ||
58 | |||
59 | #endif /* DM_UEVENT_H */ | ||
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index d837d37f6209..07cbbb8eb3e0 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -7,6 +7,7 @@ | |||
7 | 7 | ||
8 | #include "dm.h" | 8 | #include "dm.h" |
9 | #include "dm-bio-list.h" | 9 | #include "dm-bio-list.h" |
10 | #include "dm-uevent.h" | ||
10 | 11 | ||
11 | #include <linux/init.h> | 12 | #include <linux/init.h> |
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
@@ -112,6 +113,9 @@ struct mapped_device { | |||
112 | */ | 113 | */ |
113 | atomic_t event_nr; | 114 | atomic_t event_nr; |
114 | wait_queue_head_t eventq; | 115 | wait_queue_head_t eventq; |
116 | atomic_t uevent_seq; | ||
117 | struct list_head uevent_list; | ||
118 | spinlock_t uevent_lock; /* Protect access to uevent_list */ | ||
115 | 119 | ||
116 | /* | 120 | /* |
117 | * freeze/thaw support require holding onto a super block | 121 | * freeze/thaw support require holding onto a super block |
@@ -143,11 +147,19 @@ static int __init local_init(void) | |||
143 | return -ENOMEM; | 147 | return -ENOMEM; |
144 | } | 148 | } |
145 | 149 | ||
150 | r = dm_uevent_init(); | ||
151 | if (r) { | ||
152 | kmem_cache_destroy(_tio_cache); | ||
153 | kmem_cache_destroy(_io_cache); | ||
154 | return r; | ||
155 | } | ||
156 | |||
146 | _major = major; | 157 | _major = major; |
147 | r = register_blkdev(_major, _name); | 158 | r = register_blkdev(_major, _name); |
148 | if (r < 0) { | 159 | if (r < 0) { |
149 | kmem_cache_destroy(_tio_cache); | 160 | kmem_cache_destroy(_tio_cache); |
150 | kmem_cache_destroy(_io_cache); | 161 | kmem_cache_destroy(_io_cache); |
162 | dm_uevent_exit(); | ||
151 | return r; | 163 | return r; |
152 | } | 164 | } |
153 | 165 | ||
@@ -162,6 +174,7 @@ static void local_exit(void) | |||
162 | kmem_cache_destroy(_tio_cache); | 174 | kmem_cache_destroy(_tio_cache); |
163 | kmem_cache_destroy(_io_cache); | 175 | kmem_cache_destroy(_io_cache); |
164 | unregister_blkdev(_major, _name); | 176 | unregister_blkdev(_major, _name); |
177 | dm_uevent_exit(); | ||
165 | 178 | ||
166 | _major = 0; | 179 | _major = 0; |
167 | 180 | ||
@@ -751,15 +764,13 @@ static void __clone_and_map(struct clone_info *ci) | |||
751 | /* | 764 | /* |
752 | * Split the bio into several clones. | 765 | * Split the bio into several clones. |
753 | */ | 766 | */ |
754 | static void __split_bio(struct mapped_device *md, struct bio *bio) | 767 | static int __split_bio(struct mapped_device *md, struct bio *bio) |
755 | { | 768 | { |
756 | struct clone_info ci; | 769 | struct clone_info ci; |
757 | 770 | ||
758 | ci.map = dm_get_table(md); | 771 | ci.map = dm_get_table(md); |
759 | if (!ci.map) { | 772 | if (unlikely(!ci.map)) |
760 | bio_io_error(bio); | 773 | return -EIO; |
761 | return; | ||
762 | } | ||
763 | 774 | ||
764 | ci.md = md; | 775 | ci.md = md; |
765 | ci.bio = bio; | 776 | ci.bio = bio; |
@@ -779,6 +790,8 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) | |||
779 | /* drop the extra reference count */ | 790 | /* drop the extra reference count */ |
780 | dec_pending(ci.io, 0); | 791 | dec_pending(ci.io, 0); |
781 | dm_table_put(ci.map); | 792 | dm_table_put(ci.map); |
793 | |||
794 | return 0; | ||
782 | } | 795 | } |
783 | /*----------------------------------------------------------------- | 796 | /*----------------------------------------------------------------- |
784 | * CRUD END | 797 | * CRUD END |
@@ -790,7 +803,7 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) | |||
790 | */ | 803 | */ |
791 | static int dm_request(struct request_queue *q, struct bio *bio) | 804 | static int dm_request(struct request_queue *q, struct bio *bio) |
792 | { | 805 | { |
793 | int r; | 806 | int r = -EIO; |
794 | int rw = bio_data_dir(bio); | 807 | int rw = bio_data_dir(bio); |
795 | struct mapped_device *md = q->queuedata; | 808 | struct mapped_device *md = q->queuedata; |
796 | 809 | ||
@@ -815,18 +828,11 @@ static int dm_request(struct request_queue *q, struct bio *bio) | |||
815 | while (test_bit(DMF_BLOCK_IO, &md->flags)) { | 828 | while (test_bit(DMF_BLOCK_IO, &md->flags)) { |
816 | up_read(&md->io_lock); | 829 | up_read(&md->io_lock); |
817 | 830 | ||
818 | if (bio_rw(bio) == READA) { | 831 | if (bio_rw(bio) != READA) |
819 | bio_io_error(bio); | 832 | r = queue_io(md, bio); |
820 | return 0; | ||
821 | } | ||
822 | |||
823 | r = queue_io(md, bio); | ||
824 | if (r < 0) { | ||
825 | bio_io_error(bio); | ||
826 | return 0; | ||
827 | 833 | ||
828 | } else if (r == 0) | 834 | if (r <= 0) |
829 | return 0; /* deferred successfully */ | 835 | goto out_req; |
830 | 836 | ||
831 | /* | 837 | /* |
832 | * We're in a while loop, because someone could suspend | 838 | * We're in a while loop, because someone could suspend |
@@ -835,8 +841,13 @@ static int dm_request(struct request_queue *q, struct bio *bio) | |||
835 | down_read(&md->io_lock); | 841 | down_read(&md->io_lock); |
836 | } | 842 | } |
837 | 843 | ||
838 | __split_bio(md, bio); | 844 | r = __split_bio(md, bio); |
839 | up_read(&md->io_lock); | 845 | up_read(&md->io_lock); |
846 | |||
847 | out_req: | ||
848 | if (r < 0) | ||
849 | bio_io_error(bio); | ||
850 | |||
840 | return 0; | 851 | return 0; |
841 | } | 852 | } |
842 | 853 | ||
@@ -977,6 +988,9 @@ static struct mapped_device *alloc_dev(int minor) | |||
977 | atomic_set(&md->holders, 1); | 988 | atomic_set(&md->holders, 1); |
978 | atomic_set(&md->open_count, 0); | 989 | atomic_set(&md->open_count, 0); |
979 | atomic_set(&md->event_nr, 0); | 990 | atomic_set(&md->event_nr, 0); |
991 | atomic_set(&md->uevent_seq, 0); | ||
992 | INIT_LIST_HEAD(&md->uevent_list); | ||
993 | spin_lock_init(&md->uevent_lock); | ||
980 | 994 | ||
981 | md->queue = blk_alloc_queue(GFP_KERNEL); | 995 | md->queue = blk_alloc_queue(GFP_KERNEL); |
982 | if (!md->queue) | 996 | if (!md->queue) |
@@ -1044,12 +1058,14 @@ static struct mapped_device *alloc_dev(int minor) | |||
1044 | return NULL; | 1058 | return NULL; |
1045 | } | 1059 | } |
1046 | 1060 | ||
1061 | static void unlock_fs(struct mapped_device *md); | ||
1062 | |||
1047 | static void free_dev(struct mapped_device *md) | 1063 | static void free_dev(struct mapped_device *md) |
1048 | { | 1064 | { |
1049 | int minor = md->disk->first_minor; | 1065 | int minor = md->disk->first_minor; |
1050 | 1066 | ||
1051 | if (md->suspended_bdev) { | 1067 | if (md->suspended_bdev) { |
1052 | thaw_bdev(md->suspended_bdev, NULL); | 1068 | unlock_fs(md); |
1053 | bdput(md->suspended_bdev); | 1069 | bdput(md->suspended_bdev); |
1054 | } | 1070 | } |
1055 | mempool_destroy(md->tio_pool); | 1071 | mempool_destroy(md->tio_pool); |
@@ -1073,8 +1089,16 @@ static void free_dev(struct mapped_device *md) | |||
1073 | */ | 1089 | */ |
1074 | static void event_callback(void *context) | 1090 | static void event_callback(void *context) |
1075 | { | 1091 | { |
1092 | unsigned long flags; | ||
1093 | LIST_HEAD(uevents); | ||
1076 | struct mapped_device *md = (struct mapped_device *) context; | 1094 | struct mapped_device *md = (struct mapped_device *) context; |
1077 | 1095 | ||
1096 | spin_lock_irqsave(&md->uevent_lock, flags); | ||
1097 | list_splice_init(&md->uevent_list, &uevents); | ||
1098 | spin_unlock_irqrestore(&md->uevent_lock, flags); | ||
1099 | |||
1100 | dm_send_uevents(&uevents, &md->disk->kobj); | ||
1101 | |||
1078 | atomic_inc(&md->event_nr); | 1102 | atomic_inc(&md->event_nr); |
1079 | wake_up(&md->eventq); | 1103 | wake_up(&md->eventq); |
1080 | } | 1104 | } |
@@ -1233,7 +1257,8 @@ static void __flush_deferred_io(struct mapped_device *md, struct bio *c) | |||
1233 | while (c) { | 1257 | while (c) { |
1234 | n = c->bi_next; | 1258 | n = c->bi_next; |
1235 | c->bi_next = NULL; | 1259 | c->bi_next = NULL; |
1236 | __split_bio(md, c); | 1260 | if (__split_bio(md, c)) |
1261 | bio_io_error(c); | ||
1237 | c = n; | 1262 | c = n; |
1238 | } | 1263 | } |
1239 | } | 1264 | } |
@@ -1491,6 +1516,11 @@ out: | |||
1491 | /*----------------------------------------------------------------- | 1516 | /*----------------------------------------------------------------- |
1492 | * Event notification. | 1517 | * Event notification. |
1493 | *---------------------------------------------------------------*/ | 1518 | *---------------------------------------------------------------*/ |
1519 | uint32_t dm_next_uevent_seq(struct mapped_device *md) | ||
1520 | { | ||
1521 | return atomic_add_return(1, &md->uevent_seq); | ||
1522 | } | ||
1523 | |||
1494 | uint32_t dm_get_event_nr(struct mapped_device *md) | 1524 | uint32_t dm_get_event_nr(struct mapped_device *md) |
1495 | { | 1525 | { |
1496 | return atomic_read(&md->event_nr); | 1526 | return atomic_read(&md->event_nr); |
@@ -1502,6 +1532,15 @@ int dm_wait_event(struct mapped_device *md, int event_nr) | |||
1502 | (event_nr != atomic_read(&md->event_nr))); | 1532 | (event_nr != atomic_read(&md->event_nr))); |
1503 | } | 1533 | } |
1504 | 1534 | ||
1535 | void dm_uevent_add(struct mapped_device *md, struct list_head *elist) | ||
1536 | { | ||
1537 | unsigned long flags; | ||
1538 | |||
1539 | spin_lock_irqsave(&md->uevent_lock, flags); | ||
1540 | list_add(elist, &md->uevent_list); | ||
1541 | spin_unlock_irqrestore(&md->uevent_lock, flags); | ||
1542 | } | ||
1543 | |||
1505 | /* | 1544 | /* |
1506 | * The gendisk is only valid as long as you have a reference | 1545 | * The gendisk is only valid as long as you have a reference |
1507 | * count on 'md'. | 1546 | * count on 'md'. |
diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c index 7e052378c47e..f3831f31223e 100644 --- a/drivers/md/kcopyd.c +++ b/drivers/md/kcopyd.c | |||
@@ -198,7 +198,7 @@ struct kcopyd_job { | |||
198 | * These fields are only used if the job has been split | 198 | * These fields are only used if the job has been split |
199 | * into more manageable parts. | 199 | * into more manageable parts. |
200 | */ | 200 | */ |
201 | struct semaphore lock; | 201 | struct mutex lock; |
202 | atomic_t sub_jobs; | 202 | atomic_t sub_jobs; |
203 | sector_t progress; | 203 | sector_t progress; |
204 | }; | 204 | }; |
@@ -456,7 +456,7 @@ static void segment_complete(int read_err, | |||
456 | sector_t count = 0; | 456 | sector_t count = 0; |
457 | struct kcopyd_job *job = (struct kcopyd_job *) context; | 457 | struct kcopyd_job *job = (struct kcopyd_job *) context; |
458 | 458 | ||
459 | down(&job->lock); | 459 | mutex_lock(&job->lock); |
460 | 460 | ||
461 | /* update the error */ | 461 | /* update the error */ |
462 | if (read_err) | 462 | if (read_err) |
@@ -480,7 +480,7 @@ static void segment_complete(int read_err, | |||
480 | job->progress += count; | 480 | job->progress += count; |
481 | } | 481 | } |
482 | } | 482 | } |
483 | up(&job->lock); | 483 | mutex_unlock(&job->lock); |
484 | 484 | ||
485 | if (count) { | 485 | if (count) { |
486 | int i; | 486 | int i; |
@@ -562,7 +562,7 @@ int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from, | |||
562 | dispatch_job(job); | 562 | dispatch_job(job); |
563 | 563 | ||
564 | else { | 564 | else { |
565 | init_MUTEX(&job->lock); | 565 | mutex_init(&job->lock); |
566 | job->progress = 0; | 566 | job->progress = 0; |
567 | split_job(job); | 567 | split_job(job); |
568 | } | 568 | } |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 16775a0df7f6..85478d6a9c1a 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * | 9 | * |
10 | * Better read-balancing code written by Mika Kuoppala <miku@iki.fi>, 2000 | 10 | * Better read-balancing code written by Mika Kuoppala <miku@iki.fi>, 2000 |
11 | * | 11 | * |
12 | * Fixes to reconstruction by Jakob Østergaard" <jakob@ostenfeld.dk> | 12 | * Fixes to reconstruction by Jakob Østergaard" <jakob@ostenfeld.dk> |
13 | * Various fixes by Neil Brown <neilb@cse.unsw.edu.au> | 13 | * Various fixes by Neil Brown <neilb@cse.unsw.edu.au> |
14 | * | 14 | * |
15 | * Changes by Peter T. Breuer <ptb@it.uc3m.es> 31/1/2003 to support | 15 | * Changes by Peter T. Breuer <ptb@it.uc3m.es> 31/1/2003 to support |