aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2009-09-11 16:11:19 -0400
committerChris Mason <chris.mason@oracle.com>2009-09-21 19:23:48 -0400
commitba1bf4818baf68d914ef9e3b06fbea6acb674fe4 (patch)
tree1068d6ce508333a75668181bfe0e42956d4d8780 /fs/btrfs/extent-tree.c
parent1fb58a6051cd904a9f8e0344b22e31921d6b5a4d (diff)
Btrfs: make balance code choose more wisely when relocating
Currently, we can panic the box if the first block group we go to move is of a type where there is no space left to move those extents. For example, if we fill the disk up with data, and then we try to balance and we have no room to move the data nor room to allocate new chunks, we will panic. Change this by checking to see if we have room to move this chunk around, and if not, return -ENOSPC and move on to the next chunk. This will make sure we remove block groups that are moveable, like if we have alot of empty metadata block groups, and then that way we make room to be able to balance our data chunks as well. Tested this with an fs that would panic on btrfs-vol -b normally, but no longer panics with this patch. V1->V2: -actually search for a free extent on the device to make sure we can allocate a chunk if need be. -fix btrfs_shrink_device to make sure we actually try to relocate all the chunks, and then if we can't return -ENOSPC so if we are doing a btrfs-vol -r we don't remove the device with data still on it. -check to make sure the block group we are going to relocate isn't the last one in that particular space -fix a bug in btrfs_shrink_device where we would change the device's size and not fix it if we fail to do our relocate Signed-off-by: Josef Bacik <jbacik@redhat.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 4bd04f3fa8bb..4c7c9467f224 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -7402,6 +7402,93 @@ out:
7402} 7402}
7403#endif 7403#endif
7404 7404
7405/*
7406 * checks to see if its even possible to relocate this block group.
7407 *
7408 * @return - -1 if it's not a good idea to relocate this block group, 0 if its
7409 * ok to go ahead and try.
7410 */
7411int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
7412{
7413 struct btrfs_block_group_cache *block_group;
7414 struct btrfs_space_info *space_info;
7415 struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
7416 struct btrfs_device *device;
7417 int full = 0;
7418 int ret = 0;
7419
7420 block_group = btrfs_lookup_block_group(root->fs_info, bytenr);
7421
7422 /* odd, couldn't find the block group, leave it alone */
7423 if (!block_group)
7424 return -1;
7425
7426 /* no bytes used, we're good */
7427 if (!btrfs_block_group_used(&block_group->item))
7428 goto out;
7429
7430 space_info = block_group->space_info;
7431 spin_lock(&space_info->lock);
7432
7433 full = space_info->full;
7434
7435 /*
7436 * if this is the last block group we have in this space, we can't
7437 * relocate it.
7438 */
7439 if (space_info->total_bytes == block_group->key.offset) {
7440 ret = -1;
7441 spin_unlock(&space_info->lock);
7442 goto out;
7443 }
7444
7445 /*
7446 * need to make sure we have room in the space to handle all of the
7447 * extents from this block group. If we can, we're good
7448 */
7449 if (space_info->bytes_used + space_info->bytes_reserved +
7450 space_info->bytes_pinned + space_info->bytes_readonly +
7451 btrfs_block_group_used(&block_group->item) <
7452 space_info->total_bytes) {
7453 spin_unlock(&space_info->lock);
7454 goto out;
7455 }
7456 spin_unlock(&space_info->lock);
7457
7458 /*
7459 * ok we don't have enough space, but maybe we have free space on our
7460 * devices to allocate new chunks for relocation, so loop through our
7461 * alloc devices and guess if we have enough space. However, if we
7462 * were marked as full, then we know there aren't enough chunks, and we
7463 * can just return.
7464 */
7465 ret = -1;
7466 if (full)
7467 goto out;
7468
7469 mutex_lock(&root->fs_info->chunk_mutex);
7470 list_for_each_entry(device, &fs_devices->alloc_list, dev_alloc_list) {
7471 u64 min_free = btrfs_block_group_used(&block_group->item);
7472 u64 dev_offset, max_avail;
7473
7474 /*
7475 * check to make sure we can actually find a chunk with enough
7476 * space to fit our block group in.
7477 */
7478 if (device->total_bytes > device->bytes_used + min_free) {
7479 ret = find_free_dev_extent(NULL, device, min_free,
7480 &dev_offset, &max_avail);
7481 if (!ret)
7482 break;
7483 ret = -1;
7484 }
7485 }
7486 mutex_unlock(&root->fs_info->chunk_mutex);
7487out:
7488 btrfs_put_block_group(block_group);
7489 return ret;
7490}
7491
7405static int find_first_block_group(struct btrfs_root *root, 7492static int find_first_block_group(struct btrfs_root *root,
7406 struct btrfs_path *path, struct btrfs_key *key) 7493 struct btrfs_path *path, struct btrfs_key *key)
7407{ 7494{