diff options
author | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2011-08-04 11:15:33 -0400 |
---|---|---|
committer | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2011-09-29 07:38:42 -0400 |
commit | a1d3c4786a4b9c71c0767aa656a759968f7554b6 (patch) | |
tree | 1dc5596ca57f261d2816111e51a2f33928bbe4a6 | |
parent | d7728c960dccf775b92f2c4139f1216275a45c44 (diff) |
btrfs: btrfs_multi_bio replaced with btrfs_bio
btrfs_bio is a bio abstraction able to split and not complete after the last
bio has returned (like the old btrfs_multi_bio). Additionally, btrfs_bio
tracks the mirror_num used to read data which can be used for error
correction purposes.
Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
-rw-r--r-- | fs/btrfs/extent-tree.c | 10 | ||||
-rw-r--r-- | fs/btrfs/scrub.c | 20 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 128 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 10 |
4 files changed, 90 insertions, 78 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index f5be06a2462f..119f842c1d4f 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -1770,18 +1770,18 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, | |||
1770 | { | 1770 | { |
1771 | int ret; | 1771 | int ret; |
1772 | u64 discarded_bytes = 0; | 1772 | u64 discarded_bytes = 0; |
1773 | struct btrfs_multi_bio *multi = NULL; | 1773 | struct btrfs_bio *bbio = NULL; |
1774 | 1774 | ||
1775 | 1775 | ||
1776 | /* Tell the block device(s) that the sectors can be discarded */ | 1776 | /* Tell the block device(s) that the sectors can be discarded */ |
1777 | ret = btrfs_map_block(&root->fs_info->mapping_tree, REQ_DISCARD, | 1777 | ret = btrfs_map_block(&root->fs_info->mapping_tree, REQ_DISCARD, |
1778 | bytenr, &num_bytes, &multi, 0); | 1778 | bytenr, &num_bytes, &bbio, 0); |
1779 | if (!ret) { | 1779 | if (!ret) { |
1780 | struct btrfs_bio_stripe *stripe = multi->stripes; | 1780 | struct btrfs_bio_stripe *stripe = bbio->stripes; |
1781 | int i; | 1781 | int i; |
1782 | 1782 | ||
1783 | 1783 | ||
1784 | for (i = 0; i < multi->num_stripes; i++, stripe++) { | 1784 | for (i = 0; i < bbio->num_stripes; i++, stripe++) { |
1785 | if (!stripe->dev->can_discard) | 1785 | if (!stripe->dev->can_discard) |
1786 | continue; | 1786 | continue; |
1787 | 1787 | ||
@@ -1800,7 +1800,7 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, | |||
1800 | */ | 1800 | */ |
1801 | ret = 0; | 1801 | ret = 0; |
1802 | } | 1802 | } |
1803 | kfree(multi); | 1803 | kfree(bbio); |
1804 | } | 1804 | } |
1805 | 1805 | ||
1806 | if (actual_bytes) | 1806 | if (actual_bytes) |
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index db09f01c0e4f..97142a218f0a 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
@@ -572,7 +572,7 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix) | |||
572 | struct scrub_dev *sdev = sbio->sdev; | 572 | struct scrub_dev *sdev = sbio->sdev; |
573 | struct btrfs_fs_info *fs_info = sdev->dev->dev_root->fs_info; | 573 | struct btrfs_fs_info *fs_info = sdev->dev->dev_root->fs_info; |
574 | struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree; | 574 | struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree; |
575 | struct btrfs_multi_bio *multi = NULL; | 575 | struct btrfs_bio *bbio = NULL; |
576 | struct scrub_fixup_nodatasum *fixup; | 576 | struct scrub_fixup_nodatasum *fixup; |
577 | u64 logical = sbio->logical + ix * PAGE_SIZE; | 577 | u64 logical = sbio->logical + ix * PAGE_SIZE; |
578 | u64 length; | 578 | u64 length; |
@@ -610,8 +610,8 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix) | |||
610 | 610 | ||
611 | length = PAGE_SIZE; | 611 | length = PAGE_SIZE; |
612 | ret = btrfs_map_block(map_tree, REQ_WRITE, logical, &length, | 612 | ret = btrfs_map_block(map_tree, REQ_WRITE, logical, &length, |
613 | &multi, 0); | 613 | &bbio, 0); |
614 | if (ret || !multi || length < PAGE_SIZE) { | 614 | if (ret || !bbio || length < PAGE_SIZE) { |
615 | printk(KERN_ERR | 615 | printk(KERN_ERR |
616 | "scrub_fixup: btrfs_map_block failed us for %llu\n", | 616 | "scrub_fixup: btrfs_map_block failed us for %llu\n", |
617 | (unsigned long long)logical); | 617 | (unsigned long long)logical); |
@@ -619,19 +619,19 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix) | |||
619 | return; | 619 | return; |
620 | } | 620 | } |
621 | 621 | ||
622 | if (multi->num_stripes == 1) | 622 | if (bbio->num_stripes == 1) |
623 | /* there aren't any replicas */ | 623 | /* there aren't any replicas */ |
624 | goto uncorrectable; | 624 | goto uncorrectable; |
625 | 625 | ||
626 | /* | 626 | /* |
627 | * first find a good copy | 627 | * first find a good copy |
628 | */ | 628 | */ |
629 | for (i = 0; i < multi->num_stripes; ++i) { | 629 | for (i = 0; i < bbio->num_stripes; ++i) { |
630 | if (i + 1 == sbio->spag[ix].mirror_num) | 630 | if (i + 1 == sbio->spag[ix].mirror_num) |
631 | continue; | 631 | continue; |
632 | 632 | ||
633 | if (scrub_fixup_io(READ, multi->stripes[i].dev->bdev, | 633 | if (scrub_fixup_io(READ, bbio->stripes[i].dev->bdev, |
634 | multi->stripes[i].physical >> 9, | 634 | bbio->stripes[i].physical >> 9, |
635 | sbio->bio->bi_io_vec[ix].bv_page)) { | 635 | sbio->bio->bi_io_vec[ix].bv_page)) { |
636 | /* I/O-error, this is not a good copy */ | 636 | /* I/O-error, this is not a good copy */ |
637 | continue; | 637 | continue; |
@@ -640,7 +640,7 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix) | |||
640 | if (scrub_fixup_check(sbio, ix) == 0) | 640 | if (scrub_fixup_check(sbio, ix) == 0) |
641 | break; | 641 | break; |
642 | } | 642 | } |
643 | if (i == multi->num_stripes) | 643 | if (i == bbio->num_stripes) |
644 | goto uncorrectable; | 644 | goto uncorrectable; |
645 | 645 | ||
646 | if (!sdev->readonly) { | 646 | if (!sdev->readonly) { |
@@ -655,7 +655,7 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix) | |||
655 | } | 655 | } |
656 | } | 656 | } |
657 | 657 | ||
658 | kfree(multi); | 658 | kfree(bbio); |
659 | spin_lock(&sdev->stat_lock); | 659 | spin_lock(&sdev->stat_lock); |
660 | ++sdev->stat.corrected_errors; | 660 | ++sdev->stat.corrected_errors; |
661 | spin_unlock(&sdev->stat_lock); | 661 | spin_unlock(&sdev->stat_lock); |
@@ -665,7 +665,7 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix) | |||
665 | return; | 665 | return; |
666 | 666 | ||
667 | uncorrectable: | 667 | uncorrectable: |
668 | kfree(multi); | 668 | kfree(bbio); |
669 | spin_lock(&sdev->stat_lock); | 669 | spin_lock(&sdev->stat_lock); |
670 | ++sdev->stat.uncorrectable_errors; | 670 | ++sdev->stat.uncorrectable_errors; |
671 | spin_unlock(&sdev->stat_lock); | 671 | spin_unlock(&sdev->stat_lock); |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index f2a4cc79da61..9db4d7962f9b 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -2848,7 +2848,7 @@ static int find_live_mirror(struct map_lookup *map, int first, int num, | |||
2848 | 2848 | ||
2849 | static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | 2849 | static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, |
2850 | u64 logical, u64 *length, | 2850 | u64 logical, u64 *length, |
2851 | struct btrfs_multi_bio **multi_ret, | 2851 | struct btrfs_bio **bbio_ret, |
2852 | int mirror_num) | 2852 | int mirror_num) |
2853 | { | 2853 | { |
2854 | struct extent_map *em; | 2854 | struct extent_map *em; |
@@ -2866,18 +2866,18 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
2866 | int i; | 2866 | int i; |
2867 | int num_stripes; | 2867 | int num_stripes; |
2868 | int max_errors = 0; | 2868 | int max_errors = 0; |
2869 | struct btrfs_multi_bio *multi = NULL; | 2869 | struct btrfs_bio *bbio = NULL; |
2870 | 2870 | ||
2871 | if (multi_ret && !(rw & (REQ_WRITE | REQ_DISCARD))) | 2871 | if (bbio_ret && !(rw & (REQ_WRITE | REQ_DISCARD))) |
2872 | stripes_allocated = 1; | 2872 | stripes_allocated = 1; |
2873 | again: | 2873 | again: |
2874 | if (multi_ret) { | 2874 | if (bbio_ret) { |
2875 | multi = kzalloc(btrfs_multi_bio_size(stripes_allocated), | 2875 | bbio = kzalloc(btrfs_bio_size(stripes_allocated), |
2876 | GFP_NOFS); | 2876 | GFP_NOFS); |
2877 | if (!multi) | 2877 | if (!bbio) |
2878 | return -ENOMEM; | 2878 | return -ENOMEM; |
2879 | 2879 | ||
2880 | atomic_set(&multi->error, 0); | 2880 | atomic_set(&bbio->error, 0); |
2881 | } | 2881 | } |
2882 | 2882 | ||
2883 | read_lock(&em_tree->lock); | 2883 | read_lock(&em_tree->lock); |
@@ -2898,7 +2898,7 @@ again: | |||
2898 | if (mirror_num > map->num_stripes) | 2898 | if (mirror_num > map->num_stripes) |
2899 | mirror_num = 0; | 2899 | mirror_num = 0; |
2900 | 2900 | ||
2901 | /* if our multi bio struct is too small, back off and try again */ | 2901 | /* if our btrfs_bio struct is too small, back off and try again */ |
2902 | if (rw & REQ_WRITE) { | 2902 | if (rw & REQ_WRITE) { |
2903 | if (map->type & (BTRFS_BLOCK_GROUP_RAID1 | | 2903 | if (map->type & (BTRFS_BLOCK_GROUP_RAID1 | |
2904 | BTRFS_BLOCK_GROUP_DUP)) { | 2904 | BTRFS_BLOCK_GROUP_DUP)) { |
@@ -2917,11 +2917,11 @@ again: | |||
2917 | stripes_required = map->num_stripes; | 2917 | stripes_required = map->num_stripes; |
2918 | } | 2918 | } |
2919 | } | 2919 | } |
2920 | if (multi_ret && (rw & (REQ_WRITE | REQ_DISCARD)) && | 2920 | if (bbio_ret && (rw & (REQ_WRITE | REQ_DISCARD)) && |
2921 | stripes_allocated < stripes_required) { | 2921 | stripes_allocated < stripes_required) { |
2922 | stripes_allocated = map->num_stripes; | 2922 | stripes_allocated = map->num_stripes; |
2923 | free_extent_map(em); | 2923 | free_extent_map(em); |
2924 | kfree(multi); | 2924 | kfree(bbio); |
2925 | goto again; | 2925 | goto again; |
2926 | } | 2926 | } |
2927 | stripe_nr = offset; | 2927 | stripe_nr = offset; |
@@ -2950,7 +2950,7 @@ again: | |||
2950 | *length = em->len - offset; | 2950 | *length = em->len - offset; |
2951 | } | 2951 | } |
2952 | 2952 | ||
2953 | if (!multi_ret) | 2953 | if (!bbio_ret) |
2954 | goto out; | 2954 | goto out; |
2955 | 2955 | ||
2956 | num_stripes = 1; | 2956 | num_stripes = 1; |
@@ -2975,13 +2975,17 @@ again: | |||
2975 | stripe_index = find_live_mirror(map, 0, | 2975 | stripe_index = find_live_mirror(map, 0, |
2976 | map->num_stripes, | 2976 | map->num_stripes, |
2977 | current->pid % map->num_stripes); | 2977 | current->pid % map->num_stripes); |
2978 | mirror_num = stripe_index + 1; | ||
2978 | } | 2979 | } |
2979 | 2980 | ||
2980 | } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { | 2981 | } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { |
2981 | if (rw & (REQ_WRITE | REQ_DISCARD)) | 2982 | if (rw & (REQ_WRITE | REQ_DISCARD)) { |
2982 | num_stripes = map->num_stripes; | 2983 | num_stripes = map->num_stripes; |
2983 | else if (mirror_num) | 2984 | } else if (mirror_num) { |
2984 | stripe_index = mirror_num - 1; | 2985 | stripe_index = mirror_num - 1; |
2986 | } else { | ||
2987 | mirror_num = 1; | ||
2988 | } | ||
2985 | 2989 | ||
2986 | } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { | 2990 | } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { |
2987 | int factor = map->num_stripes / map->sub_stripes; | 2991 | int factor = map->num_stripes / map->sub_stripes; |
@@ -3001,6 +3005,7 @@ again: | |||
3001 | stripe_index = find_live_mirror(map, stripe_index, | 3005 | stripe_index = find_live_mirror(map, stripe_index, |
3002 | map->sub_stripes, stripe_index + | 3006 | map->sub_stripes, stripe_index + |
3003 | current->pid % map->sub_stripes); | 3007 | current->pid % map->sub_stripes); |
3008 | mirror_num = stripe_index + 1; | ||
3004 | } | 3009 | } |
3005 | } else { | 3010 | } else { |
3006 | /* | 3011 | /* |
@@ -3009,15 +3014,16 @@ again: | |||
3009 | * stripe_index is the number of our device in the stripe array | 3014 | * stripe_index is the number of our device in the stripe array |
3010 | */ | 3015 | */ |
3011 | stripe_index = do_div(stripe_nr, map->num_stripes); | 3016 | stripe_index = do_div(stripe_nr, map->num_stripes); |
3017 | mirror_num = stripe_index + 1; | ||
3012 | } | 3018 | } |
3013 | BUG_ON(stripe_index >= map->num_stripes); | 3019 | BUG_ON(stripe_index >= map->num_stripes); |
3014 | 3020 | ||
3015 | if (rw & REQ_DISCARD) { | 3021 | if (rw & REQ_DISCARD) { |
3016 | for (i = 0; i < num_stripes; i++) { | 3022 | for (i = 0; i < num_stripes; i++) { |
3017 | multi->stripes[i].physical = | 3023 | bbio->stripes[i].physical = |
3018 | map->stripes[stripe_index].physical + | 3024 | map->stripes[stripe_index].physical + |
3019 | stripe_offset + stripe_nr * map->stripe_len; | 3025 | stripe_offset + stripe_nr * map->stripe_len; |
3020 | multi->stripes[i].dev = map->stripes[stripe_index].dev; | 3026 | bbio->stripes[i].dev = map->stripes[stripe_index].dev; |
3021 | 3027 | ||
3022 | if (map->type & BTRFS_BLOCK_GROUP_RAID0) { | 3028 | if (map->type & BTRFS_BLOCK_GROUP_RAID0) { |
3023 | u64 stripes; | 3029 | u64 stripes; |
@@ -3038,16 +3044,16 @@ again: | |||
3038 | } | 3044 | } |
3039 | stripes = stripe_nr_end - 1 - j; | 3045 | stripes = stripe_nr_end - 1 - j; |
3040 | do_div(stripes, map->num_stripes); | 3046 | do_div(stripes, map->num_stripes); |
3041 | multi->stripes[i].length = map->stripe_len * | 3047 | bbio->stripes[i].length = map->stripe_len * |
3042 | (stripes - stripe_nr + 1); | 3048 | (stripes - stripe_nr + 1); |
3043 | 3049 | ||
3044 | if (i == 0) { | 3050 | if (i == 0) { |
3045 | multi->stripes[i].length -= | 3051 | bbio->stripes[i].length -= |
3046 | stripe_offset; | 3052 | stripe_offset; |
3047 | stripe_offset = 0; | 3053 | stripe_offset = 0; |
3048 | } | 3054 | } |
3049 | if (stripe_index == last_stripe) | 3055 | if (stripe_index == last_stripe) |
3050 | multi->stripes[i].length -= | 3056 | bbio->stripes[i].length -= |
3051 | stripe_end_offset; | 3057 | stripe_end_offset; |
3052 | } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { | 3058 | } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { |
3053 | u64 stripes; | 3059 | u64 stripes; |
@@ -3072,11 +3078,11 @@ again: | |||
3072 | } | 3078 | } |
3073 | stripes = stripe_nr_end - 1 - j; | 3079 | stripes = stripe_nr_end - 1 - j; |
3074 | do_div(stripes, factor); | 3080 | do_div(stripes, factor); |
3075 | multi->stripes[i].length = map->stripe_len * | 3081 | bbio->stripes[i].length = map->stripe_len * |
3076 | (stripes - stripe_nr + 1); | 3082 | (stripes - stripe_nr + 1); |
3077 | 3083 | ||
3078 | if (i < map->sub_stripes) { | 3084 | if (i < map->sub_stripes) { |
3079 | multi->stripes[i].length -= | 3085 | bbio->stripes[i].length -= |
3080 | stripe_offset; | 3086 | stripe_offset; |
3081 | if (i == map->sub_stripes - 1) | 3087 | if (i == map->sub_stripes - 1) |
3082 | stripe_offset = 0; | 3088 | stripe_offset = 0; |
@@ -3084,11 +3090,11 @@ again: | |||
3084 | if (stripe_index >= last_stripe && | 3090 | if (stripe_index >= last_stripe && |
3085 | stripe_index <= (last_stripe + | 3091 | stripe_index <= (last_stripe + |
3086 | map->sub_stripes - 1)) { | 3092 | map->sub_stripes - 1)) { |
3087 | multi->stripes[i].length -= | 3093 | bbio->stripes[i].length -= |
3088 | stripe_end_offset; | 3094 | stripe_end_offset; |
3089 | } | 3095 | } |
3090 | } else | 3096 | } else |
3091 | multi->stripes[i].length = *length; | 3097 | bbio->stripes[i].length = *length; |
3092 | 3098 | ||
3093 | stripe_index++; | 3099 | stripe_index++; |
3094 | if (stripe_index == map->num_stripes) { | 3100 | if (stripe_index == map->num_stripes) { |
@@ -3099,19 +3105,20 @@ again: | |||
3099 | } | 3105 | } |
3100 | } else { | 3106 | } else { |
3101 | for (i = 0; i < num_stripes; i++) { | 3107 | for (i = 0; i < num_stripes; i++) { |
3102 | multi->stripes[i].physical = | 3108 | bbio->stripes[i].physical = |
3103 | map->stripes[stripe_index].physical + | 3109 | map->stripes[stripe_index].physical + |
3104 | stripe_offset + | 3110 | stripe_offset + |
3105 | stripe_nr * map->stripe_len; | 3111 | stripe_nr * map->stripe_len; |
3106 | multi->stripes[i].dev = | 3112 | bbio->stripes[i].dev = |
3107 | map->stripes[stripe_index].dev; | 3113 | map->stripes[stripe_index].dev; |
3108 | stripe_index++; | 3114 | stripe_index++; |
3109 | } | 3115 | } |
3110 | } | 3116 | } |
3111 | if (multi_ret) { | 3117 | if (bbio_ret) { |
3112 | *multi_ret = multi; | 3118 | *bbio_ret = bbio; |
3113 | multi->num_stripes = num_stripes; | 3119 | bbio->num_stripes = num_stripes; |
3114 | multi->max_errors = max_errors; | 3120 | bbio->max_errors = max_errors; |
3121 | bbio->mirror_num = mirror_num; | ||
3115 | } | 3122 | } |
3116 | out: | 3123 | out: |
3117 | free_extent_map(em); | 3124 | free_extent_map(em); |
@@ -3120,9 +3127,9 @@ out: | |||
3120 | 3127 | ||
3121 | int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | 3128 | int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, |
3122 | u64 logical, u64 *length, | 3129 | u64 logical, u64 *length, |
3123 | struct btrfs_multi_bio **multi_ret, int mirror_num) | 3130 | struct btrfs_bio **bbio_ret, int mirror_num) |
3124 | { | 3131 | { |
3125 | return __btrfs_map_block(map_tree, rw, logical, length, multi_ret, | 3132 | return __btrfs_map_block(map_tree, rw, logical, length, bbio_ret, |
3126 | mirror_num); | 3133 | mirror_num); |
3127 | } | 3134 | } |
3128 | 3135 | ||
@@ -3191,28 +3198,28 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, | |||
3191 | return 0; | 3198 | return 0; |
3192 | } | 3199 | } |
3193 | 3200 | ||
3194 | static void end_bio_multi_stripe(struct bio *bio, int err) | 3201 | static void btrfs_end_bio(struct bio *bio, int err) |
3195 | { | 3202 | { |
3196 | struct btrfs_multi_bio *multi = bio->bi_private; | 3203 | struct btrfs_bio *bbio = bio->bi_private; |
3197 | int is_orig_bio = 0; | 3204 | int is_orig_bio = 0; |
3198 | 3205 | ||
3199 | if (err) | 3206 | if (err) |
3200 | atomic_inc(&multi->error); | 3207 | atomic_inc(&bbio->error); |
3201 | 3208 | ||
3202 | if (bio == multi->orig_bio) | 3209 | if (bio == bbio->orig_bio) |
3203 | is_orig_bio = 1; | 3210 | is_orig_bio = 1; |
3204 | 3211 | ||
3205 | if (atomic_dec_and_test(&multi->stripes_pending)) { | 3212 | if (atomic_dec_and_test(&bbio->stripes_pending)) { |
3206 | if (!is_orig_bio) { | 3213 | if (!is_orig_bio) { |
3207 | bio_put(bio); | 3214 | bio_put(bio); |
3208 | bio = multi->orig_bio; | 3215 | bio = bbio->orig_bio; |
3209 | } | 3216 | } |
3210 | bio->bi_private = multi->private; | 3217 | bio->bi_private = bbio->private; |
3211 | bio->bi_end_io = multi->end_io; | 3218 | bio->bi_end_io = bbio->end_io; |
3212 | /* only send an error to the higher layers if it is | 3219 | /* only send an error to the higher layers if it is |
3213 | * beyond the tolerance of the multi-bio | 3220 | * beyond the tolerance of the multi-bio |
3214 | */ | 3221 | */ |
3215 | if (atomic_read(&multi->error) > multi->max_errors) { | 3222 | if (atomic_read(&bbio->error) > bbio->max_errors) { |
3216 | err = -EIO; | 3223 | err = -EIO; |
3217 | } else if (err) { | 3224 | } else if (err) { |
3218 | /* | 3225 | /* |
@@ -3222,7 +3229,7 @@ static void end_bio_multi_stripe(struct bio *bio, int err) | |||
3222 | set_bit(BIO_UPTODATE, &bio->bi_flags); | 3229 | set_bit(BIO_UPTODATE, &bio->bi_flags); |
3223 | err = 0; | 3230 | err = 0; |
3224 | } | 3231 | } |
3225 | kfree(multi); | 3232 | kfree(bbio); |
3226 | 3233 | ||
3227 | bio_endio(bio, err); | 3234 | bio_endio(bio, err); |
3228 | } else if (!is_orig_bio) { | 3235 | } else if (!is_orig_bio) { |
@@ -3302,20 +3309,20 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, | |||
3302 | u64 logical = (u64)bio->bi_sector << 9; | 3309 | u64 logical = (u64)bio->bi_sector << 9; |
3303 | u64 length = 0; | 3310 | u64 length = 0; |
3304 | u64 map_length; | 3311 | u64 map_length; |
3305 | struct btrfs_multi_bio *multi = NULL; | ||
3306 | int ret; | 3312 | int ret; |
3307 | int dev_nr = 0; | 3313 | int dev_nr = 0; |
3308 | int total_devs = 1; | 3314 | int total_devs = 1; |
3315 | struct btrfs_bio *bbio = NULL; | ||
3309 | 3316 | ||
3310 | length = bio->bi_size; | 3317 | length = bio->bi_size; |
3311 | map_tree = &root->fs_info->mapping_tree; | 3318 | map_tree = &root->fs_info->mapping_tree; |
3312 | map_length = length; | 3319 | map_length = length; |
3313 | 3320 | ||
3314 | ret = btrfs_map_block(map_tree, rw, logical, &map_length, &multi, | 3321 | ret = btrfs_map_block(map_tree, rw, logical, &map_length, &bbio, |
3315 | mirror_num); | 3322 | mirror_num); |
3316 | BUG_ON(ret); | 3323 | BUG_ON(ret); |
3317 | 3324 | ||
3318 | total_devs = multi->num_stripes; | 3325 | total_devs = bbio->num_stripes; |
3319 | if (map_length < length) { | 3326 | if (map_length < length) { |
3320 | printk(KERN_CRIT "mapping failed logical %llu bio len %llu " | 3327 | printk(KERN_CRIT "mapping failed logical %llu bio len %llu " |
3321 | "len %llu\n", (unsigned long long)logical, | 3328 | "len %llu\n", (unsigned long long)logical, |
@@ -3323,25 +3330,28 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, | |||
3323 | (unsigned long long)map_length); | 3330 | (unsigned long long)map_length); |
3324 | BUG(); | 3331 | BUG(); |
3325 | } | 3332 | } |
3326 | multi->end_io = first_bio->bi_end_io; | 3333 | |
3327 | multi->private = first_bio->bi_private; | 3334 | bbio->orig_bio = first_bio; |
3328 | multi->orig_bio = first_bio; | 3335 | bbio->private = first_bio->bi_private; |
3329 | atomic_set(&multi->stripes_pending, multi->num_stripes); | 3336 | bbio->end_io = first_bio->bi_end_io; |
3337 | atomic_set(&bbio->stripes_pending, bbio->num_stripes); | ||
3330 | 3338 | ||
3331 | while (dev_nr < total_devs) { | 3339 | while (dev_nr < total_devs) { |
3332 | if (total_devs > 1) { | 3340 | if (dev_nr < total_devs - 1) { |
3333 | if (dev_nr < total_devs - 1) { | 3341 | bio = bio_clone(first_bio, GFP_NOFS); |
3334 | bio = bio_clone(first_bio, GFP_NOFS); | 3342 | BUG_ON(!bio); |
3335 | BUG_ON(!bio); | 3343 | } else { |
3336 | } else { | 3344 | bio = first_bio; |
3337 | bio = first_bio; | ||
3338 | } | ||
3339 | bio->bi_private = multi; | ||
3340 | bio->bi_end_io = end_bio_multi_stripe; | ||
3341 | } | 3345 | } |
3342 | bio->bi_sector = multi->stripes[dev_nr].physical >> 9; | 3346 | bio->bi_private = bbio; |
3343 | dev = multi->stripes[dev_nr].dev; | 3347 | bio->bi_end_io = btrfs_end_bio; |
3348 | bio->bi_sector = bbio->stripes[dev_nr].physical >> 9; | ||
3349 | dev = bbio->stripes[dev_nr].dev; | ||
3344 | if (dev && dev->bdev && (rw != WRITE || dev->writeable)) { | 3350 | if (dev && dev->bdev && (rw != WRITE || dev->writeable)) { |
3351 | pr_debug("btrfs_map_bio: rw %d, secor=%llu, dev=%lu " | ||
3352 | "(%s id %llu), size=%u\n", rw, | ||
3353 | (u64)bio->bi_sector, (u_long)dev->bdev->bd_dev, | ||
3354 | dev->name, dev->devid, bio->bi_size); | ||
3345 | bio->bi_bdev = dev->bdev; | 3355 | bio->bi_bdev = dev->bdev; |
3346 | if (async_submit) | 3356 | if (async_submit) |
3347 | schedule_bio(root, dev, rw, bio); | 3357 | schedule_bio(root, dev, rw, bio); |
@@ -3354,8 +3364,6 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, | |||
3354 | } | 3364 | } |
3355 | dev_nr++; | 3365 | dev_nr++; |
3356 | } | 3366 | } |
3357 | if (total_devs == 1) | ||
3358 | kfree(multi); | ||
3359 | return 0; | 3367 | return 0; |
3360 | } | 3368 | } |
3361 | 3369 | ||
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 6d866db4e177..71f4f3f67495 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
@@ -136,7 +136,10 @@ struct btrfs_bio_stripe { | |||
136 | u64 length; /* only used for discard mappings */ | 136 | u64 length; /* only used for discard mappings */ |
137 | }; | 137 | }; |
138 | 138 | ||
139 | struct btrfs_multi_bio { | 139 | struct btrfs_bio; |
140 | typedef void (btrfs_bio_end_io_t) (struct btrfs_bio *bio, int err); | ||
141 | |||
142 | struct btrfs_bio { | ||
140 | atomic_t stripes_pending; | 143 | atomic_t stripes_pending; |
141 | bio_end_io_t *end_io; | 144 | bio_end_io_t *end_io; |
142 | struct bio *orig_bio; | 145 | struct bio *orig_bio; |
@@ -144,6 +147,7 @@ struct btrfs_multi_bio { | |||
144 | atomic_t error; | 147 | atomic_t error; |
145 | int max_errors; | 148 | int max_errors; |
146 | int num_stripes; | 149 | int num_stripes; |
150 | int mirror_num; | ||
147 | struct btrfs_bio_stripe stripes[]; | 151 | struct btrfs_bio_stripe stripes[]; |
148 | }; | 152 | }; |
149 | 153 | ||
@@ -171,7 +175,7 @@ struct map_lookup { | |||
171 | int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start, | 175 | int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start, |
172 | u64 end, u64 *length); | 176 | u64 end, u64 *length); |
173 | 177 | ||
174 | #define btrfs_multi_bio_size(n) (sizeof(struct btrfs_multi_bio) + \ | 178 | #define btrfs_bio_size(n) (sizeof(struct btrfs_bio) + \ |
175 | (sizeof(struct btrfs_bio_stripe) * (n))) | 179 | (sizeof(struct btrfs_bio_stripe) * (n))) |
176 | 180 | ||
177 | int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, | 181 | int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, |
@@ -180,7 +184,7 @@ int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, | |||
180 | u64 chunk_offset, u64 start, u64 num_bytes); | 184 | u64 chunk_offset, u64 start, u64 num_bytes); |
181 | int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | 185 | int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, |
182 | u64 logical, u64 *length, | 186 | u64 logical, u64 *length, |
183 | struct btrfs_multi_bio **multi_ret, int mirror_num); | 187 | struct btrfs_bio **bbio_ret, int mirror_num); |
184 | int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, | 188 | int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, |
185 | u64 chunk_start, u64 physical, u64 devid, | 189 | u64 chunk_start, u64 physical, u64 devid, |
186 | u64 **logical, int *naddrs, int *stripe_len); | 190 | u64 **logical, int *naddrs, int *stripe_len); |