aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2012-03-28 20:32:46 -0400
committerChris Mason <chris.mason@oracle.com>2012-03-28 20:32:46 -0400
commit1c691b330a19a1344df89bcb0f4cacd99e8b289a (patch)
treeb3143a9875a773d33b9b8f60e98c7e5fae003b6a /fs/btrfs/extent-tree.c
parent1d4284bd6e8d7dd1d5521a6747bdb6dc1caf0225 (diff)
parent213e64da90d14537cd63f7090d6c4d1fcc75d9f8 (diff)
Merge branch 'for-chris' of git://github.com/idryomov/btrfs-unstable into for-linus
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c163
1 files changed, 87 insertions, 76 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 8b304e3537c4..8fe517bd8521 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3138,11 +3138,8 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
3138 3138
3139static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) 3139static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
3140{ 3140{
3141 u64 extra_flags = flags & BTRFS_BLOCK_GROUP_PROFILE_MASK; 3141 u64 extra_flags = chunk_to_extended(flags) &
3142 3142 BTRFS_EXTENDED_PROFILE_MASK;
3143 /* chunk -> extended profile */
3144 if (extra_flags == 0)
3145 extra_flags = BTRFS_AVAIL_ALLOC_BIT_SINGLE;
3146 3143
3147 if (flags & BTRFS_BLOCK_GROUP_DATA) 3144 if (flags & BTRFS_BLOCK_GROUP_DATA)
3148 fs_info->avail_data_alloc_bits |= extra_flags; 3145 fs_info->avail_data_alloc_bits |= extra_flags;
@@ -3153,6 +3150,35 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
3153} 3150}
3154 3151
3155/* 3152/*
3153 * returns target flags in extended format or 0 if restripe for this
3154 * chunk_type is not in progress
3155 */
3156static u64 get_restripe_target(struct btrfs_fs_info *fs_info, u64 flags)
3157{
3158 struct btrfs_balance_control *bctl = fs_info->balance_ctl;
3159 u64 target = 0;
3160
3161 BUG_ON(!mutex_is_locked(&fs_info->volume_mutex) &&
3162 !spin_is_locked(&fs_info->balance_lock));
3163
3164 if (!bctl)
3165 return 0;
3166
3167 if (flags & BTRFS_BLOCK_GROUP_DATA &&
3168 bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) {
3169 target = BTRFS_BLOCK_GROUP_DATA | bctl->data.target;
3170 } else if (flags & BTRFS_BLOCK_GROUP_SYSTEM &&
3171 bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
3172 target = BTRFS_BLOCK_GROUP_SYSTEM | bctl->sys.target;
3173 } else if (flags & BTRFS_BLOCK_GROUP_METADATA &&
3174 bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) {
3175 target = BTRFS_BLOCK_GROUP_METADATA | bctl->meta.target;
3176 }
3177
3178 return target;
3179}
3180
3181/*
3156 * @flags: available profiles in extended format (see ctree.h) 3182 * @flags: available profiles in extended format (see ctree.h)
3157 * 3183 *
3158 * Returns reduced profile in chunk format. If profile changing is in 3184 * Returns reduced profile in chunk format. If profile changing is in
@@ -3168,31 +3194,19 @@ u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
3168 */ 3194 */
3169 u64 num_devices = root->fs_info->fs_devices->rw_devices + 3195 u64 num_devices = root->fs_info->fs_devices->rw_devices +
3170 root->fs_info->fs_devices->missing_devices; 3196 root->fs_info->fs_devices->missing_devices;
3197 u64 target;
3171 3198
3172 /* pick restriper's target profile if it's available */ 3199 /*
3200 * see if restripe for this chunk_type is in progress, if so
3201 * try to reduce to the target profile
3202 */
3173 spin_lock(&root->fs_info->balance_lock); 3203 spin_lock(&root->fs_info->balance_lock);
3174 if (root->fs_info->balance_ctl) { 3204 target = get_restripe_target(root->fs_info, flags);
3175 struct btrfs_balance_control *bctl = root->fs_info->balance_ctl; 3205 if (target) {
3176 u64 tgt = 0; 3206 /* pick target profile only if it's already available */
3177 3207 if ((flags & target) & BTRFS_EXTENDED_PROFILE_MASK) {
3178 if ((flags & BTRFS_BLOCK_GROUP_DATA) &&
3179 (bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
3180 (flags & bctl->data.target)) {
3181 tgt = BTRFS_BLOCK_GROUP_DATA | bctl->data.target;
3182 } else if ((flags & BTRFS_BLOCK_GROUP_SYSTEM) &&
3183 (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
3184 (flags & bctl->sys.target)) {
3185 tgt = BTRFS_BLOCK_GROUP_SYSTEM | bctl->sys.target;
3186 } else if ((flags & BTRFS_BLOCK_GROUP_METADATA) &&
3187 (bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
3188 (flags & bctl->meta.target)) {
3189 tgt = BTRFS_BLOCK_GROUP_METADATA | bctl->meta.target;
3190 }
3191
3192 if (tgt) {
3193 spin_unlock(&root->fs_info->balance_lock); 3208 spin_unlock(&root->fs_info->balance_lock);
3194 flags = tgt; 3209 return extended_to_chunk(target);
3195 goto out;
3196 } 3210 }
3197 } 3211 }
3198 spin_unlock(&root->fs_info->balance_lock); 3212 spin_unlock(&root->fs_info->balance_lock);
@@ -3220,10 +3234,7 @@ u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
3220 flags &= ~BTRFS_BLOCK_GROUP_RAID0; 3234 flags &= ~BTRFS_BLOCK_GROUP_RAID0;
3221 } 3235 }
3222 3236
3223out: 3237 return extended_to_chunk(flags);
3224 /* extended -> chunk profile */
3225 flags &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE;
3226 return flags;
3227} 3238}
3228 3239
3229static u64 get_alloc_profile(struct btrfs_root *root, u64 flags) 3240static u64 get_alloc_profile(struct btrfs_root *root, u64 flags)
@@ -3445,8 +3456,6 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
3445 int wait_for_alloc = 0; 3456 int wait_for_alloc = 0;
3446 int ret = 0; 3457 int ret = 0;
3447 3458
3448 BUG_ON(!profile_is_valid(flags, 0));
3449
3450 space_info = __find_space_info(extent_root->fs_info, flags); 3459 space_info = __find_space_info(extent_root->fs_info, flags);
3451 if (!space_info) { 3460 if (!space_info) {
3452 ret = update_space_info(extent_root->fs_info, flags, 3461 ret = update_space_info(extent_root->fs_info, flags,
@@ -5300,22 +5309,29 @@ wait_block_group_cache_done(struct btrfs_block_group_cache *cache)
5300 return 0; 5309 return 0;
5301} 5310}
5302 5311
5303static int get_block_group_index(struct btrfs_block_group_cache *cache) 5312static int __get_block_group_index(u64 flags)
5304{ 5313{
5305 int index; 5314 int index;
5306 if (cache->flags & BTRFS_BLOCK_GROUP_RAID10) 5315
5316 if (flags & BTRFS_BLOCK_GROUP_RAID10)
5307 index = 0; 5317 index = 0;
5308 else if (cache->flags & BTRFS_BLOCK_GROUP_RAID1) 5318 else if (flags & BTRFS_BLOCK_GROUP_RAID1)
5309 index = 1; 5319 index = 1;
5310 else if (cache->flags & BTRFS_BLOCK_GROUP_DUP) 5320 else if (flags & BTRFS_BLOCK_GROUP_DUP)
5311 index = 2; 5321 index = 2;
5312 else if (cache->flags & BTRFS_BLOCK_GROUP_RAID0) 5322 else if (flags & BTRFS_BLOCK_GROUP_RAID0)
5313 index = 3; 5323 index = 3;
5314 else 5324 else
5315 index = 4; 5325 index = 4;
5326
5316 return index; 5327 return index;
5317} 5328}
5318 5329
5330static int get_block_group_index(struct btrfs_block_group_cache *cache)
5331{
5332 return __get_block_group_index(cache->flags);
5333}
5334
5319enum btrfs_loop_type { 5335enum btrfs_loop_type {
5320 LOOP_CACHING_NOWAIT = 0, 5336 LOOP_CACHING_NOWAIT = 0,
5321 LOOP_CACHING_WAIT = 1, 5337 LOOP_CACHING_WAIT = 1,
@@ -7011,31 +7027,15 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
7011static u64 update_block_group_flags(struct btrfs_root *root, u64 flags) 7027static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
7012{ 7028{
7013 u64 num_devices; 7029 u64 num_devices;
7014 u64 stripped = BTRFS_BLOCK_GROUP_RAID0 | 7030 u64 stripped;
7015 BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10;
7016
7017 if (root->fs_info->balance_ctl) {
7018 struct btrfs_balance_control *bctl = root->fs_info->balance_ctl;
7019 u64 tgt = 0;
7020
7021 /* pick restriper's target profile and return */
7022 if (flags & BTRFS_BLOCK_GROUP_DATA &&
7023 bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) {
7024 tgt = BTRFS_BLOCK_GROUP_DATA | bctl->data.target;
7025 } else if (flags & BTRFS_BLOCK_GROUP_SYSTEM &&
7026 bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
7027 tgt = BTRFS_BLOCK_GROUP_SYSTEM | bctl->sys.target;
7028 } else if (flags & BTRFS_BLOCK_GROUP_METADATA &&
7029 bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) {
7030 tgt = BTRFS_BLOCK_GROUP_METADATA | bctl->meta.target;
7031 }
7032 7031
7033 if (tgt) { 7032 /*
7034 /* extended -> chunk profile */ 7033 * if restripe for this chunk_type is on pick target profile and
7035 tgt &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE; 7034 * return, otherwise do the usual balance
7036 return tgt; 7035 */
7037 } 7036 stripped = get_restripe_target(root->fs_info, flags);
7038 } 7037 if (stripped)
7038 return extended_to_chunk(stripped);
7039 7039
7040 /* 7040 /*
7041 * we add in the count of missing devices because we want 7041 * we add in the count of missing devices because we want
@@ -7045,6 +7045,9 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
7045 num_devices = root->fs_info->fs_devices->rw_devices + 7045 num_devices = root->fs_info->fs_devices->rw_devices +
7046 root->fs_info->fs_devices->missing_devices; 7046 root->fs_info->fs_devices->missing_devices;
7047 7047
7048 stripped = BTRFS_BLOCK_GROUP_RAID0 |
7049 BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10;
7050
7048 if (num_devices == 1) { 7051 if (num_devices == 1) {
7049 stripped |= BTRFS_BLOCK_GROUP_DUP; 7052 stripped |= BTRFS_BLOCK_GROUP_DUP;
7050 stripped = flags & ~stripped; 7053 stripped = flags & ~stripped;
@@ -7057,7 +7060,6 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
7057 if (flags & (BTRFS_BLOCK_GROUP_RAID1 | 7060 if (flags & (BTRFS_BLOCK_GROUP_RAID1 |
7058 BTRFS_BLOCK_GROUP_RAID10)) 7061 BTRFS_BLOCK_GROUP_RAID10))
7059 return stripped | BTRFS_BLOCK_GROUP_DUP; 7062 return stripped | BTRFS_BLOCK_GROUP_DUP;
7060 return flags;
7061 } else { 7063 } else {
7062 /* they already had raid on here, just return */ 7064 /* they already had raid on here, just return */
7063 if (flags & stripped) 7065 if (flags & stripped)
@@ -7070,9 +7072,9 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
7070 if (flags & BTRFS_BLOCK_GROUP_DUP) 7072 if (flags & BTRFS_BLOCK_GROUP_DUP)
7071 return stripped | BTRFS_BLOCK_GROUP_RAID1; 7073 return stripped | BTRFS_BLOCK_GROUP_RAID1;
7072 7074
7073 /* turn single device chunks into raid0 */ 7075 /* this is drive concat, leave it alone */
7074 return stripped | BTRFS_BLOCK_GROUP_RAID0;
7075 } 7076 }
7077
7076 return flags; 7078 return flags;
7077} 7079}
7078 7080
@@ -7253,6 +7255,7 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
7253 u64 min_free; 7255 u64 min_free;
7254 u64 dev_min = 1; 7256 u64 dev_min = 1;
7255 u64 dev_nr = 0; 7257 u64 dev_nr = 0;
7258 u64 target;
7256 int index; 7259 int index;
7257 int full = 0; 7260 int full = 0;
7258 int ret = 0; 7261 int ret = 0;
@@ -7293,13 +7296,11 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
7293 /* 7296 /*
7294 * ok we don't have enough space, but maybe we have free space on our 7297 * ok we don't have enough space, but maybe we have free space on our
7295 * devices to allocate new chunks for relocation, so loop through our 7298 * devices to allocate new chunks for relocation, so loop through our
7296 * alloc devices and guess if we have enough space. However, if we 7299 * alloc devices and guess if we have enough space. if this block
7297 * were marked as full, then we know there aren't enough chunks, and we 7300 * group is going to be restriped, run checks against the target
7298 * can just return. 7301 * profile instead of the current one.
7299 */ 7302 */
7300 ret = -1; 7303 ret = -1;
7301 if (full)
7302 goto out;
7303 7304
7304 /* 7305 /*
7305 * index: 7306 * index:
@@ -7309,7 +7310,20 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
7309 * 3: raid0 7310 * 3: raid0
7310 * 4: single 7311 * 4: single
7311 */ 7312 */
7312 index = get_block_group_index(block_group); 7313 target = get_restripe_target(root->fs_info, block_group->flags);
7314 if (target) {
7315 index = __get_block_group_index(extended_to_chunk(target));
7316 } else {
7317 /*
7318 * this is just a balance, so if we were marked as full
7319 * we know there is no space for a new chunk
7320 */
7321 if (full)
7322 goto out;
7323
7324 index = get_block_group_index(block_group);
7325 }
7326
7313 if (index == 0) { 7327 if (index == 0) {
7314 dev_min = 4; 7328 dev_min = 4;
7315 /* Divide by 2 */ 7329 /* Divide by 2 */
@@ -7720,11 +7734,8 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
7720 7734
7721static void clear_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) 7735static void clear_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
7722{ 7736{
7723 u64 extra_flags = flags & BTRFS_BLOCK_GROUP_PROFILE_MASK; 7737 u64 extra_flags = chunk_to_extended(flags) &
7724 7738 BTRFS_EXTENDED_PROFILE_MASK;
7725 /* chunk -> extended profile */
7726 if (extra_flags == 0)
7727 extra_flags = BTRFS_AVAIL_ALLOC_BIT_SINGLE;
7728 7739
7729 if (flags & BTRFS_BLOCK_GROUP_DATA) 7740 if (flags & BTRFS_BLOCK_GROUP_DATA)
7730 fs_info->avail_data_alloc_bits &= ~extra_flags; 7741 fs_info->avail_data_alloc_bits &= ~extra_flags;