aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2012-01-16 15:26:02 -0500
committerChris Mason <chris.mason@oracle.com>2012-01-16 15:26:02 -0500
commit27263e28321db438bc43dc0c0be432ce91526224 (patch)
treeb7571dd52d6c1d48528e383d273b330da94439bd /fs/btrfs/extent-tree.c
parent64e05503ab5c73b2ffb8d55d2f7aab74f34fc691 (diff)
parent19a39dce3b9bf0244d19a446718ad6f7605ff099 (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.c128
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
3023static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) 3020static 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 */
3039u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) 3043u64 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
3104out:
3105 /* extended -> chunk profile */
3106 flags &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE;
3070 return flags; 3107 return flags;
3071} 3108}
3072 3109
3073static u64 get_alloc_profile(struct btrfs_root *root, u64 flags) 3110static 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
7527static 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
7469int btrfs_remove_block_group(struct btrfs_trans_handle *trans, 7543int 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)