diff options
author | Li Zefan <lizf@cn.fujitsu.com> | 2011-12-01 01:06:42 -0500 |
---|---|---|
committer | Li Zefan <lizf@cn.fujitsu.com> | 2012-01-10 21:26:46 -0500 |
commit | ec9ef7a13be4dcce964c8503e8999087945e5b9e (patch) | |
tree | afd97976c76c45fca7b659f8d81cbcd4995d2a7e /fs/btrfs/volumes.c | |
parent | de11cc12df17337979e0929d2831887432f236ca (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.c | 95 |
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 | ||