diff options
author | Mikulas Patocka <mpatocka@redhat.com> | 2008-04-24 17:10:42 -0400 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2008-04-25 08:26:56 -0400 |
commit | a2aebe03be60ae4da03507a00d60211d5e0327c3 (patch) | |
tree | 9475bf530b36f3f4a26c8307d94b3c53787d9ef2 /drivers/md | |
parent | a765e20eeb423d0fa6a02ffab51141e53bbd93cb (diff) |
dm raid1: use timer
This patch replaces the schedule() in the main kmirrord thread with a timer.
The schedule() could introduce an unwanted delay when work is ready to be
processed.
The code instead calls wake() when there's work to be done immediately, and
delayed_wake() after a failure to give a short delay before retrying.
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm-raid1.c | 48 |
1 files changed, 28 insertions, 20 deletions
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 6692e5a84bb1..3b9532fc294c 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
@@ -154,6 +154,9 @@ struct mirror_set { | |||
154 | 154 | ||
155 | struct workqueue_struct *kmirrord_wq; | 155 | struct workqueue_struct *kmirrord_wq; |
156 | struct work_struct kmirrord_work; | 156 | struct work_struct kmirrord_work; |
157 | struct timer_list timer; | ||
158 | unsigned long timer_pending; | ||
159 | |||
157 | struct work_struct trigger_event; | 160 | struct work_struct trigger_event; |
158 | 161 | ||
159 | unsigned int nr_mirrors; | 162 | unsigned int nr_mirrors; |
@@ -178,6 +181,25 @@ static void wake(struct mirror_set *ms) | |||
178 | queue_work(ms->kmirrord_wq, &ms->kmirrord_work); | 181 | queue_work(ms->kmirrord_wq, &ms->kmirrord_work); |
179 | } | 182 | } |
180 | 183 | ||
184 | static void delayed_wake_fn(unsigned long data) | ||
185 | { | ||
186 | struct mirror_set *ms = (struct mirror_set *) data; | ||
187 | |||
188 | clear_bit(0, &ms->timer_pending); | ||
189 | wake(ms); | ||
190 | } | ||
191 | |||
192 | static void delayed_wake(struct mirror_set *ms) | ||
193 | { | ||
194 | if (test_and_set_bit(0, &ms->timer_pending)) | ||
195 | return; | ||
196 | |||
197 | ms->timer.expires = jiffies + HZ / 5; | ||
198 | ms->timer.data = (unsigned long) ms; | ||
199 | ms->timer.function = delayed_wake_fn; | ||
200 | add_timer(&ms->timer); | ||
201 | } | ||
202 | |||
181 | /* FIXME move this */ | 203 | /* FIXME move this */ |
182 | static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw); | 204 | static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw); |
183 | 205 | ||
@@ -1180,6 +1202,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes) | |||
1180 | spin_lock_irq(&ms->lock); | 1202 | spin_lock_irq(&ms->lock); |
1181 | bio_list_merge(&ms->failures, &sync); | 1203 | bio_list_merge(&ms->failures, &sync); |
1182 | spin_unlock_irq(&ms->lock); | 1204 | spin_unlock_irq(&ms->lock); |
1205 | wake(ms); | ||
1183 | } else | 1206 | } else |
1184 | while ((bio = bio_list_pop(&sync))) | 1207 | while ((bio = bio_list_pop(&sync))) |
1185 | do_write(ms, bio); | 1208 | do_write(ms, bio); |
@@ -1239,7 +1262,7 @@ static void do_failures(struct mirror_set *ms, struct bio_list *failures) | |||
1239 | bio_list_merge(&ms->failures, failures); | 1262 | bio_list_merge(&ms->failures, failures); |
1240 | spin_unlock_irq(&ms->lock); | 1263 | spin_unlock_irq(&ms->lock); |
1241 | 1264 | ||
1242 | wake(ms); | 1265 | delayed_wake(ms); |
1243 | } | 1266 | } |
1244 | 1267 | ||
1245 | static void trigger_event(struct work_struct *work) | 1268 | static void trigger_event(struct work_struct *work) |
@@ -1253,7 +1276,7 @@ static void trigger_event(struct work_struct *work) | |||
1253 | /*----------------------------------------------------------------- | 1276 | /*----------------------------------------------------------------- |
1254 | * kmirrord | 1277 | * kmirrord |
1255 | *---------------------------------------------------------------*/ | 1278 | *---------------------------------------------------------------*/ |
1256 | static int _do_mirror(struct work_struct *work) | 1279 | static void do_mirror(struct work_struct *work) |
1257 | { | 1280 | { |
1258 | struct mirror_set *ms =container_of(work, struct mirror_set, | 1281 | struct mirror_set *ms =container_of(work, struct mirror_set, |
1259 | kmirrord_work); | 1282 | kmirrord_work); |
@@ -1274,24 +1297,6 @@ static int _do_mirror(struct work_struct *work) | |||
1274 | do_reads(ms, &reads); | 1297 | do_reads(ms, &reads); |
1275 | do_writes(ms, &writes); | 1298 | do_writes(ms, &writes); |
1276 | do_failures(ms, &failures); | 1299 | do_failures(ms, &failures); |
1277 | |||
1278 | return (ms->failures.head) ? 1 : 0; | ||
1279 | } | ||
1280 | |||
1281 | static void do_mirror(struct work_struct *work) | ||
1282 | { | ||
1283 | /* | ||
1284 | * If _do_mirror returns 1, we give it | ||
1285 | * another shot. This helps for cases like | ||
1286 | * 'suspend' where we call flush_workqueue | ||
1287 | * and expect all work to be finished. If | ||
1288 | * a failure happens during a suspend, we | ||
1289 | * couldn't issue a 'wake' because it would | ||
1290 | * not be honored. Therefore, we return '1' | ||
1291 | * from _do_mirror, and retry here. | ||
1292 | */ | ||
1293 | while (_do_mirror(work)) | ||
1294 | schedule(); | ||
1295 | } | 1300 | } |
1296 | 1301 | ||
1297 | 1302 | ||
@@ -1545,6 +1550,8 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1545 | goto err_free_context; | 1550 | goto err_free_context; |
1546 | } | 1551 | } |
1547 | INIT_WORK(&ms->kmirrord_work, do_mirror); | 1552 | INIT_WORK(&ms->kmirrord_work, do_mirror); |
1553 | init_timer(&ms->timer); | ||
1554 | ms->timer_pending = 0; | ||
1548 | INIT_WORK(&ms->trigger_event, trigger_event); | 1555 | INIT_WORK(&ms->trigger_event, trigger_event); |
1549 | 1556 | ||
1550 | r = parse_features(ms, argc, argv, &args_used); | 1557 | r = parse_features(ms, argc, argv, &args_used); |
@@ -1587,6 +1594,7 @@ static void mirror_dtr(struct dm_target *ti) | |||
1587 | { | 1594 | { |
1588 | struct mirror_set *ms = (struct mirror_set *) ti->private; | 1595 | struct mirror_set *ms = (struct mirror_set *) ti->private; |
1589 | 1596 | ||
1597 | del_timer_sync(&ms->timer); | ||
1590 | flush_workqueue(ms->kmirrord_wq); | 1598 | flush_workqueue(ms->kmirrord_wq); |
1591 | dm_kcopyd_client_destroy(ms->kcopyd_client); | 1599 | dm_kcopyd_client_destroy(ms->kcopyd_client); |
1592 | destroy_workqueue(ms->kmirrord_wq); | 1600 | destroy_workqueue(ms->kmirrord_wq); |