diff options
| -rw-r--r-- | drivers/md/dm-thin.c | 125 |
1 files changed, 72 insertions, 53 deletions
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 7ca2bf2aafaa..188121ca00aa 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c | |||
| @@ -523,7 +523,7 @@ struct pool { | |||
| 523 | 523 | ||
| 524 | struct bio_list retry_on_resume_list; | 524 | struct bio_list retry_on_resume_list; |
| 525 | 525 | ||
| 526 | struct deferred_set ds; /* FIXME: move to thin_c */ | 526 | struct deferred_set shared_read_ds; |
| 527 | 527 | ||
| 528 | struct new_mapping *next_mapping; | 528 | struct new_mapping *next_mapping; |
| 529 | mempool_t *mapping_pool; | 529 | mempool_t *mapping_pool; |
| @@ -618,6 +618,12 @@ static struct pool *__pool_table_lookup_metadata_dev(struct block_device *md_dev | |||
| 618 | 618 | ||
| 619 | /*----------------------------------------------------------------*/ | 619 | /*----------------------------------------------------------------*/ |
| 620 | 620 | ||
| 621 | struct endio_hook { | ||
| 622 | struct thin_c *tc; | ||
| 623 | struct deferred_entry *shared_read_entry; | ||
| 624 | struct new_mapping *overwrite_mapping; | ||
| 625 | }; | ||
| 626 | |||
| 621 | static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master) | 627 | static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master) |
| 622 | { | 628 | { |
| 623 | struct bio *bio; | 629 | struct bio *bio; |
| @@ -628,7 +634,8 @@ static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master) | |||
| 628 | bio_list_init(master); | 634 | bio_list_init(master); |
| 629 | 635 | ||
| 630 | while ((bio = bio_list_pop(&bios))) { | 636 | while ((bio = bio_list_pop(&bios))) { |
| 631 | if (dm_get_mapinfo(bio)->ptr == tc) | 637 | struct endio_hook *h = dm_get_mapinfo(bio)->ptr; |
| 638 | if (h->tc == tc) | ||
| 632 | bio_endio(bio, DM_ENDIO_REQUEUE); | 639 | bio_endio(bio, DM_ENDIO_REQUEUE); |
| 633 | else | 640 | else |
| 634 | bio_list_add(master, bio); | 641 | bio_list_add(master, bio); |
| @@ -716,16 +723,11 @@ static void wake_worker(struct pool *pool) | |||
| 716 | /* | 723 | /* |
| 717 | * Bio endio functions. | 724 | * Bio endio functions. |
| 718 | */ | 725 | */ |
| 719 | struct endio_hook { | ||
| 720 | struct thin_c *tc; | ||
| 721 | bio_end_io_t *saved_bi_end_io; | ||
| 722 | struct deferred_entry *entry; | ||
| 723 | }; | ||
| 724 | |||
| 725 | struct new_mapping { | 726 | struct new_mapping { |
| 726 | struct list_head list; | 727 | struct list_head list; |
| 727 | 728 | ||
| 728 | int prepared; | 729 | unsigned quiesced:1; |
| 730 | unsigned prepared:1; | ||
| 729 | 731 | ||
| 730 | struct thin_c *tc; | 732 | struct thin_c *tc; |
| 731 | dm_block_t virt_block; | 733 | dm_block_t virt_block; |
| @@ -747,7 +749,7 @@ static void __maybe_add_mapping(struct new_mapping *m) | |||
| 747 | { | 749 | { |
| 748 | struct pool *pool = m->tc->pool; | 750 | struct pool *pool = m->tc->pool; |
| 749 | 751 | ||
| 750 | if (list_empty(&m->list) && m->prepared) { | 752 | if (m->quiesced && m->prepared) { |
| 751 | list_add(&m->list, &pool->prepared_mappings); | 753 | list_add(&m->list, &pool->prepared_mappings); |
| 752 | wake_worker(pool); | 754 | wake_worker(pool); |
| 753 | } | 755 | } |
| @@ -770,7 +772,8 @@ static void copy_complete(int read_err, unsigned long write_err, void *context) | |||
| 770 | static void overwrite_endio(struct bio *bio, int err) | 772 | static void overwrite_endio(struct bio *bio, int err) |
| 771 | { | 773 | { |
| 772 | unsigned long flags; | 774 | unsigned long flags; |
| 773 | struct new_mapping *m = dm_get_mapinfo(bio)->ptr; | 775 | struct endio_hook *h = dm_get_mapinfo(bio)->ptr; |
| 776 | struct new_mapping *m = h->overwrite_mapping; | ||
| 774 | struct pool *pool = m->tc->pool; | 777 | struct pool *pool = m->tc->pool; |
| 775 | 778 | ||
| 776 | m->err = err; | 779 | m->err = err; |
| @@ -781,31 +784,6 @@ static void overwrite_endio(struct bio *bio, int err) | |||
| 781 | spin_unlock_irqrestore(&pool->lock, flags); | 784 | spin_unlock_irqrestore(&pool->lock, flags); |
| 782 | } | 785 | } |
| 783 | 786 | ||
| 784 | static void shared_read_endio(struct bio *bio, int err) | ||
| 785 | { | ||
| 786 | struct list_head mappings; | ||
| 787 | struct new_mapping *m, *tmp; | ||
| 788 | struct endio_hook *h = dm_get_mapinfo(bio)->ptr; | ||
| 789 | unsigned long flags; | ||
| 790 | struct pool *pool = h->tc->pool; | ||
| 791 | |||
| 792 | bio->bi_end_io = h->saved_bi_end_io; | ||
| 793 | bio_endio(bio, err); | ||
| 794 | |||
| 795 | INIT_LIST_HEAD(&mappings); | ||
| 796 | ds_dec(h->entry, &mappings); | ||
| 797 | |||
| 798 | spin_lock_irqsave(&pool->lock, flags); | ||
| 799 | list_for_each_entry_safe(m, tmp, &mappings, list) { | ||
| 800 | list_del(&m->list); | ||
| 801 | INIT_LIST_HEAD(&m->list); | ||
| 802 | __maybe_add_mapping(m); | ||
| 803 | } | ||
| 804 | spin_unlock_irqrestore(&pool->lock, flags); | ||
| 805 | |||
| 806 | mempool_free(h, pool->endio_hook_pool); | ||
| 807 | } | ||
| 808 | |||
| 809 | /*----------------------------------------------------------------*/ | 787 | /*----------------------------------------------------------------*/ |
| 810 | 788 | ||
| 811 | /* | 789 | /* |
| @@ -957,6 +935,7 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block, | |||
| 957 | struct new_mapping *m = get_next_mapping(pool); | 935 | struct new_mapping *m = get_next_mapping(pool); |
| 958 | 936 | ||
| 959 | INIT_LIST_HEAD(&m->list); | 937 | INIT_LIST_HEAD(&m->list); |
| 938 | m->quiesced = 0; | ||
| 960 | m->prepared = 0; | 939 | m->prepared = 0; |
| 961 | m->tc = tc; | 940 | m->tc = tc; |
| 962 | m->virt_block = virt_block; | 941 | m->virt_block = virt_block; |
| @@ -965,7 +944,8 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block, | |||
| 965 | m->err = 0; | 944 | m->err = 0; |
| 966 | m->bio = NULL; | 945 | m->bio = NULL; |
| 967 | 946 | ||
| 968 | ds_add_work(&pool->ds, &m->list); | 947 | if (!ds_add_work(&pool->shared_read_ds, &m->list)) |
| 948 | m->quiesced = 1; | ||
| 969 | 949 | ||
| 970 | /* | 950 | /* |
| 971 | * IO to pool_dev remaps to the pool target's data_dev. | 951 | * IO to pool_dev remaps to the pool target's data_dev. |
| @@ -974,9 +954,10 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block, | |||
| 974 | * bio immediately. Otherwise we use kcopyd to clone the data first. | 954 | * bio immediately. Otherwise we use kcopyd to clone the data first. |
| 975 | */ | 955 | */ |
| 976 | if (io_overwrites_block(pool, bio)) { | 956 | if (io_overwrites_block(pool, bio)) { |
| 957 | struct endio_hook *h = dm_get_mapinfo(bio)->ptr; | ||
| 958 | h->overwrite_mapping = m; | ||
| 977 | m->bio = bio; | 959 | m->bio = bio; |
| 978 | save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio); | 960 | save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio); |
| 979 | dm_get_mapinfo(bio)->ptr = m; | ||
| 980 | remap_and_issue(tc, bio, data_dest); | 961 | remap_and_issue(tc, bio, data_dest); |
| 981 | } else { | 962 | } else { |
| 982 | struct dm_io_region from, to; | 963 | struct dm_io_region from, to; |
| @@ -1023,6 +1004,7 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block, | |||
| 1023 | struct new_mapping *m = get_next_mapping(pool); | 1004 | struct new_mapping *m = get_next_mapping(pool); |
| 1024 | 1005 | ||
| 1025 | INIT_LIST_HEAD(&m->list); | 1006 | INIT_LIST_HEAD(&m->list); |
| 1007 | m->quiesced = 1; | ||
| 1026 | m->prepared = 0; | 1008 | m->prepared = 0; |
| 1027 | m->tc = tc; | 1009 | m->tc = tc; |
| 1028 | m->virt_block = virt_block; | 1010 | m->virt_block = virt_block; |
| @@ -1040,9 +1022,10 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block, | |||
| 1040 | process_prepared_mapping(m); | 1022 | process_prepared_mapping(m); |
| 1041 | 1023 | ||
| 1042 | else if (io_overwrites_block(pool, bio)) { | 1024 | else if (io_overwrites_block(pool, bio)) { |
| 1025 | struct endio_hook *h = dm_get_mapinfo(bio)->ptr; | ||
| 1026 | h->overwrite_mapping = m; | ||
| 1043 | m->bio = bio; | 1027 | m->bio = bio; |
| 1044 | save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio); | 1028 | save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio); |
| 1045 | dm_get_mapinfo(bio)->ptr = m; | ||
| 1046 | remap_and_issue(tc, bio, data_block); | 1029 | remap_and_issue(tc, bio, data_block); |
| 1047 | 1030 | ||
| 1048 | } else { | 1031 | } else { |
| @@ -1129,7 +1112,8 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result) | |||
| 1129 | */ | 1112 | */ |
| 1130 | static void retry_on_resume(struct bio *bio) | 1113 | static void retry_on_resume(struct bio *bio) |
| 1131 | { | 1114 | { |
| 1132 | struct thin_c *tc = dm_get_mapinfo(bio)->ptr; | 1115 | struct endio_hook *h = dm_get_mapinfo(bio)->ptr; |
| 1116 | struct thin_c *tc = h->tc; | ||
| 1133 | struct pool *pool = tc->pool; | 1117 | struct pool *pool = tc->pool; |
| 1134 | unsigned long flags; | 1118 | unsigned long flags; |
| 1135 | 1119 | ||
| @@ -1195,13 +1179,9 @@ static void process_shared_bio(struct thin_c *tc, struct bio *bio, | |||
| 1195 | if (bio_data_dir(bio) == WRITE) | 1179 | if (bio_data_dir(bio) == WRITE) |
| 1196 | break_sharing(tc, bio, block, &key, lookup_result, cell); | 1180 | break_sharing(tc, bio, block, &key, lookup_result, cell); |
| 1197 | else { | 1181 | else { |
| 1198 | struct endio_hook *h; | 1182 | struct endio_hook *h = dm_get_mapinfo(bio)->ptr; |
| 1199 | |||
