Merge branch 'restriper' of git://github.com/idryomov/btrfs-unstable into integration
This commit is contained in:
@@ -618,8 +618,7 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,
|
||||
struct list_head *head = &info->space_info;
|
||||
struct btrfs_space_info *found;
|
||||
|
||||
flags &= BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_SYSTEM |
|
||||
BTRFS_BLOCK_GROUP_METADATA;
|
||||
flags &= BTRFS_BLOCK_GROUP_TYPE_MASK;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(found, head, list) {
|
||||
@@ -2999,9 +2998,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
|
||||
INIT_LIST_HEAD(&found->block_groups[i]);
|
||||
init_rwsem(&found->groups_sem);
|
||||
spin_lock_init(&found->lock);
|
||||
found->flags = flags & (BTRFS_BLOCK_GROUP_DATA |
|
||||
BTRFS_BLOCK_GROUP_SYSTEM |
|
||||
BTRFS_BLOCK_GROUP_METADATA);
|
||||
found->flags = flags & BTRFS_BLOCK_GROUP_TYPE_MASK;
|
||||
found->total_bytes = total_bytes;
|
||||
found->disk_total = total_bytes * factor;
|
||||
found->bytes_used = bytes_used;
|
||||
@@ -3022,20 +3019,27 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
|
||||
|
||||
static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
|
||||
{
|
||||
u64 extra_flags = flags & (BTRFS_BLOCK_GROUP_RAID0 |
|
||||
BTRFS_BLOCK_GROUP_RAID1 |
|
||||
BTRFS_BLOCK_GROUP_RAID10 |
|
||||
BTRFS_BLOCK_GROUP_DUP);
|
||||
if (extra_flags) {
|
||||
if (flags & BTRFS_BLOCK_GROUP_DATA)
|
||||
fs_info->avail_data_alloc_bits |= extra_flags;
|
||||
if (flags & BTRFS_BLOCK_GROUP_METADATA)
|
||||
fs_info->avail_metadata_alloc_bits |= extra_flags;
|
||||
if (flags & BTRFS_BLOCK_GROUP_SYSTEM)
|
||||
fs_info->avail_system_alloc_bits |= extra_flags;
|
||||
}
|
||||
u64 extra_flags = flags & BTRFS_BLOCK_GROUP_PROFILE_MASK;
|
||||
|
||||
/* chunk -> extended profile */
|
||||
if (extra_flags == 0)
|
||||
extra_flags = BTRFS_AVAIL_ALLOC_BIT_SINGLE;
|
||||
|
||||
if (flags & BTRFS_BLOCK_GROUP_DATA)
|
||||
fs_info->avail_data_alloc_bits |= extra_flags;
|
||||
if (flags & BTRFS_BLOCK_GROUP_METADATA)
|
||||
fs_info->avail_metadata_alloc_bits |= extra_flags;
|
||||
if (flags & BTRFS_BLOCK_GROUP_SYSTEM)
|
||||
fs_info->avail_system_alloc_bits |= extra_flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* @flags: available profiles in extended format (see ctree.h)
|
||||
*
|
||||
* Returns reduced profile in chunk format. If profile changing is in
|
||||
* progress (either running or paused) picks the target profile (if it's
|
||||
* already available), otherwise falls back to plain reducing.
|
||||
*/
|
||||
u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
|
||||
{
|
||||
/*
|
||||
@@ -3046,6 +3050,34 @@ u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
|
||||
u64 num_devices = root->fs_info->fs_devices->rw_devices +
|
||||
root->fs_info->fs_devices->missing_devices;
|
||||
|
||||
/* pick restriper's target profile if it's available */
|
||||
spin_lock(&root->fs_info->balance_lock);
|
||||
if (root->fs_info->balance_ctl) {
|
||||
struct btrfs_balance_control *bctl = root->fs_info->balance_ctl;
|
||||
u64 tgt = 0;
|
||||
|
||||
if ((flags & BTRFS_BLOCK_GROUP_DATA) &&
|
||||
(bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
|
||||
(flags & bctl->data.target)) {
|
||||
tgt = BTRFS_BLOCK_GROUP_DATA | bctl->data.target;
|
||||
} else if ((flags & BTRFS_BLOCK_GROUP_SYSTEM) &&
|
||||
(bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
|
||||
(flags & bctl->sys.target)) {
|
||||
tgt = BTRFS_BLOCK_GROUP_SYSTEM | bctl->sys.target;
|
||||
} else if ((flags & BTRFS_BLOCK_GROUP_METADATA) &&
|
||||
(bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
|
||||
(flags & bctl->meta.target)) {
|
||||
tgt = BTRFS_BLOCK_GROUP_METADATA | bctl->meta.target;
|
||||
}
|
||||
|
||||
if (tgt) {
|
||||
spin_unlock(&root->fs_info->balance_lock);
|
||||
flags = tgt;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
spin_unlock(&root->fs_info->balance_lock);
|
||||
|
||||
if (num_devices == 1)
|
||||
flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0);
|
||||
if (num_devices < 4)
|
||||
@@ -3065,22 +3097,25 @@ u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
|
||||
if ((flags & BTRFS_BLOCK_GROUP_RAID0) &&
|
||||
((flags & BTRFS_BLOCK_GROUP_RAID1) |
|
||||
(flags & BTRFS_BLOCK_GROUP_RAID10) |
|
||||
(flags & BTRFS_BLOCK_GROUP_DUP)))
|
||||
(flags & BTRFS_BLOCK_GROUP_DUP))) {
|
||||
flags &= ~BTRFS_BLOCK_GROUP_RAID0;
|
||||
}
|
||||
|
||||
out:
|
||||
/* extended -> chunk profile */
|
||||
flags &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE;
|
||||
return flags;
|
||||
}
|
||||
|
||||
static u64 get_alloc_profile(struct btrfs_root *root, u64 flags)
|
||||
{
|
||||
if (flags & BTRFS_BLOCK_GROUP_DATA)
|
||||
flags |= root->fs_info->avail_data_alloc_bits &
|
||||
root->fs_info->data_alloc_profile;
|
||||
flags |= root->fs_info->avail_data_alloc_bits;
|
||||
else if (flags & BTRFS_BLOCK_GROUP_SYSTEM)
|
||||
flags |= root->fs_info->avail_system_alloc_bits &
|
||||
root->fs_info->system_alloc_profile;
|
||||
flags |= root->fs_info->avail_system_alloc_bits;
|
||||
else if (flags & BTRFS_BLOCK_GROUP_METADATA)
|
||||
flags |= root->fs_info->avail_metadata_alloc_bits &
|
||||
root->fs_info->metadata_alloc_profile;
|
||||
flags |= root->fs_info->avail_metadata_alloc_bits;
|
||||
|
||||
return btrfs_reduce_alloc_profile(root, flags);
|
||||
}
|
||||
|
||||
@@ -3282,7 +3317,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
|
||||
int wait_for_alloc = 0;
|
||||
int ret = 0;
|
||||
|
||||
flags = btrfs_reduce_alloc_profile(extent_root, flags);
|
||||
BUG_ON(!profile_is_valid(flags, 0));
|
||||
|
||||
space_info = __find_space_info(extent_root->fs_info, flags);
|
||||
if (!space_info) {
|
||||
@@ -6792,6 +6827,29 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
|
||||
u64 stripped = BTRFS_BLOCK_GROUP_RAID0 |
|
||||
BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10;
|
||||
|
||||
if (root->fs_info->balance_ctl) {
|
||||
struct btrfs_balance_control *bctl = root->fs_info->balance_ctl;
|
||||
u64 tgt = 0;
|
||||
|
||||
/* pick restriper's target profile and return */
|
||||
if (flags & BTRFS_BLOCK_GROUP_DATA &&
|
||||
bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) {
|
||||
tgt = BTRFS_BLOCK_GROUP_DATA | bctl->data.target;
|
||||
} else if (flags & BTRFS_BLOCK_GROUP_SYSTEM &&
|
||||
bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
|
||||
tgt = BTRFS_BLOCK_GROUP_SYSTEM | bctl->sys.target;
|
||||
} else if (flags & BTRFS_BLOCK_GROUP_METADATA &&
|
||||
bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) {
|
||||
tgt = BTRFS_BLOCK_GROUP_METADATA | bctl->meta.target;
|
||||
}
|
||||
|
||||
if (tgt) {
|
||||
/* extended -> chunk profile */
|
||||
tgt &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE;
|
||||
return tgt;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* we add in the count of missing devices because we want
|
||||
* 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,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clear_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
|
||||
{
|
||||
u64 extra_flags = flags & BTRFS_BLOCK_GROUP_PROFILE_MASK;
|
||||
|
||||
/* chunk -> extended profile */
|
||||
if (extra_flags == 0)
|
||||
extra_flags = BTRFS_AVAIL_ALLOC_BIT_SINGLE;
|
||||
|
||||
if (flags & BTRFS_BLOCK_GROUP_DATA)
|
||||
fs_info->avail_data_alloc_bits &= ~extra_flags;
|
||||
if (flags & BTRFS_BLOCK_GROUP_METADATA)
|
||||
fs_info->avail_metadata_alloc_bits &= ~extra_flags;
|
||||
if (flags & BTRFS_BLOCK_GROUP_SYSTEM)
|
||||
fs_info->avail_system_alloc_bits &= ~extra_flags;
|
||||
}
|
||||
|
||||
int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root, u64 group_start)
|
||||
{
|
||||
@@ -7476,6 +7550,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_key key;
|
||||
struct inode *inode;
|
||||
int ret;
|
||||
int index;
|
||||
int factor;
|
||||
|
||||
root = root->fs_info->extent_root;
|
||||
@@ -7491,6 +7566,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
|
||||
free_excluded_extents(root, block_group);
|
||||
|
||||
memcpy(&key, &block_group->key, sizeof(key));
|
||||
index = get_block_group_index(block_group);
|
||||
if (block_group->flags & (BTRFS_BLOCK_GROUP_DUP |
|
||||
BTRFS_BLOCK_GROUP_RAID1 |
|
||||
BTRFS_BLOCK_GROUP_RAID10))
|
||||
@@ -7565,6 +7641,8 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
|
||||
* are still on the list after taking the semaphore
|
||||
*/
|
||||
list_del_init(&block_group->list);
|
||||
if (list_empty(&block_group->space_info->block_groups[index]))
|
||||
clear_avail_alloc_bits(root->fs_info, block_group->flags);
|
||||
up_write(&block_group->space_info->groups_sem);
|
||||
|
||||
if (block_group->cached == BTRFS_CACHE_STARTED)
|
||||
|
Reference in New Issue
Block a user