aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-03-28 18:31:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-28 18:31:05 -0400
commit212a17ab878305600e607f637d2d8a49d9f7ef25 (patch)
tree64ad97fcc3d5c49ebd735f5508643c798aeecddf /fs/btrfs/volumes.c
parentbaaca1a61497d97cec595fedce03b0a23b983e64 (diff)
parentd9d04879321af570ea7285c6dad92d9c3cd108a1 (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.c164
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
36struct 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
47static int init_first_rw_device(struct btrfs_trans_handle *trans, 36static 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;
2932again: 2929again:
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;