diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
| -rw-r--r-- | fs/btrfs/extent-tree.c | 87 |
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 | */ | ||
| 7411 | int 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); | ||
| 7487 | out: | ||
| 7488 | btrfs_put_block_group(block_group); | ||
| 7489 | return ret; | ||
| 7490 | } | ||
| 7491 | |||
| 7405 | static int find_first_block_group(struct btrfs_root *root, | 7492 | static 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 | { |
