diff options
Diffstat (limited to 'drivers/md/dm-raid1.c')
-rw-r--r-- | drivers/md/dm-raid1.c | 50 |
1 files changed, 44 insertions, 6 deletions
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 4d6bc101962e..536ef0bef154 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
@@ -145,6 +145,8 @@ struct dm_raid1_read_record { | |||
145 | struct dm_bio_details details; | 145 | struct dm_bio_details details; |
146 | }; | 146 | }; |
147 | 147 | ||
148 | static struct kmem_cache *_dm_raid1_read_record_cache; | ||
149 | |||
148 | /* | 150 | /* |
149 | * Every mirror should look like this one. | 151 | * Every mirror should look like this one. |
150 | */ | 152 | */ |
@@ -586,6 +588,9 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes) | |||
586 | int state; | 588 | int state; |
587 | struct bio *bio; | 589 | struct bio *bio; |
588 | struct bio_list sync, nosync, recover, *this_list = NULL; | 590 | struct bio_list sync, nosync, recover, *this_list = NULL; |
591 | struct bio_list requeue; | ||
592 | struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh); | ||
593 | region_t region; | ||
589 | 594 | ||
590 | if (!writes->head) | 595 | if (!writes->head) |
591 | return; | 596 | return; |
@@ -596,10 +601,18 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes) | |||
596 | bio_list_init(&sync); | 601 | bio_list_init(&sync); |
597 | bio_list_init(&nosync); | 602 | bio_list_init(&nosync); |
598 | bio_list_init(&recover); | 603 | bio_list_init(&recover); |
604 | bio_list_init(&requeue); | ||
599 | 605 | ||
600 | while ((bio = bio_list_pop(writes))) { | 606 | while ((bio = bio_list_pop(writes))) { |
601 | state = dm_rh_get_state(ms->rh, | 607 | region = dm_rh_bio_to_region(ms->rh, bio); |
602 | dm_rh_bio_to_region(ms->rh, bio), 1); | 608 | |
609 | if (log->type->is_remote_recovering && | ||
610 | log->type->is_remote_recovering(log, region)) { | ||
611 | bio_list_add(&requeue, bio); | ||
612 | continue; | ||
613 | } | ||
614 | |||
615 | state = dm_rh_get_state(ms->rh, region, 1); | ||
603 | switch (state) { | 616 | switch (state) { |
604 | case DM_RH_CLEAN: | 617 | case DM_RH_CLEAN: |
605 | case DM_RH_DIRTY: | 618 | case DM_RH_DIRTY: |
@@ -619,6 +632,16 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes) | |||
619 | } | 632 | } |
620 | 633 | ||
621 | /* | 634 | /* |
635 | * Add bios that are delayed due to remote recovery | ||
636 | * back on to the write queue | ||
637 | */ | ||
638 | if (unlikely(requeue.head)) { | ||
639 | spin_lock_irq(&ms->lock); | ||
640 | bio_list_merge(&ms->writes, &requeue); | ||
641 | spin_unlock_irq(&ms->lock); | ||
642 | } | ||
643 | |||
644 | /* | ||
622 | * Increment the pending counts for any regions that will | 645 | * Increment the pending counts for any regions that will |
623 | * be written to (writes to recover regions are going to | 646 | * be written to (writes to recover regions are going to |
624 | * be delayed). | 647 | * be delayed). |
@@ -764,9 +787,9 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors, | |||
764 | atomic_set(&ms->suspend, 0); | 787 | atomic_set(&ms->suspend, 0); |
765 | atomic_set(&ms->default_mirror, DEFAULT_MIRROR); | 788 | atomic_set(&ms->default_mirror, DEFAULT_MIRROR); |
766 | 789 | ||
767 | len = sizeof(struct dm_raid1_read_record); | 790 | ms->read_record_pool = mempool_create_slab_pool(MIN_READ_RECORDS, |
768 | ms->read_record_pool = mempool_create_kmalloc_pool(MIN_READ_RECORDS, | 791 | _dm_raid1_read_record_cache); |
769 | len); | 792 | |
770 | if (!ms->read_record_pool) { | 793 | if (!ms->read_record_pool) { |
771 | ti->error = "Error creating mirror read_record_pool"; | 794 | ti->error = "Error creating mirror read_record_pool"; |
772 | kfree(ms); | 795 | kfree(ms); |
@@ -1279,16 +1302,31 @@ static int __init dm_mirror_init(void) | |||
1279 | { | 1302 | { |
1280 | int r; | 1303 | int r; |
1281 | 1304 | ||
1305 | _dm_raid1_read_record_cache = KMEM_CACHE(dm_raid1_read_record, 0); | ||
1306 | if (!_dm_raid1_read_record_cache) { | ||
1307 | DMERR("Can't allocate dm_raid1_read_record cache"); | ||
1308 | r = -ENOMEM; | ||
1309 | goto bad_cache; | ||
1310 | } | ||
1311 | |||
1282 | r = dm_register_target(&mirror_target); | 1312 | r = dm_register_target(&mirror_target); |
1283 | if (r < 0) | 1313 | if (r < 0) { |
1284 | DMERR("Failed to register mirror target"); | 1314 | DMERR("Failed to register mirror target"); |
1315 | goto bad_target; | ||
1316 | } | ||
1317 | |||
1318 | return 0; | ||
1285 | 1319 | ||
1320 | bad_target: | ||
1321 | kmem_cache_destroy(_dm_raid1_read_record_cache); | ||
1322 | bad_cache: | ||
1286 | return r; | 1323 | return r; |
1287 | } | 1324 | } |
1288 | 1325 | ||
1289 | static void __exit dm_mirror_exit(void) | 1326 | static void __exit dm_mirror_exit(void) |
1290 | { | 1327 | { |
1291 | dm_unregister_target(&mirror_target); | 1328 | dm_unregister_target(&mirror_target); |
1329 | kmem_cache_destroy(_dm_raid1_read_record_cache); | ||
1292 | } | 1330 | } |
1293 | 1331 | ||
1294 | /* Module hooks */ | 1332 | /* Module hooks */ |