aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Schmidt <list.btrfs@jan-o-sch.net>2011-08-04 11:15:33 -0400
committerJan Schmidt <list.btrfs@jan-o-sch.net>2011-09-29 07:38:42 -0400
commita1d3c4786a4b9c71c0767aa656a759968f7554b6 (patch)
tree1dc5596ca57f261d2816111e51a2f33928bbe4a6
parentd7728c960dccf775b92f2c4139f1216275a45c44 (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.c10
-rw-r--r--fs/btrfs/scrub.c20
-rw-r--r--fs/btrfs/volumes.c128
-rw-r--r--fs/btrfs/volumes.h10
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
667uncorrectable: 667uncorrectable:
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
2849static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, 2849static 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;
2873again: 2873again:
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 }
3116out: 3123out:
3117 free_extent_map(em); 3124 free_extent_map(em);
@@ -3120,9 +3127,9 @@ out:
3120 3127
3121int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, 3128int 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
3194static void end_bio_multi_stripe(struct bio *bio, int err) 3201static 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
139struct btrfs_multi_bio { 139struct btrfs_bio;
140typedef void (btrfs_bio_end_io_t) (struct btrfs_bio *bio, int err);
141
142struct 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 {
171int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start, 175int 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
177int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, 181int 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);
181int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, 185int 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);
184int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, 188int 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);