Skip to content

Commit

Permalink
Btrfs: improve the logic in btrfs_can_relocate()
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ilya Dryomov committed Mar 27, 2012
1 parent 7738a53 commit 4a5e98f
Showing 1 changed file with 18 additions and 6 deletions.
24 changes: 18 additions & 6 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -7136,6 +7136,7 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
u64 min_free;
u64 dev_min = 1;
u64 dev_nr = 0;
u64 target;
int index;
int full = 0;
int ret = 0;
Expand Down Expand Up @@ -7176,13 +7177,11 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
/*
* ok we don't have enough space, but maybe we have free space on our
* devices to allocate new chunks for relocation, so loop through our
* alloc devices and guess if we have enough space. However, if we
* were marked as full, then we know there aren't enough chunks, and we
* can just return.
* alloc devices and guess if we have enough space. if this block
* group is going to be restriped, run checks against the target
* profile instead of the current one.
*/
ret = -1;
if (full)
goto out;

/*
* index:
Expand All @@ -7192,7 +7191,20 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
* 3: raid0
* 4: single
*/
index = get_block_group_index(block_group);
target = get_restripe_target(root->fs_info, block_group->flags);
if (target) {
index = __get_block_group_index(extended_to_chunk(target));
} else {
/*
* this is just a balance, so if we were marked as full
* we know there is no space for a new chunk
*/
if (full)
goto out;

index = get_block_group_index(block_group);
}

if (index == 0) {
dev_min = 4;
/* Divide by 2 */
Expand Down

0 comments on commit 4a5e98f

Please sign in to comment.