diff options
Diffstat (limited to 'drivers/md/dm-raid1.c')
-rw-r--r-- | drivers/md/dm-raid1.c | 97 |
1 files changed, 49 insertions, 48 deletions
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index d12cf3e5e076..be48cedf986b 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/vmalloc.h> | 20 | #include <linux/vmalloc.h> |
21 | #include <linux/workqueue.h> | 21 | #include <linux/workqueue.h> |
22 | 22 | ||
23 | #define DM_MSG_PREFIX "raid1" | ||
24 | |||
23 | static struct workqueue_struct *_kmirrord_wq; | 25 | static struct workqueue_struct *_kmirrord_wq; |
24 | static struct work_struct _kmirrord_work; | 26 | static struct work_struct _kmirrord_work; |
25 | 27 | ||
@@ -106,12 +108,42 @@ struct region { | |||
106 | struct bio_list delayed_bios; | 108 | struct bio_list delayed_bios; |
107 | }; | 109 | }; |
108 | 110 | ||
111 | |||
112 | /*----------------------------------------------------------------- | ||
113 | * Mirror set structures. | ||
114 | *---------------------------------------------------------------*/ | ||
115 | struct mirror { | ||
116 | atomic_t error_count; | ||
117 | struct dm_dev *dev; | ||
118 | sector_t offset; | ||
119 | }; | ||
120 | |||
121 | struct mirror_set { | ||
122 | struct dm_target *ti; | ||
123 | struct list_head list; | ||
124 | struct region_hash rh; | ||
125 | struct kcopyd_client *kcopyd_client; | ||
126 | |||
127 | spinlock_t lock; /* protects the next two lists */ | ||
128 | struct bio_list reads; | ||
129 | struct bio_list writes; | ||
130 | |||
131 | /* recovery */ | ||
132 | region_t nr_regions; | ||
133 | int in_sync; | ||
134 | |||
135 | struct mirror *default_mirror; /* Default mirror */ | ||
136 | |||
137 | unsigned int nr_mirrors; | ||
138 | struct mirror mirror[0]; | ||
139 | }; | ||
140 | |||
109 | /* | 141 | /* |
110 | * Conversion fns | 142 | * Conversion fns |
111 | */ | 143 | */ |
112 | static inline region_t bio_to_region(struct region_hash *rh, struct bio *bio) | 144 | static inline region_t bio_to_region(struct region_hash *rh, struct bio *bio) |
113 | { | 145 | { |
114 | return bio->bi_sector >> rh->region_shift; | 146 | return (bio->bi_sector - rh->ms->ti->begin) >> rh->region_shift; |
115 | } | 147 | } |
116 | 148 | ||
117 | static inline sector_t region_to_sector(struct region_hash *rh, region_t region) | 149 | static inline sector_t region_to_sector(struct region_hash *rh, region_t region) |
@@ -458,11 +490,9 @@ static int __rh_recovery_prepare(struct region_hash *rh) | |||
458 | /* Already quiesced ? */ | 490 | /* Already quiesced ? */ |
459 | if (atomic_read(®->pending)) | 491 | if (atomic_read(®->pending)) |
460 | list_del_init(®->list); | 492 | list_del_init(®->list); |
493 | else | ||
494 | list_move(®->list, &rh->quiesced_regions); | ||
461 | 495 | ||
462 | else { | ||
463 | list_del_init(®->list); | ||
464 | list_add(®->list, &rh->quiesced_regions); | ||
465 | } | ||
466 | spin_unlock_irq(&rh->region_lock); | 496 | spin_unlock_irq(&rh->region_lock); |
467 | 497 | ||
468 | return 1; | 498 | return 1; |
@@ -541,35 +571,6 @@ static void rh_start_recovery(struct region_hash *rh) | |||
541 | wake(); | 571 | wake(); |
542 | } | 572 | } |
543 | 573 | ||
544 | /*----------------------------------------------------------------- | ||
545 | * Mirror set structures. | ||
546 | *---------------------------------------------------------------*/ | ||
547 | struct mirror { | ||
548 | atomic_t error_count; | ||
549 | struct dm_dev *dev; | ||
550 | sector_t offset; | ||
551 | }; | ||
552 | |||
553 | struct mirror_set { | ||
554 | struct dm_target *ti; | ||
555 | struct list_head list; | ||
556 | struct region_hash rh; | ||
557 | struct kcopyd_client *kcopyd_client; | ||
558 | |||
559 | spinlock_t lock; /* protects the next two lists */ | ||
560 | struct bio_list reads; | ||
561 | struct bio_list writes; | ||
562 | |||
563 | /* recovery */ | ||
564 | region_t nr_regions; | ||
565 | int in_sync; | ||
566 | |||
567 | struct mirror *default_mirror; /* Default mirror */ | ||
568 | |||
569 | unsigned int nr_mirrors; | ||
570 | struct mirror mirror[0]; | ||
571 | }; | ||
572 | |||
573 | /* | 574 | /* |
574 | * Every mirror should look like this one. | 575 | * Every mirror should look like this one. |
575 | */ | 576 | */ |
@@ -603,7 +604,7 @@ static void recovery_complete(int read_err, unsigned int write_err, | |||
603 | struct region *reg = (struct region *) context; | 604 | struct region *reg = (struct region *) context; |
604 | 605 | ||
605 | /* FIXME: better error handling */ | 606 | /* FIXME: better error handling */ |
606 | rh_recovery_end(reg, read_err || write_err); | 607 | rh_recovery_end(reg, !(read_err || write_err)); |
607 | } | 608 | } |
608 | 609 | ||
609 | static int recover(struct mirror_set *ms, struct region *reg) | 610 | static int recover(struct mirror_set *ms, struct region *reg) |
@@ -893,7 +894,7 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors, | |||
893 | 894 | ||
894 | ms = kmalloc(len, GFP_KERNEL); | 895 | ms = kmalloc(len, GFP_KERNEL); |
895 | if (!ms) { | 896 | if (!ms) { |
896 | ti->error = "dm-mirror: Cannot allocate mirror context"; | 897 | ti->error = "Cannot allocate mirror context"; |
897 | return NULL; | 898 | return NULL; |
898 | } | 899 | } |
899 | 900 | ||
@@ -907,7 +908,7 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors, | |||
907 | ms->default_mirror = &ms->mirror[DEFAULT_MIRROR]; | 908 | ms->default_mirror = &ms->mirror[DEFAULT_MIRROR]; |
908 | 909 | ||
909 | if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) { | 910 | if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) { |
910 | ti->error = "dm-mirror: Error creating dirty region hash"; | 911 | ti->error = "Error creating dirty region hash"; |
911 | kfree(ms); | 912 | kfree(ms); |
912 | return NULL; | 913 | return NULL; |
913 | } | 914 | } |
@@ -937,14 +938,14 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti, | |||
937 | unsigned long long offset; | 938 | unsigned long long offset; |
938 | 939 | ||
939 | if (sscanf(argv[1], "%llu", &offset) != 1) { | 940 | if (sscanf(argv[1], "%llu", &offset) != 1) { |
940 | ti->error = "dm-mirror: Invalid offset"; | 941 | ti->error = "Invalid offset"; |
941 | return -EINVAL; | 942 | return -EINVAL; |
942 | } | 943 | } |
943 | 944 | ||
944 | if (dm_get_device(ti, argv[0], offset, ti->len, | 945 | if (dm_get_device(ti, argv[0], offset, ti->len, |
945 | dm_table_get_mode(ti->table), | 946 | dm_table_get_mode(ti->table), |
946 | &ms->mirror[mirror].dev)) { | 947 | &ms->mirror[mirror].dev)) { |
947 | ti->error = "dm-mirror: Device lookup failure"; | 948 | ti->error = "Device lookup failure"; |
948 | return -ENXIO; | 949 | return -ENXIO; |
949 | } | 950 | } |
950 | 951 | ||
@@ -981,30 +982,30 @@ static struct dirty_log *create_dirty_log(struct dm_target *ti, | |||
981 | struct dirty_log *dl; | 982 | struct dirty_log *dl; |
982 | 983 | ||
983 | if (argc < 2) { | 984 | if (argc < 2) { |
984 | ti->error = "dm-mirror: Insufficient mirror log arguments"; | 985 | ti->error = "Insufficient mirror log arguments"; |
985 | return NULL; | 986 | return NULL; |
986 | } | 987 | } |
987 | 988 | ||
988 | if (sscanf(argv[1], "%u", ¶m_count) != 1) { | 989 | if (sscanf(argv[1], "%u", ¶m_count) != 1) { |
989 | ti->error = "dm-mirror: Invalid mirror log argument count"; | 990 | ti->error = "Invalid mirror log argument count"; |
990 | return NULL; | 991 | return NULL; |
991 | } | 992 | } |
992 | 993 | ||
993 | *args_used = 2 + param_count; | 994 | *args_used = 2 + param_count; |
994 | 995 | ||
995 | if (argc < *args_used) { | 996 | if (argc < *args_used) { |
996 | ti->error = "dm-mirror: Insufficient mirror log arguments"; | 997 | ti->error = "Insufficient mirror log arguments"; |
997 | return NULL; | 998 | return NULL; |
998 | } | 999 | } |
999 | 1000 | ||
1000 | dl = dm_create_dirty_log(argv[0], ti, param_count, argv + 2); | 1001 | dl = dm_create_dirty_log(argv[0], ti, param_count, argv + 2); |
1001 | if (!dl) { | 1002 | if (!dl) { |
1002 | ti->error = "dm-mirror: Error creating mirror dirty log"; | 1003 | ti->error = "Error creating mirror dirty log"; |
1003 | return NULL; | 1004 | return NULL; |
1004 | } | 1005 | } |
1005 | 1006 | ||
1006 | if (!_check_region_size(ti, dl->type->get_region_size(dl))) { | 1007 | if (!_check_region_size(ti, dl->type->get_region_size(dl))) { |
1007 | ti->error = "dm-mirror: Invalid region size"; | 1008 | ti->error = "Invalid region size"; |
1008 | dm_destroy_dirty_log(dl); | 1009 | dm_destroy_dirty_log(dl); |
1009 | return NULL; | 1010 | return NULL; |
1010 | } | 1011 | } |
@@ -1038,7 +1039,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1038 | 1039 | ||
1039 | if (!argc || sscanf(argv[0], "%u", &nr_mirrors) != 1 || | 1040 | if (!argc || sscanf(argv[0], "%u", &nr_mirrors) != 1 || |
1040 | nr_mirrors < 2 || nr_mirrors > KCOPYD_MAX_REGIONS + 1) { | 1041 | nr_mirrors < 2 || nr_mirrors > KCOPYD_MAX_REGIONS + 1) { |
1041 | ti->error = "dm-mirror: Invalid number of mirrors"; | 1042 | ti->error = "Invalid number of mirrors"; |
1042 | dm_destroy_dirty_log(dl); | 1043 | dm_destroy_dirty_log(dl); |
1043 | return -EINVAL; | 1044 | return -EINVAL; |
1044 | } | 1045 | } |
@@ -1046,7 +1047,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1046 | argv++, argc--; | 1047 | argv++, argc--; |
1047 | 1048 | ||
1048 | if (argc != nr_mirrors * 2) { | 1049 | if (argc != nr_mirrors * 2) { |
1049 | ti->error = "dm-mirror: Wrong number of mirror arguments"; | 1050 | ti->error = "Wrong number of mirror arguments"; |
1050 | dm_destroy_dirty_log(dl); | 1051 | dm_destroy_dirty_log(dl); |
1051 | return -EINVAL; | 1052 | return -EINVAL; |
1052 | } | 1053 | } |
@@ -1115,7 +1116,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio, | |||
1115 | struct mirror *m; | 1116 | struct mirror *m; |
1116 | struct mirror_set *ms = ti->private; | 1117 | struct mirror_set *ms = ti->private; |
1117 | 1118 | ||
1118 | map_context->ll = bio->bi_sector >> ms->rh.region_shift; | 1119 | map_context->ll = bio_to_region(&ms->rh, bio); |
1119 | 1120 | ||
1120 | if (rw == WRITE) { | 1121 | if (rw == WRITE) { |
1121 | queue_bio(ms, bio, rw); | 1122 | queue_bio(ms, bio, rw); |
@@ -1221,7 +1222,7 @@ static int mirror_status(struct dm_target *ti, status_type_t type, | |||
1221 | 1222 | ||
1222 | static struct target_type mirror_target = { | 1223 | static struct target_type mirror_target = { |
1223 | .name = "mirror", | 1224 | .name = "mirror", |
1224 | .version = {1, 0, 1}, | 1225 | .version = {1, 0, 2}, |
1225 | .module = THIS_MODULE, | 1226 | .module = THIS_MODULE, |
1226 | .ctr = mirror_ctr, | 1227 | .ctr = mirror_ctr, |
1227 | .dtr = mirror_dtr, | 1228 | .dtr = mirror_dtr, |