diff options
author | Chris Mason <chris.mason@oracle.com> | 2012-03-28 20:32:46 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2012-03-28 20:32:46 -0400 |
commit | 1c691b330a19a1344df89bcb0f4cacd99e8b289a (patch) | |
tree | b3143a9875a773d33b9b8f60e98c7e5fae003b6a /fs/btrfs/extent-tree.c | |
parent | 1d4284bd6e8d7dd1d5521a6747bdb6dc1caf0225 (diff) | |
parent | 213e64da90d14537cd63f7090d6c4d1fcc75d9f8 (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.c | 163 |
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 | ||
3139 | static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) | 3139 | static 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 | */ | ||
3156 | static 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 | ||
3223 | out: | 3237 | return extended_to_chunk(flags); |
3224 | /* extended -> chunk profile */ | ||
3225 | flags &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE; | ||
3226 | return flags; | ||
3227 | } | 3238 | } |
3228 | 3239 | ||
3229 | static u64 get_alloc_profile(struct btrfs_root *root, u64 flags) | 3240 | static 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 | ||
5303 | static int get_block_group_index(struct btrfs_block_group_cache *cache) | 5312 | static 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 | ||
5330 | static int get_block_group_index(struct btrfs_block_group_cache *cache) | ||
5331 | { | ||
5332 | return __get_block_group_index(cache->flags); | ||
5333 | } | ||
5334 | |||
5319 | enum btrfs_loop_type { | 5335 | enum 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, | |||
7011 | static u64 update_block_group_flags(struct btrfs_root *root, u64 flags) | 7027 | static 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 | ||
7721 | static void clear_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) | 7735 | static 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; |