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); |
