diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-28 18:31:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-28 18:31:05 -0400 |
commit | 212a17ab878305600e607f637d2d8a49d9f7ef25 (patch) | |
tree | 64ad97fcc3d5c49ebd735f5508643c798aeecddf /fs/btrfs/volumes.c | |
parent | baaca1a61497d97cec595fedce03b0a23b983e64 (diff) | |
parent | d9d04879321af570ea7285c6dad92d9c3cd108a1 (diff) |
Merge branch 'for-linus-unmerged' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
* 'for-linus-unmerged' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable: (45 commits)
Btrfs: fix __btrfs_map_block on 32 bit machines
btrfs: fix possible deadlock by clearing __GFP_FS flag
btrfs: check link counter overflow in link(2)
btrfs: don't mess with i_nlink of unlocked inode in rename()
Btrfs: check return value of btrfs_alloc_path()
Btrfs: fix OOPS of empty filesystem after balance
Btrfs: fix memory leak of empty filesystem after balance
Btrfs: fix return value of setflags ioctl
Btrfs: fix uncheck memory allocations
btrfs: make inode ref log recovery faster
Btrfs: add btrfs_trim_fs() to handle FITRIM
Btrfs: adjust btrfs_discard_extent() return errors and trimmed bytes
Btrfs: make btrfs_map_block() return entire free extent for each device of RAID0/1/10/DUP
Btrfs: make update_reserved_bytes() public
btrfs: return EXDEV when linking from different subvolumes
Btrfs: Per file/directory controls for COW and compression
Btrfs: add datacow flag in inode flag
btrfs: use GFP_NOFS instead of GFP_KERNEL
Btrfs: check return value of read_tree_block()
btrfs: properly access unaligned checksum buffer
...
Fix up trivial conflicts in fs/btrfs/volumes.c due to plug removal in
the block layer.
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 164 |
1 files changed, 138 insertions, 26 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 9d554e8e6583..309a57b9fc85 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -33,17 +33,6 @@ | |||
33 | #include "volumes.h" | 33 | #include "volumes.h" |
34 | #include "async-thread.h" | 34 | #include "async-thread.h" |
35 | 35 | ||
36 | struct map_lookup { | ||
37 | u64 type; | ||
38 | int io_align; | ||
39 | int io_width; | ||
40 | int stripe_len; | ||
41 | int sector_size; | ||
42 | int num_stripes; | ||
43 | int sub_stripes; | ||
44 | struct btrfs_bio_stripe stripes[]; | ||
45 | }; | ||
46 | |||
47 | static int init_first_rw_device(struct btrfs_trans_handle *trans, | 36 | static int init_first_rw_device(struct btrfs_trans_handle *trans, |
48 | struct btrfs_root *root, | 37 | struct btrfs_root *root, |
49 | struct btrfs_device *device); | 38 | struct btrfs_device *device); |
@@ -1879,6 +1868,8 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, | |||
1879 | 1868 | ||
1880 | BUG_ON(ret); | 1869 | BUG_ON(ret); |
1881 | 1870 | ||
1871 | trace_btrfs_chunk_free(root, map, chunk_offset, em->len); | ||
1872 | |||
1882 | if (map->type & BTRFS_BLOCK_GROUP_SYSTEM) { | 1873 | if (map->type & BTRFS_BLOCK_GROUP_SYSTEM) { |
1883 | ret = btrfs_del_sys_chunk(root, chunk_objectid, chunk_offset); | 1874 | ret = btrfs_del_sys_chunk(root, chunk_objectid, chunk_offset); |
1884 | BUG_ON(ret); | 1875 | BUG_ON(ret); |
@@ -2606,6 +2597,8 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
2606 | *num_bytes = chunk_bytes_by_type(type, calc_size, | 2597 | *num_bytes = chunk_bytes_by_type(type, calc_size, |
2607 | map->num_stripes, sub_stripes); | 2598 | map->num_stripes, sub_stripes); |
2608 | 2599 | ||
2600 | trace_btrfs_chunk_alloc(info->chunk_root, map, start, *num_bytes); | ||
2601 | |||
2609 | em = alloc_extent_map(GFP_NOFS); | 2602 | em = alloc_extent_map(GFP_NOFS); |
2610 | if (!em) { | 2603 | if (!em) { |
2611 | ret = -ENOMEM; | 2604 | ret = -ENOMEM; |
@@ -2714,6 +2707,7 @@ static int __finish_chunk_alloc(struct btrfs_trans_handle *trans, | |||
2714 | item_size); | 2707 | item_size); |
2715 | BUG_ON(ret); | 2708 | BUG_ON(ret); |
2716 | } | 2709 | } |
2710 | |||
2717 | kfree(chunk); | 2711 | kfree(chunk); |
2718 | return 0; | 2712 | return 0; |
2719 | } | 2713 | } |
@@ -2918,7 +2912,10 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
2918 | struct extent_map_tree *em_tree = &map_tree->map_tree; | 2912 | struct extent_map_tree *em_tree = &map_tree->map_tree; |
2919 | u64 offset; | 2913 | u64 offset; |
2920 | u64 stripe_offset; | 2914 | u64 stripe_offset; |
2915 | u64 stripe_end_offset; | ||
2921 | u64 stripe_nr; | 2916 | u64 stripe_nr; |
2917 | u64 stripe_nr_orig; | ||
2918 | u64 stripe_nr_end; | ||
2922 | int stripes_allocated = 8; | 2919 | int stripes_allocated = 8; |
2923 | int stripes_required = 1; | 2920 | int stripes_required = 1; |
2924 | int stripe_index; | 2921 | int stripe_index; |
@@ -2927,7 +2924,7 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
2927 | int max_errors = 0; | 2924 | int max_errors = 0; |
2928 | struct btrfs_multi_bio *multi = NULL; | 2925 | struct btrfs_multi_bio *multi = NULL; |
2929 | 2926 | ||
2930 | if (multi_ret && !(rw & REQ_WRITE)) | 2927 | if (multi_ret && !(rw & (REQ_WRITE | REQ_DISCARD))) |
2931 | stripes_allocated = 1; | 2928 | stripes_allocated = 1; |
2932 | again: | 2929 | again: |
2933 | if (multi_ret) { | 2930 | if (multi_ret) { |
@@ -2968,7 +2965,15 @@ again: | |||
2968 | max_errors = 1; | 2965 | max_errors = 1; |
2969 | } | 2966 | } |
2970 | } | 2967 | } |
2971 | if (multi_ret && (rw & REQ_WRITE) && | 2968 | if (rw & REQ_DISCARD) { |
2969 | if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | | ||
2970 | BTRFS_BLOCK_GROUP_RAID1 | | ||
2971 | BTRFS_BLOCK_GROUP_DUP | | ||
2972 | BTRFS_BLOCK_GROUP_RAID10)) { | ||
2973 | stripes_required = map->num_stripes; | ||
2974 | } | ||
2975 | } | ||
2976 | if (multi_ret && (rw & (REQ_WRITE | REQ_DISCARD)) && | ||
2972 | stripes_allocated < stripes_required) { | 2977 | stripes_allocated < stripes_required) { |
2973 | stripes_allocated = map->num_stripes; | 2978 | stripes_allocated = map->num_stripes; |
2974 | free_extent_map(em); | 2979 | free_extent_map(em); |
@@ -2988,12 +2993,15 @@ again: | |||
2988 | /* stripe_offset is the offset of this block in its stripe*/ | 2993 | /* stripe_offset is the offset of this block in its stripe*/ |
2989 | stripe_offset = offset - stripe_offset; | 2994 | stripe_offset = offset - stripe_offset; |
2990 | 2995 | ||
2991 | if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 | | 2996 | if (rw & REQ_DISCARD) |
2992 | BTRFS_BLOCK_GROUP_RAID10 | | 2997 | *length = min_t(u64, em->len - offset, *length); |
2993 | BTRFS_BLOCK_GROUP_DUP)) { | 2998 | else if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | |
2999 | BTRFS_BLOCK_GROUP_RAID1 | | ||
3000 | BTRFS_BLOCK_GROUP_RAID10 | | ||
3001 | BTRFS_BLOCK_GROUP_DUP)) { | ||
2994 | /* we limit the length of each bio to what fits in a stripe */ | 3002 | /* we limit the length of each bio to what fits in a stripe */ |
2995 | *length = min_t(u64, em->len - offset, | 3003 | *length = min_t(u64, em->len - offset, |
2996 | map->stripe_len - stripe_offset); | 3004 | map->stripe_len - stripe_offset); |
2997 | } else { | 3005 | } else { |
2998 | *length = em->len - offset; | 3006 | *length = em->len - offset; |
2999 | } | 3007 | } |
@@ -3003,8 +3011,19 @@ again: | |||
3003 | 3011 | ||
3004 | num_stripes = 1; | 3012 | num_stripes = 1; |
3005 | stripe_index = 0; | 3013 | stripe_index = 0; |
3006 | if (map->type & BTRFS_BLOCK_GROUP_RAID1) { | 3014 | stripe_nr_orig = stripe_nr; |
3007 | if (rw & REQ_WRITE) | 3015 | stripe_nr_end = (offset + *length + map->stripe_len - 1) & |
3016 | (~(map->stripe_len - 1)); | ||
3017 | do_div(stripe_nr_end, map->stripe_len); | ||
3018 | stripe_end_offset = stripe_nr_end * map->stripe_len - | ||
3019 | (offset + *length); | ||
3020 | if (map->type & BTRFS_BLOCK_GROUP_RAID0) { | ||
3021 | if (rw & REQ_DISCARD) | ||
3022 | num_stripes = min_t(u64, map->num_stripes, | ||
3023 | stripe_nr_end - stripe_nr_orig); | ||
3024 | stripe_index = do_div(stripe_nr, map->num_stripes); | ||
3025 | } else if (map->type & BTRFS_BLOCK_GROUP_RAID1) { | ||
3026 | if (rw & (REQ_WRITE | REQ_DISCARD)) | ||
3008 | num_stripes = map->num_stripes; | 3027 | num_stripes = map->num_stripes; |
3009 | else if (mirror_num) | 3028 | else if (mirror_num) |
3010 | stripe_index = mirror_num - 1; | 3029 | stripe_index = mirror_num - 1; |
@@ -3015,7 +3034,7 @@ again: | |||
3015 | } | 3034 | } |
3016 | 3035 | ||
3017 | } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { | 3036 | } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { |
3018 | if (rw & REQ_WRITE) | 3037 | if (rw & (REQ_WRITE | REQ_DISCARD)) |
3019 | num_stripes = map->num_stripes; | 3038 | num_stripes = map->num_stripes; |
3020 | else if (mirror_num) | 3039 | else if (mirror_num) |
3021 | stripe_index = mirror_num - 1; | 3040 | stripe_index = mirror_num - 1; |
@@ -3028,6 +3047,10 @@ again: | |||
3028 | 3047 | ||
3029 | if (rw & REQ_WRITE) | 3048 | if (rw & REQ_WRITE) |
3030 | num_stripes = map->sub_stripes; | 3049 | num_stripes = map->sub_stripes; |
3050 | else if (rw & REQ_DISCARD) | ||
3051 | num_stripes = min_t(u64, map->sub_stripes * | ||
3052 | (stripe_nr_end - stripe_nr_orig), | ||
3053 | map->num_stripes); | ||
3031 | else if (mirror_num) | 3054 | else if (mirror_num) |
3032 | stripe_index += mirror_num - 1; | 3055 | stripe_index += mirror_num - 1; |
3033 | else { | 3056 | else { |
@@ -3045,12 +3068,101 @@ again: | |||
3045 | } | 3068 | } |
3046 | BUG_ON(stripe_index >= map->num_stripes); | 3069 | BUG_ON(stripe_index >= map->num_stripes); |
3047 | 3070 | ||
3048 | for (i = 0; i < num_stripes; i++) { | 3071 | if (rw & REQ_DISCARD) { |
3049 | multi->stripes[i].physical = | 3072 | for (i = 0; i < num_stripes; i++) { |
3050 | map->stripes[stripe_index].physical + | 3073 | multi->stripes[i].physical = |
3051 | stripe_offset + stripe_nr * map->stripe_len; | 3074 | map->stripes[stripe_index].physical + |
3052 | multi->stripes[i].dev = map->stripes[stripe_index].dev; | 3075 | stripe_offset + stripe_nr * map->stripe_len; |
3053 | stripe_index++; | 3076 | multi->stripes[i].dev = map->stripes[stripe_index].dev; |
3077 | |||
3078 | if (map->type & BTRFS_BLOCK_GROUP_RAID0) { | ||
3079 | u64 stripes; | ||
3080 | u32 last_stripe = 0; | ||
3081 | int j; | ||
3082 | |||
3083 | div_u64_rem(stripe_nr_end - 1, | ||
3084 | map->num_stripes, | ||
3085 | &last_stripe); | ||
3086 | |||
3087 | for (j = 0; j < map->num_stripes; j++) { | ||
3088 | u32 test; | ||
3089 | |||
3090 | div_u64_rem(stripe_nr_end - 1 - j, | ||
3091 | map->num_stripes, &test); | ||
3092 | if (test == stripe_index) | ||
3093 | break; | ||
3094 | } | ||
3095 | stripes = stripe_nr_end - 1 - j; | ||
3096 | do_div(stripes, map->num_stripes); | ||
3097 | multi->stripes[i].length = map->stripe_len * | ||
3098 | (stripes - stripe_nr + 1); | ||
3099 | |||
3100 | if (i == 0) { | ||
3101 | multi->stripes[i].length -= | ||
3102 | stripe_offset; | ||
3103 | stripe_offset = 0; | ||
3104 | } | ||
3105 | if (stripe_index == last_stripe) | ||
3106 | multi->stripes[i].length -= | ||
3107 | stripe_end_offset; | ||
3108 | } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { | ||
3109 | u64 stripes; | ||
3110 | int j; | ||
3111 | int factor = map->num_stripes / | ||
3112 | map->sub_stripes; | ||
3113 | u32 last_stripe = 0; | ||
3114 | |||
3115 | div_u64_rem(stripe_nr_end - 1, | ||
3116 | factor, &last_stripe); | ||
3117 | last_stripe *= map->sub_stripes; | ||
3118 | |||
3119 | for (j = 0; j < factor; j++) { | ||
3120 | u32 test; | ||
3121 | |||
3122 | div_u64_rem(stripe_nr_end - 1 - j, | ||
3123 | factor, &test); | ||
3124 | |||
3125 | if (test == | ||
3126 | stripe_index / map->sub_stripes) | ||
3127 | break; | ||
3128 | } | ||
3129 | stripes = stripe_nr_end - 1 - j; | ||
3130 | do_div(stripes, factor); | ||
3131 | multi->stripes[i].length = map->stripe_len * | ||
3132 | (stripes - stripe_nr + 1); | ||
3133 | |||
3134 | if (i < map->sub_stripes) { | ||
3135 | multi->stripes[i].length -= | ||
3136 | stripe_offset; | ||
3137 | if (i == map->sub_stripes - 1) | ||
3138 | stripe_offset = 0; | ||
3139 | } | ||
3140 | if (stripe_index >= last_stripe && | ||
3141 | stripe_index <= (last_stripe + | ||
3142 | map->sub_stripes - 1)) { | ||
3143 | multi->stripes[i].length -= | ||
3144 | stripe_end_offset; | ||
3145 | } | ||
3146 | } else | ||
3147 | multi->stripes[i].length = *length; | ||
3148 | |||
3149 | stripe_index++; | ||
3150 | if (stripe_index == map->num_stripes) { | ||
3151 | /* This could only happen for RAID0/10 */ | ||
3152 | stripe_index = 0; | ||
3153 | stripe_nr++; | ||
3154 | } | ||
3155 | } | ||
3156 | } else { | ||
3157 | for (i = 0; i < num_stripes; i++) { | ||
3158 | multi->stripes[i].physical = | ||
3159 | map->stripes[stripe_index].physical + | ||
3160 | stripe_offset + | ||
3161 | stripe_nr * map->stripe_len; | ||
3162 | multi->stripes[i].dev = | ||
3163 | map->stripes[stripe_index].dev; | ||
3164 | stripe_index++; | ||
3165 | } | ||
3054 | } | 3166 | } |
3055 | if (multi_ret) { | 3167 | if (multi_ret) { |
3056 | *multi_ret = multi; | 3168 | *multi_ret = multi; |