diff options
author | Chris Mason <chris.mason@oracle.com> | 2012-01-16 15:26:02 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2012-01-16 15:26:02 -0500 |
commit | 27263e28321db438bc43dc0c0be432ce91526224 (patch) | |
tree | b7571dd52d6c1d48528e383d273b330da94439bd /fs/btrfs/extent-tree.c | |
parent | 64e05503ab5c73b2ffb8d55d2f7aab74f34fc691 (diff) | |
parent | 19a39dce3b9bf0244d19a446718ad6f7605ff099 (diff) |
Merge branch 'restriper' of git://github.com/idryomov/btrfs-unstable into integration
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 128 |
1 files changed, 103 insertions, 25 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 37594e4bf660..352083ad233c 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -618,8 +618,7 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info, | |||
618 | struct list_head *head = &info->space_info; | 618 | struct list_head *head = &info->space_info; |
619 | struct btrfs_space_info *found; | 619 | struct btrfs_space_info *found; |
620 | 620 | ||
621 | flags &= BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_SYSTEM | | 621 | flags &= BTRFS_BLOCK_GROUP_TYPE_MASK; |
622 | BTRFS_BLOCK_GROUP_METADATA; | ||
623 | 622 | ||
624 | rcu_read_lock(); | 623 | rcu_read_lock(); |
625 | list_for_each_entry_rcu(found, head, list) { | 624 | list_for_each_entry_rcu(found, head, list) { |
@@ -2999,9 +2998,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, | |||
2999 | INIT_LIST_HEAD(&found->block_groups[i]); | 2998 | INIT_LIST_HEAD(&found->block_groups[i]); |
3000 | init_rwsem(&found->groups_sem); | 2999 | init_rwsem(&found->groups_sem); |
3001 | spin_lock_init(&found->lock); | 3000 | spin_lock_init(&found->lock); |
3002 | found->flags = flags & (BTRFS_BLOCK_GROUP_DATA | | 3001 | found->flags = flags & BTRFS_BLOCK_GROUP_TYPE_MASK; |
3003 | BTRFS_BLOCK_GROUP_SYSTEM | | ||
3004 | BTRFS_BLOCK_GROUP_METADATA); | ||
3005 | found->total_bytes = total_bytes; | 3002 | found->total_bytes = total_bytes; |
3006 | found->disk_total = total_bytes * factor; | 3003 | found->disk_total = total_bytes * factor; |
3007 | found->bytes_used = bytes_used; | 3004 | found->bytes_used = bytes_used; |
@@ -3022,20 +3019,27 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, | |||
3022 | 3019 | ||
3023 | static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) | 3020 | static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) |
3024 | { | 3021 | { |
3025 | u64 extra_flags = flags & (BTRFS_BLOCK_GROUP_RAID0 | | 3022 | u64 extra_flags = flags & BTRFS_BLOCK_GROUP_PROFILE_MASK; |
3026 | BTRFS_BLOCK_GROUP_RAID1 | | 3023 | |
3027 | BTRFS_BLOCK_GROUP_RAID10 | | 3024 | /* chunk -> extended profile */ |
3028 | BTRFS_BLOCK_GROUP_DUP); | 3025 | if (extra_flags == 0) |
3029 | if (extra_flags) { | 3026 | extra_flags = BTRFS_AVAIL_ALLOC_BIT_SINGLE; |
3030 | if (flags & BTRFS_BLOCK_GROUP_DATA) | 3027 | |
3031 | fs_info->avail_data_alloc_bits |= extra_flags; | 3028 | if (flags & BTRFS_BLOCK_GROUP_DATA) |
3032 | if (flags & BTRFS_BLOCK_GROUP_METADATA) | 3029 | fs_info->avail_data_alloc_bits |= extra_flags; |
3033 | fs_info->avail_metadata_alloc_bits |= extra_flags; | 3030 | if (flags & BTRFS_BLOCK_GROUP_METADATA) |
3034 | if (flags & BTRFS_BLOCK_GROUP_SYSTEM) | 3031 | fs_info->avail_metadata_alloc_bits |= extra_flags; |
3035 | fs_info->avail_system_alloc_bits |= extra_flags; | 3032 | if (flags & BTRFS_BLOCK_GROUP_SYSTEM) |
3036 | } | 3033 | fs_info->avail_system_alloc_bits |= extra_flags; |
3037 | } | 3034 | } |
3038 | 3035 | ||
3036 | /* | ||
3037 | * @flags: available profiles in extended format (see ctree.h) | ||
3038 | * | ||
3039 | * Returns reduced profile in chunk format. If profile changing is in | ||
3040 | * progress (either running or paused) picks the target profile (if it's | ||
3041 | * already available), otherwise falls back to plain reducing. | ||
3042 | */ | ||
3039 | u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) | 3043 | u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) |
3040 | { | 3044 | { |
3041 | /* | 3045 | /* |
@@ -3046,6 +3050,34 @@ u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) | |||
3046 | u64 num_devices = root->fs_info->fs_devices->rw_devices + | 3050 | u64 num_devices = root->fs_info->fs_devices->rw_devices + |
3047 | root->fs_info->fs_devices->missing_devices; | 3051 | root->fs_info->fs_devices->missing_devices; |
3048 | 3052 | ||
3053 | /* pick restriper's target profile if it's available */ | ||
3054 | spin_lock(&root->fs_info->balance_lock); | ||
3055 | if (root->fs_info->balance_ctl) { | ||
3056 | struct btrfs_balance_control *bctl = root->fs_info->balance_ctl; | ||
3057 | u64 tgt = 0; | ||
3058 | |||
3059 | if ((flags & BTRFS_BLOCK_GROUP_DATA) && | ||
3060 | (bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) && | ||
3061 | (flags & bctl->data.target)) { | ||
3062 | tgt = BTRFS_BLOCK_GROUP_DATA | bctl->data.target; | ||
3063 | } else if ((flags & BTRFS_BLOCK_GROUP_SYSTEM) && | ||
3064 | (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) && | ||
3065 | (flags & bctl->sys.target)) { | ||
3066 | tgt = BTRFS_BLOCK_GROUP_SYSTEM | bctl->sys.target; | ||
3067 | } else if ((flags & BTRFS_BLOCK_GROUP_METADATA) && | ||
3068 | (bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) && | ||
3069 | (flags & bctl->meta.target)) { | ||
3070 | tgt = BTRFS_BLOCK_GROUP_METADATA | bctl->meta.target; | ||
3071 | } | ||
3072 | |||
3073 | if (tgt) { | ||
3074 | spin_unlock(&root->fs_info->balance_lock); | ||
3075 | flags = tgt; | ||
3076 | goto out; | ||
3077 | } | ||
3078 | } | ||
3079 | spin_unlock(&root->fs_info->balance_lock); | ||
3080 | |||
3049 | if (num_devices == 1) | 3081 | if (num_devices == 1) |
3050 | flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0); | 3082 | flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0); |
3051 | if (num_devices < 4) | 3083 | if (num_devices < 4) |
@@ -3065,22 +3097,25 @@ u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) | |||
3065 | if ((flags & BTRFS_BLOCK_GROUP_RAID0) && | 3097 | if ((flags & BTRFS_BLOCK_GROUP_RAID0) && |
3066 | ((flags & BTRFS_BLOCK_GROUP_RAID1) | | 3098 | ((flags & BTRFS_BLOCK_GROUP_RAID1) | |
3067 | (flags & BTRFS_BLOCK_GROUP_RAID10) | | 3099 | (flags & BTRFS_BLOCK_GROUP_RAID10) | |
3068 | (flags & BTRFS_BLOCK_GROUP_DUP))) | 3100 | (flags & BTRFS_BLOCK_GROUP_DUP))) { |
3069 | flags &= ~BTRFS_BLOCK_GROUP_RAID0; | 3101 | flags &= ~BTRFS_BLOCK_GROUP_RAID0; |
3102 | } | ||
3103 | |||
3104 | out: | ||
3105 | /* extended -> chunk profile */ | ||
3106 | flags &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE; | ||
3070 | return flags; | 3107 | return flags; |
3071 | } | 3108 | } |
3072 | 3109 | ||
3073 | static u64 get_alloc_profile(struct btrfs_root *root, u64 flags) | 3110 | static u64 get_alloc_profile(struct btrfs_root *root, u64 flags) |
3074 | { | 3111 | { |
3075 | if (flags & BTRFS_BLOCK_GROUP_DATA) | 3112 | if (flags & BTRFS_BLOCK_GROUP_DATA) |
3076 | flags |= root->fs_info->avail_data_alloc_bits & | 3113 | flags |= root->fs_info->avail_data_alloc_bits; |
3077 | root->fs_info->data_alloc_profile; | ||
3078 | else if (flags & BTRFS_BLOCK_GROUP_SYSTEM) | 3114 | else if (flags & BTRFS_BLOCK_GROUP_SYSTEM) |
3079 | flags |= root->fs_info->avail_system_alloc_bits & | 3115 | flags |= root->fs_info->avail_system_alloc_bits; |
3080 | root->fs_info->system_alloc_profile; | ||
3081 | else if (flags & BTRFS_BLOCK_GROUP_METADATA) | 3116 | else if (flags & BTRFS_BLOCK_GROUP_METADATA) |
3082 | flags |= root->fs_info->avail_metadata_alloc_bits & | 3117 | flags |= root->fs_info->avail_metadata_alloc_bits; |
3083 | root->fs_info->metadata_alloc_profile; | 3118 | |
3084 | return btrfs_reduce_alloc_profile(root, flags); | 3119 | return btrfs_reduce_alloc_profile(root, flags); |
3085 | } | 3120 | } |
3086 | 3121 | ||
@@ -3282,7 +3317,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
3282 | int wait_for_alloc = 0; | 3317 | int wait_for_alloc = 0; |
3283 | int ret = 0; | 3318 | int ret = 0; |
3284 | 3319 | ||
3285 | flags = btrfs_reduce_alloc_profile(extent_root, flags); | 3320 | BUG_ON(!profile_is_valid(flags, 0)); |
3286 | 3321 | ||
3287 | space_info = __find_space_info(extent_root->fs_info, flags); | 3322 | space_info = __find_space_info(extent_root->fs_info, flags); |
3288 | if (!space_info) { | 3323 | if (!space_info) { |
@@ -6792,6 +6827,29 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags) | |||
6792 | u64 stripped = BTRFS_BLOCK_GROUP_RAID0 | | 6827 | u64 stripped = BTRFS_BLOCK_GROUP_RAID0 | |
6793 | BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10; | 6828 | BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10; |
6794 | 6829 | ||
6830 | if (root->fs_info->balance_ctl) { | ||
6831 | struct btrfs_balance_control *bctl = root->fs_info->balance_ctl; | ||
6832 | u64 tgt = 0; | ||
6833 | |||
6834 | /* pick restriper's target profile and return */ | ||
6835 | if (flags & BTRFS_BLOCK_GROUP_DATA && | ||
6836 | bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) { | ||
6837 | tgt = BTRFS_BLOCK_GROUP_DATA | bctl->data.target; | ||
6838 | } else if (flags & BTRFS_BLOCK_GROUP_SYSTEM && | ||
6839 | bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) { | ||
6840 | tgt = BTRFS_BLOCK_GROUP_SYSTEM | bctl->sys.target; | ||
6841 | } else if (flags & BTRFS_BLOCK_GROUP_METADATA && | ||
6842 | bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) { | ||
6843 | tgt = BTRFS_BLOCK_GROUP_METADATA | bctl->meta.target; | ||
6844 | } | ||
6845 | |||
6846 | if (tgt) { | ||
6847 | /* extended -> chunk profile */ | ||
6848 | tgt &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE; | ||
6849 | return tgt; | ||
6850 | } | ||
6851 | } | ||
6852 | |||
6795 | /* | 6853 | /* |
6796 | * we add in the count of missing devices because we want | 6854 | * we add in the count of missing devices because we want |
6797 | * to make sure that any RAID levels on a degraded FS | 6855 | * to make sure that any RAID levels on a degraded FS |
@@ -7466,6 +7524,22 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, | |||
7466 | return 0; | 7524 | return 0; |
7467 | } | 7525 | } |
7468 | 7526 | ||
7527 | static void clear_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) | ||
7528 | { | ||
7529 | u64 extra_flags = flags & BTRFS_BLOCK_GROUP_PROFILE_MASK; | ||
7530 | |||
7531 | /* chunk -> extended profile */ | ||
7532 | if (extra_flags == 0) | ||
7533 | extra_flags = BTRFS_AVAIL_ALLOC_BIT_SINGLE; | ||
7534 | |||
7535 | if (flags & BTRFS_BLOCK_GROUP_DATA) | ||
7536 | fs_info->avail_data_alloc_bits &= ~extra_flags; | ||
7537 | if (flags & BTRFS_BLOCK_GROUP_METADATA) | ||
7538 | fs_info->avail_metadata_alloc_bits &= ~extra_flags; | ||
7539 | if (flags & BTRFS_BLOCK_GROUP_SYSTEM) | ||
7540 | fs_info->avail_system_alloc_bits &= ~extra_flags; | ||
7541 | } | ||
7542 | |||
7469 | int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | 7543 | int btrfs_remove_block_group(struct btrfs_trans_handle *trans, |
7470 | struct btrfs_root *root, u64 group_start) | 7544 | struct btrfs_root *root, u64 group_start) |
7471 | { | 7545 | { |
@@ -7476,6 +7550,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
7476 | struct btrfs_key key; | 7550 | struct btrfs_key key; |
7477 | struct inode *inode; | 7551 | struct inode *inode; |
7478 | int ret; | 7552 | int ret; |
7553 | int index; | ||
7479 | int factor; | 7554 | int factor; |
7480 | 7555 | ||
7481 | root = root->fs_info->extent_root; | 7556 | root = root->fs_info->extent_root; |
@@ -7491,6 +7566,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
7491 | free_excluded_extents(root, block_group); | 7566 | free_excluded_extents(root, block_group); |
7492 | 7567 | ||
7493 | memcpy(&key, &block_group->key, sizeof(key)); | 7568 | memcpy(&key, &block_group->key, sizeof(key)); |
7569 | index = get_block_group_index(block_group); | ||
7494 | if (block_group->flags & (BTRFS_BLOCK_GROUP_DUP | | 7570 | if (block_group->flags & (BTRFS_BLOCK_GROUP_DUP | |
7495 | BTRFS_BLOCK_GROUP_RAID1 | | 7571 | BTRFS_BLOCK_GROUP_RAID1 | |
7496 | BTRFS_BLOCK_GROUP_RAID10)) | 7572 | BTRFS_BLOCK_GROUP_RAID10)) |
@@ -7565,6 +7641,8 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
7565 | * are still on the list after taking the semaphore | 7641 | * are still on the list after taking the semaphore |
7566 | */ | 7642 | */ |
7567 | list_del_init(&block_group->list); | 7643 | list_del_init(&block_group->list); |
7644 | if (list_empty(&block_group->space_info->block_groups[index])) | ||
7645 | clear_avail_alloc_bits(root->fs_info, block_group->flags); | ||
7568 | up_write(&block_group->space_info->groups_sem); | 7646 | up_write(&block_group->space_info->groups_sem); |
7569 | 7647 | ||
7570 | if (block_group->cached == BTRFS_CACHE_STARTED) | 7648 | if (block_group->cached == BTRFS_CACHE_STARTED) |