mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-20 03:04:01 +08:00
Btrfs: implement online profile changing
Profile changing is done by launching a balance with BTRFS_BALANCE_CONVERT bits set and target fields of respective btrfs_balance_args structs initialized. Profile reducing code in this case will pick restriper's target profile if it's available instead of doing a blind reduce. If target profile is not yet available it goes back to a plain reduce. Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
parent
70922617b0
commit
e4d8ec0f65
@ -3030,7 +3030,9 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
|
|||||||
/*
|
/*
|
||||||
* @flags: available profiles in extended format (see ctree.h)
|
* @flags: available profiles in extended format (see ctree.h)
|
||||||
*
|
*
|
||||||
* Returns reduced profile in chunk format.
|
* 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)
|
u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
|
||||||
{
|
{
|
||||||
@ -3042,6 +3044,34 @@ u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
|
|||||||
u64 num_devices = root->fs_info->fs_devices->rw_devices +
|
u64 num_devices = root->fs_info->fs_devices->rw_devices +
|
||||||
root->fs_info->fs_devices->missing_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)
|
if (num_devices == 1)
|
||||||
flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0);
|
flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0);
|
||||||
if (num_devices < 4)
|
if (num_devices < 4)
|
||||||
@ -3065,6 +3095,7 @@ u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
|
|||||||
flags &= ~BTRFS_BLOCK_GROUP_RAID0;
|
flags &= ~BTRFS_BLOCK_GROUP_RAID0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
/* extended -> chunk profile */
|
/* extended -> chunk profile */
|
||||||
flags &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE;
|
flags &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE;
|
||||||
return flags;
|
return flags;
|
||||||
@ -6795,6 +6826,29 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
|
|||||||
u64 stripped = BTRFS_BLOCK_GROUP_RAID0 |
|
u64 stripped = BTRFS_BLOCK_GROUP_RAID0 |
|
||||||
BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10;
|
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
|
* we add in the count of missing devices because we want
|
||||||
* to make sure that any RAID levels on a degraded FS
|
* to make sure that any RAID levels on a degraded FS
|
||||||
|
@ -2438,6 +2438,75 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Profile changing sanity checks. Skip them if a simple
|
||||||
|
* balance is requested.
|
||||||
|
*/
|
||||||
|
if (!((bctl->data.flags | bctl->sys.flags | bctl->meta.flags) &
|
||||||
|
BTRFS_BALANCE_ARGS_CONVERT))
|
||||||
|
goto do_balance;
|
||||||
|
|
||||||
|
allowed = BTRFS_AVAIL_ALLOC_BIT_SINGLE;
|
||||||
|
if (fs_info->fs_devices->num_devices == 1)
|
||||||
|
allowed |= BTRFS_BLOCK_GROUP_DUP;
|
||||||
|
else if (fs_info->fs_devices->num_devices < 4)
|
||||||
|
allowed |= (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1);
|
||||||
|
else
|
||||||
|
allowed |= (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 |
|
||||||
|
BTRFS_BLOCK_GROUP_RAID10);
|
||||||
|
|
||||||
|
if (!profile_is_valid(bctl->data.target, 1) ||
|
||||||
|
bctl->data.target & ~allowed) {
|
||||||
|
printk(KERN_ERR "btrfs: unable to start balance with target "
|
||||||
|
"data profile %llu\n",
|
||||||
|
(unsigned long long)bctl->data.target);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!profile_is_valid(bctl->meta.target, 1) ||
|
||||||
|
bctl->meta.target & ~allowed) {
|
||||||
|
printk(KERN_ERR "btrfs: unable to start balance with target "
|
||||||
|
"metadata profile %llu\n",
|
||||||
|
(unsigned long long)bctl->meta.target);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!profile_is_valid(bctl->sys.target, 1) ||
|
||||||
|
bctl->sys.target & ~allowed) {
|
||||||
|
printk(KERN_ERR "btrfs: unable to start balance with target "
|
||||||
|
"system profile %llu\n",
|
||||||
|
(unsigned long long)bctl->sys.target);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bctl->data.target & BTRFS_BLOCK_GROUP_DUP) {
|
||||||
|
printk(KERN_ERR "btrfs: dup for data is not allowed\n");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allow to reduce meta or sys integrity only if force set */
|
||||||
|
allowed = BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID1 |
|
||||||
|
BTRFS_BLOCK_GROUP_RAID10;
|
||||||
|
if (((bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
|
||||||
|
(fs_info->avail_system_alloc_bits & allowed) &&
|
||||||
|
!(bctl->sys.target & allowed)) ||
|
||||||
|
((bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
|
||||||
|
(fs_info->avail_metadata_alloc_bits & allowed) &&
|
||||||
|
!(bctl->meta.target & allowed))) {
|
||||||
|
if (bctl->flags & BTRFS_BALANCE_FORCE) {
|
||||||
|
printk(KERN_INFO "btrfs: force reducing metadata "
|
||||||
|
"integrity\n");
|
||||||
|
} else {
|
||||||
|
printk(KERN_ERR "btrfs: balance will reduce metadata "
|
||||||
|
"integrity, use force if you want this\n");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do_balance:
|
||||||
set_balance_control(bctl);
|
set_balance_control(bctl);
|
||||||
|
|
||||||
mutex_unlock(&fs_info->balance_mutex);
|
mutex_unlock(&fs_info->balance_mutex);
|
||||||
|
@ -196,6 +196,9 @@ struct map_lookup {
|
|||||||
#define BTRFS_BALANCE_TYPE_MASK (BTRFS_BALANCE_DATA | \
|
#define BTRFS_BALANCE_TYPE_MASK (BTRFS_BALANCE_DATA | \
|
||||||
BTRFS_BALANCE_SYSTEM | \
|
BTRFS_BALANCE_SYSTEM | \
|
||||||
BTRFS_BALANCE_METADATA)
|
BTRFS_BALANCE_METADATA)
|
||||||
|
|
||||||
|
#define BTRFS_BALANCE_FORCE (1ULL << 3)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Balance filters
|
* Balance filters
|
||||||
*/
|
*/
|
||||||
@ -205,6 +208,8 @@ struct map_lookup {
|
|||||||
#define BTRFS_BALANCE_ARGS_DRANGE (1ULL << 3)
|
#define BTRFS_BALANCE_ARGS_DRANGE (1ULL << 3)
|
||||||
#define BTRFS_BALANCE_ARGS_VRANGE (1ULL << 4)
|
#define BTRFS_BALANCE_ARGS_VRANGE (1ULL << 4)
|
||||||
|
|
||||||
|
#define BTRFS_BALANCE_ARGS_CONVERT (1ULL << 8)
|
||||||
|
|
||||||
struct btrfs_balance_args;
|
struct btrfs_balance_args;
|
||||||
struct btrfs_balance_control {
|
struct btrfs_balance_control {
|
||||||
struct btrfs_fs_info *fs_info;
|
struct btrfs_fs_info *fs_info;
|
||||||
|
Loading…
Reference in New Issue
Block a user