Commit fce3bb9a1bd492793170e117c60d5718b7896af4
Committed by
root
1 parent
b4d00d569a
Exists in
master
and in
39 other branches
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>
Showing 2 changed files with 129 additions and 22 deletions Side-by-side Diff
fs/btrfs/volumes.c
... | ... | @@ -2956,7 +2956,10 @@ |
2956 | 2956 | struct extent_map_tree *em_tree = &map_tree->map_tree; |
2957 | 2957 | u64 offset; |
2958 | 2958 | u64 stripe_offset; |
2959 | + u64 stripe_end_offset; | |
2959 | 2960 | u64 stripe_nr; |
2961 | + u64 stripe_nr_orig; | |
2962 | + u64 stripe_nr_end; | |
2960 | 2963 | int stripes_allocated = 8; |
2961 | 2964 | int stripes_required = 1; |
2962 | 2965 | int stripe_index; |
... | ... | @@ -2965,7 +2968,7 @@ |
2965 | 2968 | int max_errors = 0; |
2966 | 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 | 2972 | stripes_allocated = 1; |
2970 | 2973 | again: |
2971 | 2974 | if (multi_ret) { |
... | ... | @@ -3011,7 +3014,15 @@ |
3011 | 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 | 3026 | stripes_allocated < stripes_required) { |
3016 | 3027 | stripes_allocated = map->num_stripes; |
3017 | 3028 | free_extent_map(em); |
3018 | 3029 | |
... | ... | @@ -3031,12 +3042,15 @@ |
3031 | 3042 | /* stripe_offset is the offset of this block in its stripe*/ |
3032 | 3043 | stripe_offset = offset - stripe_offset; |
3033 | 3044 | |
3034 | - if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 | | |
3035 | - BTRFS_BLOCK_GROUP_RAID10 | | |
3036 | - BTRFS_BLOCK_GROUP_DUP)) { | |
3045 | + if (rw & REQ_DISCARD) | |
3046 | + *length = min_t(u64, em->len - offset, *length); | |
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 | 3051 | /* we limit the length of each bio to what fits in a stripe */ |
3038 | 3052 | *length = min_t(u64, em->len - offset, |
3039 | - map->stripe_len - stripe_offset); | |
3053 | + map->stripe_len - stripe_offset); | |
3040 | 3054 | } else { |
3041 | 3055 | *length = em->len - offset; |
3042 | 3056 | } |
... | ... | @@ -3046,8 +3060,19 @@ |
3046 | 3060 | |
3047 | 3061 | num_stripes = 1; |
3048 | 3062 | stripe_index = 0; |
3049 | - if (map->type & BTRFS_BLOCK_GROUP_RAID1) { | |
3050 | - if (unplug_page || (rw & REQ_WRITE)) | |
3063 | + stripe_nr_orig = stripe_nr; | |
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 | 3076 | num_stripes = map->num_stripes; |
3052 | 3077 | else if (mirror_num) |
3053 | 3078 | stripe_index = mirror_num - 1; |
... | ... | @@ -3058,7 +3083,7 @@ |
3058 | 3083 | } |
3059 | 3084 | |
3060 | 3085 | } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { |
3061 | - if (rw & REQ_WRITE) | |
3086 | + if (rw & (REQ_WRITE | REQ_DISCARD)) | |
3062 | 3087 | num_stripes = map->num_stripes; |
3063 | 3088 | else if (mirror_num) |
3064 | 3089 | stripe_index = mirror_num - 1; |
... | ... | @@ -3071,6 +3096,10 @@ |
3071 | 3096 | |
3072 | 3097 | if (unplug_page || (rw & REQ_WRITE)) |
3073 | 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 | 3103 | else if (mirror_num) |
3075 | 3104 | stripe_index += mirror_num - 1; |
3076 | 3105 | else { |
3077 | 3106 | |
3078 | 3107 | |
... | ... | @@ -3088,24 +3117,101 @@ |
3088 | 3117 | } |
3089 | 3118 | BUG_ON(stripe_index >= map->num_stripes); |
3090 | 3119 | |
3091 | - for (i = 0; i < num_stripes; i++) { | |
3092 | - if (unplug_page) { | |
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 { | |
3120 | + if (rw & REQ_DISCARD) { | |
3121 | + for (i = 0; i < num_stripes; i++) { | |
3103 | 3122 | multi->stripes[i].physical = |
3104 | 3123 | map->stripes[stripe_index].physical + |
3105 | 3124 | stripe_offset + stripe_nr * map->stripe_len; |
3106 | 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 | + } | |
3107 | 3190 | } |
3108 | - stripe_index++; | |
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++; | |
3214 | + } | |
3109 | 3215 | } |
3110 | 3216 | if (multi_ret) { |
3111 | 3217 | *multi_ret = multi; |