aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorIlya Dryomov <idryomov@gmail.com>2012-03-27 10:09:17 -0400
committerIlya Dryomov <idryomov@gmail.com>2012-03-27 10:09:17 -0400
commit4a5e98f5d61f698452e564e0cde34c16a6b65752 (patch)
treed65c346e8763380a1afac2984abc12533ecf15b7 /fs/btrfs
parent7738a53a3a3aa8d82350280ff4bc7df9c3094123 (diff)
Btrfs: improve the logic in btrfs_can_relocate()
Currently if we don't have enough space allocated we go ahead and loop though devices in the hopes of finding enough space for a chunk of the *same* type as the one we are trying to relocate. The problem with that is that if we are trying to restripe the chunk its target type can be more relaxed than the current one (eg require less devices or less space). So, when restriping, run checks against the target profile instead of the current one. Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/extent-tree.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index c44aa9680789..9454045f091a 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -7136,6 +7136,7 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
7136 u64 min_free; 7136 u64 min_free;
7137 u64 dev_min = 1; 7137 u64 dev_min = 1;
7138 u64 dev_nr = 0; 7138 u64 dev_nr = 0;
7139 u64 target;
7139 int index; 7140 int index;
7140 int full = 0; 7141 int full = 0;
7141 int ret = 0; 7142 int ret = 0;
@@ -7176,13 +7177,11 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
7176 /* 7177 /*
7177 * ok we don't have enough space, but maybe we have free space on our 7178 * ok we don't have enough space, but maybe we have free space on our
7178 * devices to allocate new chunks for relocation, so loop through our 7179 * devices to allocate new chunks for relocation, so loop through our
7179 * alloc devices and guess if we have enough space. However, if we 7180 * alloc devices and guess if we have enough space. if this block
7180 * were marked as full, then we know there aren't enough chunks, and we 7181 * group is going to be restriped, run checks against the target
7181 * can just return. 7182 * profile instead of the current one.
7182 */ 7183 */
7183 ret = -1; 7184 ret = -1;
7184 if (full)
7185 goto out;
7186 7185
7187 /* 7186 /*
7188 * index: 7187 * index:
@@ -7192,7 +7191,20 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
7192 * 3: raid0 7191 * 3: raid0
7193 * 4: single 7192 * 4: single
7194 */ 7193 */
7195 index = get_block_group_index(block_group); 7194 target = get_restripe_target(root->fs_info, block_group->flags);
7195 if (target) {
7196 index = __get_block_group_index(extended_to_chunk(target));
7197 } else {
7198 /*
7199 * this is just a balance, so if we were marked as full
7200 * we know there is no space for a new chunk
7201 */
7202 if (full)
7203 goto out;
7204
7205 index = get_block_group_index(block_group);
7206 }
7207
7196 if (index == 0) { 7208 if (index == 0) {
7197 dev_min = 4; 7209 dev_min = 4;
7198 /* Divide by 2 */ 7210 /* Divide by 2 */