aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLi Dongyang <lidongyang@novell.com>2011-03-24 06:24:26 -0400
committerroot <Chris Mason chris.mason@oracle.com>2011-03-28 05:37:45 -0400
commitfce3bb9a1bd492793170e117c60d5718b7896af4 (patch)
tree6704e735635531438bdc7dda074ad5e89d89d8eb /fs
parentb4d00d569a49fcef02195635dbf8d15904b1fb63 (diff)
Btrfs: make btrfs_map_block() return entire free extent for each device of RAID0/1/10/DUP
btrfs_map_block() will only return a single stripe length, but we want the full extent be mapped to each disk when we are trimming the extent, so we add length to btrfs_bio_stripe and fill it if we are mapping for REQ_DISCARD. Signed-off-by: Li Dongyang <lidongyang@novell.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/volumes.c150
-rw-r--r--fs/btrfs/volumes.h1
2 files changed, 129 insertions, 22 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 8ba3c9ebff93..c440c89a470a 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -2956,7 +2956,10 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
2956 struct extent_map_tree *em_tree = &map_tree->map_tree; 2956 struct extent_map_tree *em_tree = &map_tree->map_tree;
2957 u64 offset; 2957 u64 offset;
2958 u64 stripe_offset; 2958 u64 stripe_offset;
2959 u64 stripe_end_offset;
2959 u64 stripe_nr; 2960 u64 stripe_nr;
2961 u64 stripe_nr_orig;
2962 u64 stripe_nr_end;
2960 int stripes_allocated = 8; 2963 int stripes_allocated = 8;
2961 int stripes_required = 1; 2964 int stripes_required = 1;
2962 int stripe_index; 2965 int stripe_index;
@@ -2965,7 +2968,7 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
2965 int max_errors = 0; 2968 int max_errors = 0;
2966 struct btrfs_multi_bio *multi = NULL; 2969 struct btrfs_multi_bio *multi = NULL;
2967 2970
2968 if (multi_ret && !(rw & REQ_WRITE)) 2971 if (multi_ret && !(rw & (REQ_WRITE | REQ_DISCARD)))
2969 stripes_allocated = 1; 2972 stripes_allocated = 1;
2970again: 2973again:
2971 if (multi_ret) { 2974 if (multi_ret) {
@@ -3011,7 +3014,15 @@ again:
3011 max_errors = 1; 3014 max_errors = 1;
3012 } 3015 }
3013 } 3016 }
3014 if (multi_ret && (rw & REQ_WRITE) && 3017 if (rw & REQ_DISCARD) {
3018 if (map->type & (BTRFS_BLOCK_GROUP_RAID0 |
3019 BTRFS_BLOCK_GROUP_RAID1 |
3020 BTRFS_BLOCK_GROUP_DUP |
3021 BTRFS_BLOCK_GROUP_RAID10)) {
3022 stripes_required = map->num_stripes;
3023 }
3024 }
3025 if (multi_ret && (rw & (REQ_WRITE | REQ_DISCARD)) &&
3015 stripes_allocated < stripes_required) { 3026 stripes_allocated < stripes_required) {
3016 stripes_allocated = map->num_stripes; 3027 stripes_allocated = map->num_stripes;
3017 free_extent_map(em); 3028 free_extent_map(em);
@@ -3031,12 +3042,15 @@ again:
3031 /* stripe_offset is the offset of this block in its stripe*/ 3042 /* stripe_offset is the offset of this block in its stripe*/
3032 stripe_offset = offset - stripe_offset; 3043 stripe_offset = offset - stripe_offset;
3033 3044
3034 if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 | 3045 if (rw & REQ_DISCARD)
3035 BTRFS_BLOCK_GROUP_RAID10 | 3046 *length = min_t(u64, em->len - offset, *length);
3036 BTRFS_BLOCK_GROUP_DUP)) { 3047 else if (map->type & (BTRFS_BLOCK_GROUP_RAID0 |
3048 BTRFS_BLOCK_GROUP_RAID1 |
3049 BTRFS_BLOCK_GROUP_RAID10 |
3050 BTRFS_BLOCK_GROUP_DUP)) {
3037 /* we limit the length of each bio to what fits in a stripe */ 3051 /* we limit the length of each bio to what fits in a stripe */
3038 *length = min_t(u64, em->len - offset, 3052 *length = min_t(u64, em->len - offset,
3039 map->stripe_len - stripe_offset); 3053 map->stripe_len - stripe_offset);
3040 } else { 3054 } else {
3041 *length = em->len - offset; 3055 *length = em->len - offset;
3042 } 3056 }
@@ -3046,8 +3060,19 @@ again:
3046 3060
3047 num_stripes = 1; 3061 num_stripes = 1;
3048 stripe_index = 0; 3062 stripe_index = 0;
3049 if (map->type & BTRFS_BLOCK_GROUP_RAID1) { 3063 stripe_nr_orig = stripe_nr;
3050 if (unplug_page || (rw & REQ_WRITE)) 3064 stripe_nr_end = (offset + *length + map->stripe_len - 1) &
3065 (~(map->stripe_len - 1));
3066 do_div(stripe_nr_end, map->stripe_len);
3067 stripe_end_offset = stripe_nr_end * map->stripe_len -
3068 (offset + *length);
3069 if (map->type & BTRFS_BLOCK_GROUP_RAID0) {
3070 if (rw & REQ_DISCARD)
3071 num_stripes = min_t(u64, map->num_stripes,
3072 stripe_nr_end - stripe_nr_orig);
3073 stripe_index = do_div(stripe_nr, map->num_stripes);
3074 } else if (map->type & BTRFS_BLOCK_GROUP_RAID1) {
3075 if (unplug_page || (rw & (REQ_WRITE | REQ_DISCARD)))
3051 num_stripes = map->num_stripes; 3076 num_stripes = map->num_stripes;
3052 else if (mirror_num) 3077 else if (mirror_num)
3053 stripe_index = mirror_num - 1; 3078 stripe_index = mirror_num - 1;
@@ -3058,7 +3083,7 @@ again:
3058 } 3083 }
3059 3084
3060 } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { 3085 } else if (map->type & BTRFS_BLOCK_GROUP_DUP) {
3061 if (rw & REQ_WRITE) 3086 if (rw & (REQ_WRITE | REQ_DISCARD))
3062 num_stripes = map->num_stripes; 3087 num_stripes = map->num_stripes;
3063 else if (mirror_num) 3088 else if (mirror_num)
3064 stripe_index = mirror_num - 1; 3089 stripe_index = mirror_num - 1;
@@ -3071,6 +3096,10 @@ again:
3071 3096
3072 if (unplug_page || (rw & REQ_WRITE)) 3097 if (unplug_page || (rw & REQ_WRITE))
3073 num_stripes = map->sub_stripes; 3098 num_stripes = map->sub_stripes;
3099 else if (rw & REQ_DISCARD)
3100 num_stripes = min_t(u64, map->sub_stripes *
3101 (stripe_nr_end - stripe_nr_orig),
3102 map->num_stripes);
3074 else if (mirror_num) 3103 else if (mirror_num)
3075 stripe_index += mirror_num - 1; 3104 stripe_index += mirror_num - 1;
3076 else { 3105 else {
@@ -3088,24 +3117,101 @@ again:
3088 } 3117 }
3089 BUG_ON(stripe_index >= map->num_stripes); 3118 BUG_ON(stripe_index >= map->num_stripes);
3090 3119
3091 for (i = 0; i < num_stripes; i++) { 3120 if (rw & REQ_DISCARD) {
3092 if (unplug_page) { 3121 for (i = 0; i < num_stripes; i++) {
3093 struct btrfs_device *device;
3094 struct backing_dev_info *bdi;
3095
3096 device = map->stripes[stripe_index].dev;
3097 if (device->bdev) {
3098 bdi = blk_get_backing_dev_info(device->bdev);
3099 if (bdi->unplug_io_fn)
3100 bdi->unplug_io_fn(bdi, unplug_page);
3101 }
3102 } else {
3103 multi->stripes[i].physical = 3122 multi->stripes[i].physical =
3104 map->stripes[stripe_index].physical + 3123 map->stripes[stripe_index].physical +
3105 stripe_offset + stripe_nr * map->stripe_len; 3124 stripe_offset + stripe_nr * map->stripe_len;
3106 multi->stripes[i].dev = map->stripes[stripe_index].dev; 3125 multi->stripes[i].dev = map->stripes[stripe_index].dev;
3126
3127 if (map->type & BTRFS_BLOCK_GROUP_RAID0) {
3128 u64 stripes;
3129 int last_stripe = (stripe_nr_end - 1) %
3130 map->num_stripes;
3131 int j;
3132
3133 for (j = 0; j < map->num_stripes; j++) {
3134 if ((stripe_nr_end - 1 - j) %
3135 map->num_stripes == stripe_index)
3136 break;
3137 }
3138 stripes = stripe_nr_end - 1 - j;
3139 do_div(stripes, map->num_stripes);
3140 multi->stripes[i].length = map->stripe_len *
3141 (stripes - stripe_nr + 1);
3142
3143 if (i == 0) {
3144 multi->stripes[i].length -=
3145 stripe_offset;
3146 stripe_offset = 0;
3147 }
3148 if (stripe_index == last_stripe)
3149 multi->stripes[i].length -=
3150 stripe_end_offset;
3151 } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
3152 u64 stripes;
3153 int j;
3154 int factor = map->num_stripes /
3155 map->sub_stripes;
3156 int last_stripe = (stripe_nr_end - 1) % factor;
3157 last_stripe *= map->sub_stripes;
3158
3159 for (j = 0; j < factor; j++) {
3160 if ((stripe_nr_end - 1 - j) % factor ==
3161 stripe_index / map->sub_stripes)
3162 break;
3163 }
3164 stripes = stripe_nr_end - 1 - j;
3165 do_div(stripes, factor);
3166 multi->stripes[i].length = map->stripe_len *
3167 (stripes - stripe_nr + 1);
3168
3169 if (i < map->sub_stripes) {
3170 multi->stripes[i].length -=
3171 stripe_offset;
3172 if (i == map->sub_stripes - 1)
3173 stripe_offset = 0;
3174 }
3175 if (stripe_index >= last_stripe &&
3176 stripe_index <= (last_stripe +
3177 map->sub_stripes - 1)) {
3178 multi->stripes[i].length -=
3179 stripe_end_offset;
3180 }
3181 } else
3182 multi->stripes[i].length = *length;
3183
3184 stripe_index++;
3185 if (stripe_index == map->num_stripes) {
3186 /* This could only happen for RAID0/10 */
3187 stripe_index = 0;
3188 stripe_nr++;
3189 }
3190 }
3191 } else {
3192 for (i = 0; i < num_stripes; i++) {
3193 if (unplug_page) {
3194 struct btrfs_device *device;
3195 struct backing_dev_info *bdi;
3196
3197 device = map->stripes[stripe_index].dev;
3198 if (device->bdev) {
3199 bdi = blk_get_backing_dev_info(device->
3200 bdev);
3201 if (bdi->unplug_io_fn)
3202 bdi->unplug_io_fn(bdi,
3203 unplug_page);
3204 }
3205 } else {
3206 multi->stripes[i].physical =
3207 map->stripes[stripe_index].physical +
3208 stripe_offset +
3209 stripe_nr * map->stripe_len;
3210 multi->stripes[i].dev =
3211 map->stripes[stripe_index].dev;
3212 }
3213 stripe_index++;
3107 } 3214 }
3108 stripe_index++;
3109 } 3215 }
3110 if (multi_ret) { 3216 if (multi_ret) {
3111 *multi_ret = multi; 3217 *multi_ret = multi;
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 7b38d0668b51..cc2eadaf7a27 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -126,6 +126,7 @@ struct btrfs_fs_devices {
126struct btrfs_bio_stripe { 126struct btrfs_bio_stripe {
127 struct btrfs_device *dev; 127 struct btrfs_device *dev;
128 u64 physical; 128 u64 physical;
129 u64 length; /* only used for discard mappings */
129}; 130};
130 131
131struct btrfs_multi_bio { 132struct btrfs_multi_bio {