aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorHolger Smolinski <smolinski@de.ibm.com>2007-05-09 05:32:50 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-09 15:30:46 -0400
commit6ad36fe2b451cc85cc7b14f4128286759e217124 (patch)
tree05e6111d39c969ee729309d6bded6bcfe08aa44e /drivers/md
parent8defab33774a5c33920196a2ee9c0a946d22ba67 (diff)
dm raid1: one kmirrord per mirror
This patch replaces the single instance of kmirrord by one instance per mirror set. This change is required to avoid a deadlock in kmirrord when the persistent dirty log of a mirror itself resides on a mirror. The single instance of kmirrord then issues a sync write to the dirty log in write_bits which gets deferred to kmirrord itself later in the call chain. But kmirrord never does the deferred work because it is still waiting for the sync write_bits. _mirror_sets is removed as it no longer needed, and we always flush the workqueue before destroying it to ensure all work is complete before destroying it. Signed-off-by: Holger Smolinski <smolinski@de.ibm.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com> Cc: Oleg Nesterov <oleg@tv-sign.ru> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-raid1.c81
1 files changed, 27 insertions, 54 deletions
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 23a642619bed..c8b4c108da9e 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -22,15 +22,8 @@
22 22
23#define DM_MSG_PREFIX "raid1" 23#define DM_MSG_PREFIX "raid1"
24 24
25static struct workqueue_struct *_kmirrord_wq;
26static struct work_struct _kmirrord_work;
27static DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped); 25static DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped);
28 26
29static inline void wake(void)
30{
31 queue_work(_kmirrord_wq, &_kmirrord_work);
32}
33
34/*----------------------------------------------------------------- 27/*-----------------------------------------------------------------
35 * Region hash 28 * Region hash
36 * 29 *
@@ -136,6 +129,9 @@ struct mirror_set {
136 129
137 struct mirror *default_mirror; /* Default mirror */ 130 struct mirror *default_mirror; /* Default mirror */
138 131
132 struct workqueue_struct *kmirrord_wq;
133 struct work_struct kmirrord_work;
134
139 unsigned int nr_mirrors; 135 unsigned int nr_mirrors;
140 struct mirror mirror[0]; 136 struct mirror mirror[0];
141}; 137};
@@ -153,6 +149,11 @@ static inline sector_t region_to_sector(struct region_hash *rh, region_t region)
153 return region << rh->region_shift; 149 return region << rh->region_shift;
154} 150}
155 151
152static void wake(struct mirror_set *ms)
153{
154 queue_work(ms->kmirrord_wq, &ms->kmirrord_work);
155}
156
156/* FIXME move this */ 157/* FIXME move this */
157static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw); 158static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw);
158 159
@@ -471,7 +472,7 @@ static void rh_dec(struct region_hash *rh, region_t region)
471 spin_unlock_irqrestore(&rh->region_lock, flags); 472 spin_unlock_irqrestore(&rh->region_lock, flags);
472 473
473 if (should_wake) 474 if (should_wake)
474 wake(); 475 wake(rh->ms);
475} 476}
476 477
477/* 478/*
@@ -558,7 +559,7 @@ static void rh_recovery_end(struct region *reg, int success)
558 list_add(&reg->list, &reg->rh->recovered_regions); 559 list_add(&reg->list, &reg->rh->recovered_regions);
559 spin_unlock_irq(&rh->region_lock); 560 spin_unlock_irq(&rh->region_lock);
560 561
561 wake(); 562 wake(rh->ms);
562} 563}
563 564
564static void rh_flush(struct region_hash *rh) 565static void rh_flush(struct region_hash *rh)
@@ -592,7 +593,7 @@ static void rh_start_recovery(struct region_hash *rh)
592 for (i = 0; i < MAX_RECOVERY; i++) 593 for (i = 0; i < MAX_RECOVERY; i++)
593 up(&rh->recovery_count); 594 up(&rh->recovery_count);
594 595
595 wake(); 596 wake(rh->ms);
596} 597}
597 598
598/* 599/*
@@ -870,11 +871,10 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
870/*----------------------------------------------------------------- 871/*-----------------------------------------------------------------
871 * kmirrord 872 * kmirrord
872 *---------------------------------------------------------------*/ 873 *---------------------------------------------------------------*/
873static LIST_HEAD(_mirror_sets); 874static void do_mirror(struct work_struct *work)
874static DECLARE_RWSEM(_mirror_sets_lock);
875
876static void do_mirror(struct mirror_set *ms)
877{ 875{
876 struct mirror_set *ms =container_of(work, struct mirror_set,
877 kmirrord_work);
878 struct bio_list reads, writes; 878 struct bio_list reads, writes;
879 879
880 spin_lock(&ms->lock); 880 spin_lock(&ms->lock);
@@ -890,16 +890,6 @@ static void do_mirror(struct mirror_set *ms)
890 do_writes(ms, &writes); 890 do_writes(ms, &writes);
891} 891}
892 892
893static void do_work(struct work_struct *ignored)
894{
895 struct mirror_set *ms;
896
897 down_read(&_mirror_sets_lock);
898 list_for_each_entry (ms, &_mirror_sets, list)
899 do_mirror(ms);
900 up_read(&_mirror_sets_lock);
901}
902
903/*----------------------------------------------------------------- 893/*-----------------------------------------------------------------
904 * Target functions 894 * Target functions
905 *---------------------------------------------------------------*/ 895 *---------------------------------------------------------------*/
@@ -978,23 +968,6 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
978 return 0; 968 return 0;
979} 969}
980 970
981static int add_mirror_set(struct mirror_set *ms)
982{
983 down_write(&_mirror_sets_lock);
984 list_add_tail(&ms->list, &_mirror_sets);
985 up_write(&_mirror_sets_lock);
986 wake();
987
988 return 0;
989}
990
991static void del_mirror_set(struct mirror_set *ms)
992{
993 down_write(&_mirror_sets_lock);
994 list_del(&ms->list);
995 up_write(&_mirror_sets_lock);
996}
997
998/* 971/*
999 * Create dirty log: log_type #log_params <log_params> 972 * Create dirty log: log_type #log_params <log_params>
1000 */ 973 */
@@ -1096,13 +1069,22 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
1096 ti->private = ms; 1069 ti->private = ms;
1097 ti->split_io = ms->rh.region_size; 1070 ti->split_io = ms->rh.region_size;
1098 1071
1072 ms->kmirrord_wq = create_singlethread_workqueue("kmirrord");
1073 if (!ms->kmirrord_wq) {
1074 DMERR("couldn't start kmirrord");
1075 free_context(ms, ti, m);
1076 return -ENOMEM;
1077 }
1078 INIT_WORK(&ms->kmirrord_work, do_mirror);
1079
1099 r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client); 1080 r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client);
1100 if (r) { 1081 if (r) {
1082 destroy_workqueue(ms->kmirrord_wq);
1101 free_context(ms, ti, ms->nr_mirrors); 1083 free_context(ms, ti, ms->nr_mirrors);
1102 return r; 1084 return r;
1103 } 1085 }
1104 1086
1105 add_mirror_set(ms); 1087 wake(ms);
1106 return 0; 1088 return 0;
1107} 1089}
1108 1090
@@ -1110,8 +1092,9 @@ static void mirror_dtr(struct dm_target *ti)
1110{ 1092{
1111 struct mirror_set *ms = (struct mirror_set *) ti->private; 1093 struct mirror_set *ms = (struct mirror_set *) ti->private;
1112 1094
1113 del_mirror_set(ms); 1095 flush_workqueue(ms->kmirrord_wq);
1114 kcopyd_client_destroy(ms->kcopyd_client); 1096 kcopyd_client_destroy(ms->kcopyd_client);
1097 destroy_workqueue(ms->kmirrord_wq);
1115 free_context(ms, ti, ms->nr_mirrors); 1098 free_context(ms, ti, ms->nr_mirrors);
1116} 1099}
1117 1100
@@ -1127,7 +1110,7 @@ static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw)
1127 spin_unlock(&ms->lock); 1110 spin_unlock(&ms->lock);
1128 1111
1129 if (should_wake) 1112 if (should_wake)
1130 wake(); 1113 wake(ms);
1131} 1114}
1132 1115
1133/* 1116/*
@@ -1270,20 +1253,11 @@ static int __init dm_mirror_init(void)
1270 if (r) 1253 if (r)
1271 return r; 1254 return r;
1272 1255
1273 _kmirrord_wq = create_singlethread_workqueue("kmirrord");
1274 if (!_kmirrord_wq) {
1275 DMERR("couldn't start kmirrord");
1276 dm_dirty_log_exit();
1277 return r;
1278 }
1279 INIT_WORK(&_kmirrord_work, do_work);
1280
1281 r = dm_register_target(&mirror_target); 1256 r = dm_register_target(&mirror_target);
1282 if (r < 0) { 1257 if (r < 0) {
1283 DMERR("%s: Failed to register mirror target", 1258 DMERR("%s: Failed to register mirror target",
1284 mirror_target.name); 1259 mirror_target.name);
1285 dm_dirty_log_exit(); 1260 dm_dirty_log_exit();
1286 destroy_workqueue(_kmirrord_wq);
1287 } 1261 }
1288 1262
1289 return r; 1263 return r;
@@ -1297,7 +1271,6 @@ static void __exit dm_mirror_exit(void)
1297 if (r < 0) 1271 if (r < 0)
1298 DMERR("%s: unregister failed %d", mirror_target.name, r); 1272 DMERR("%s: unregister failed %d", mirror_target.name, r);
1299 1273
1300 destroy_workqueue(_kmirrord_wq);
1301 dm_dirty_log_exit(); 1274 dm_dirty_log_exit();
1302} 1275}
1303 1276