aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorLi Zefan <lizf@cn.fujitsu.com>2011-12-01 01:06:42 -0500
committerLi Zefan <lizf@cn.fujitsu.com>2012-01-10 21:26:46 -0500
commitec9ef7a13be4dcce964c8503e8999087945e5b9e (patch)
treeafd97976c76c45fca7b659f8d81cbcd4995d2a7e /fs/btrfs/volumes.c
parentde11cc12df17337979e0929d2831887432f236ca (diff)
Btrfs: simplfy calculation of stripe length for discard operation
For btrfs raid, while discarding a range of space, we'll need to know the start offset and length to discard for each device, and it's done in btrfs_map_block(). However the calculation is a bit complex for raid0 and raid10, so I reimplement it based on a fact that: dev1 dev2 dev3 (raid0) ----------------------------------- s0 s3 s6 s1 s4 s7 s2 s5 Each device has (total_stripes / nr_dev) stripes, or plus one. Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c95
1 files changed, 31 insertions, 64 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 540fdd25fb5e..563ef650850e 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -3024,80 +3024,47 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
3024 atomic_set(&bbio->error, 0); 3024 atomic_set(&bbio->error, 0);
3025 3025
3026 if (rw & REQ_DISCARD) { 3026 if (rw & REQ_DISCARD) {
3027 int factor = 0;
3028 int sub_stripes = 0;
3029 u64 stripes_per_dev = 0;
3030 u32 remaining_stripes = 0;
3031
3032 if (map->type &
3033 (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID10)) {
3034 if (map->type & BTRFS_BLOCK_GROUP_RAID0)
3035 sub_stripes = 1;
3036 else
3037 sub_stripes = map->sub_stripes;
3038
3039 factor = map->num_stripes / sub_stripes;
3040 stripes_per_dev = div_u64_rem(stripe_nr_end -
3041 stripe_nr_orig,
3042 factor,
3043 &remaining_stripes);
3044 }
3045
3027 for (i = 0; i < num_stripes; i++) { 3046 for (i = 0; i < num_stripes; i++) {
3028 bbio->stripes[i].physical = 3047 bbio->stripes[i].physical =
3029 map->stripes[stripe_index].physical + 3048 map->stripes[stripe_index].physical +
3030 stripe_offset + stripe_nr * map->stripe_len; 3049 stripe_offset + stripe_nr * map->stripe_len;
3031 bbio->stripes[i].dev = map->stripes[stripe_index].dev; 3050 bbio->stripes[i].dev = map->stripes[stripe_index].dev;
3032 3051
3033 if (map->type & BTRFS_BLOCK_GROUP_RAID0) { 3052 if (map->type & (BTRFS_BLOCK_GROUP_RAID0 |
3034 u64 stripes; 3053 BTRFS_BLOCK_GROUP_RAID10)) {
3035 u32 last_stripe = 0; 3054 bbio->stripes[i].length = stripes_per_dev *
3036 int j; 3055 map->stripe_len;
3037 3056 if (i / sub_stripes < remaining_stripes)
3038 div_u64_rem(stripe_nr_end - 1, 3057 bbio->stripes[i].length +=
3039 map->num_stripes, 3058 map->stripe_len;
3040 &last_stripe); 3059 if (i < sub_stripes)
3041
3042 for (j = 0; j < map->num_stripes; j++) {
3043 u32 test;
3044
3045 div_u64_rem(stripe_nr_end - 1 - j,
3046 map->num_stripes, &test);
3047 if (test == stripe_index)
3048 break;
3049 }
3050 stripes = stripe_nr_end - 1 - j;
3051 do_div(stripes, map->num_stripes);
3052 bbio->stripes[i].length = map->stripe_len *
3053 (stripes - stripe_nr + 1);
3054
3055 if (i == 0) {
3056 bbio->stripes[i].length -= 3060 bbio->stripes[i].length -=
3057 stripe_offset; 3061 stripe_offset;
3058 stripe_offset = 0; 3062 if ((i / sub_stripes + 1) %
3059 } 3063 sub_stripes == remaining_stripes)
3060 if (stripe_index == last_stripe)
3061 bbio->stripes[i].length -=
3062 stripe_end_offset;
3063 } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
3064 u64 stripes;
3065 int j;
3066 int factor = map->num_stripes /
3067 map->sub_stripes;
3068 u32 last_stripe = 0;
3069
3070 div_u64_rem(stripe_nr_end - 1,
3071 factor, &last_stripe);
3072 last_stripe *= map->sub_stripes;
3073
3074 for (j = 0; j < factor; j++) {
3075 u32 test;
3076
3077 div_u64_rem(stripe_nr_end - 1 - j,
3078 factor, &test);
3079
3080 if (test ==
3081 stripe_index / map->sub_stripes)
3082 break;
3083 }
3084 stripes = stripe_nr_end - 1 - j;
3085 do_div(stripes, factor);
3086 bbio->stripes[i].length = map->stripe_len *
3087 (stripes - stripe_nr + 1);
3088
3089 if (i < map->sub_stripes) {
3090 bbio->stripes[i].length -=
3091 stripe_offset;
3092 if (i == map->sub_stripes - 1)
3093 stripe_offset = 0;
3094 }
3095 if (stripe_index >= last_stripe &&
3096 stripe_index <= (last_stripe +
3097 map->sub_stripes - 1)) {
3098 bbio->stripes[i].length -= 3064 bbio->stripes[i].length -=
3099 stripe_end_offset; 3065 stripe_end_offset;
3100 } 3066 if (i == sub_stripes - 1)
3067 stripe_offset = 0;
3101 } else 3068 } else
3102 bbio->stripes[i].length = *length; 3069 bbio->stripes[i].length = *length;
3103 3070