diff options
author | Mikulas Patocka <mpatocka@redhat.com> | 2009-12-10 18:52:03 -0500 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2009-12-10 18:52:03 -0500 |
commit | 04788507686d184d8166918b70ef52311bc36dcb (patch) | |
tree | c17fb1f8f9ac8d2a137f9c523d059f5918940c93 /drivers/md/dm-raid1.c | |
parent | 64b30c46e866bbff8a9e17883a18636adc358455 (diff) |
dm raid1: add framework to hold bios during suspend
Add framework to delay bios until a suspend and then resubmit them with
either DM_ENDIO_REQUEUE (if the suspend was noflush) or complete them
with -EIO. I/O barrier support will use this.
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Reviewed-by: Takahiro Yasui <tyasui@redhat.com>
Tested-by: Takahiro Yasui <tyasui@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md/dm-raid1.c')
-rw-r--r-- | drivers/md/dm-raid1.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 85c8704c67bb..895cce75eee9 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
@@ -58,6 +58,7 @@ struct mirror_set { | |||
58 | struct bio_list reads; | 58 | struct bio_list reads; |
59 | struct bio_list writes; | 59 | struct bio_list writes; |
60 | struct bio_list failures; | 60 | struct bio_list failures; |
61 | struct bio_list holds; /* bios are waiting until suspend */ | ||
61 | 62 | ||
62 | struct dm_region_hash *rh; | 63 | struct dm_region_hash *rh; |
63 | struct dm_kcopyd_client *kcopyd_client; | 64 | struct dm_kcopyd_client *kcopyd_client; |
@@ -450,6 +451,27 @@ static void map_region(struct dm_io_region *io, struct mirror *m, | |||
450 | io->count = bio->bi_size >> 9; | 451 | io->count = bio->bi_size >> 9; |
451 | } | 452 | } |
452 | 453 | ||
454 | static void hold_bio(struct mirror_set *ms, struct bio *bio) | ||
455 | { | ||
456 | /* | ||
457 | * If device is suspended, complete the bio. | ||
458 | */ | ||
459 | if (atomic_read(&ms->suspend)) { | ||
460 | if (dm_noflush_suspending(ms->ti)) | ||
461 | bio_endio(bio, DM_ENDIO_REQUEUE); | ||
462 | else | ||
463 | bio_endio(bio, -EIO); | ||
464 | return; | ||
465 | } | ||
466 | |||
467 | /* | ||
468 | * Hold bio until the suspend is complete. | ||
469 | */ | ||
470 | spin_lock_irq(&ms->lock); | ||
471 | bio_list_add(&ms->holds, bio); | ||
472 | spin_unlock_irq(&ms->lock); | ||
473 | } | ||
474 | |||
453 | /*----------------------------------------------------------------- | 475 | /*----------------------------------------------------------------- |
454 | * Reads | 476 | * Reads |
455 | *---------------------------------------------------------------*/ | 477 | *---------------------------------------------------------------*/ |
@@ -1225,6 +1247,9 @@ static void mirror_presuspend(struct dm_target *ti) | |||
1225 | struct mirror_set *ms = (struct mirror_set *) ti->private; | 1247 | struct mirror_set *ms = (struct mirror_set *) ti->private; |
1226 | struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh); | 1248 | struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh); |
1227 | 1249 | ||
1250 | struct bio_list holds; | ||
1251 | struct bio *bio; | ||
1252 | |||
1228 | atomic_set(&ms->suspend, 1); | 1253 | atomic_set(&ms->suspend, 1); |
1229 | 1254 | ||
1230 | /* | 1255 | /* |
@@ -1247,6 +1272,22 @@ static void mirror_presuspend(struct dm_target *ti) | |||
1247 | * we know that all of our I/O has been pushed. | 1272 | * we know that all of our I/O has been pushed. |
1248 | */ | 1273 | */ |
1249 | flush_workqueue(ms->kmirrord_wq); | 1274 | flush_workqueue(ms->kmirrord_wq); |
1275 | |||
1276 | /* | ||
1277 | * Now set ms->suspend is set and the workqueue flushed, no more | ||
1278 | * entries can be added to ms->hold list, so process it. | ||
1279 | * | ||
1280 | * Bios can still arrive concurrently with or after this | ||
1281 | * presuspend function, but they cannot join the hold list | ||
1282 | * because ms->suspend is set. | ||
1283 | */ | ||
1284 | spin_lock_irq(&ms->lock); | ||
1285 | holds = ms->holds; | ||
1286 | bio_list_init(&ms->holds); | ||
1287 | spin_unlock_irq(&ms->lock); | ||
1288 | |||
1289 | while ((bio = bio_list_pop(&holds))) | ||
1290 | hold_bio(ms, bio); | ||
1250 | } | 1291 | } |
1251 | 1292 | ||
1252 | static void mirror_postsuspend(struct dm_target *ti) | 1293 | static void mirror_postsuspend(struct dm_target *ti) |