aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
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{