btrfs: introduce exclusive operation BALANCE_PAUSED state
Current set of exclusive operation states is not sufficient to handle all practical use cases. In particular there is a need to be able to add a device to a filesystem that have paused balance. Currently there is no way to distinguish between a running and a paused balance. Fix this by introducing BTRFS_EXCLOP_BALANCE_PAUSED which is going to be set in 2 occasions: 1. When a filesystem is mounted with skip_balance and there is an unfinished balance it will now be into BALANCE_PAUSED instead of simply BALANCE state. 2. When a running balance is paused. Signed-off-by: Nikolay Borisov <nborisov@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
d96b34248c
commit
efc0e69c2f
3 changed files with 36 additions and 2 deletions
|
@ -611,6 +611,7 @@ enum {
|
||||||
*/
|
*/
|
||||||
enum btrfs_exclusive_operation {
|
enum btrfs_exclusive_operation {
|
||||||
BTRFS_EXCLOP_NONE,
|
BTRFS_EXCLOP_NONE,
|
||||||
|
BTRFS_EXCLOP_BALANCE_PAUSED,
|
||||||
BTRFS_EXCLOP_BALANCE,
|
BTRFS_EXCLOP_BALANCE,
|
||||||
BTRFS_EXCLOP_DEV_ADD,
|
BTRFS_EXCLOP_DEV_ADD,
|
||||||
BTRFS_EXCLOP_DEV_REMOVE,
|
BTRFS_EXCLOP_DEV_REMOVE,
|
||||||
|
@ -3321,6 +3322,9 @@ bool btrfs_exclop_start_try_lock(struct btrfs_fs_info *fs_info,
|
||||||
enum btrfs_exclusive_operation type);
|
enum btrfs_exclusive_operation type);
|
||||||
void btrfs_exclop_start_unlock(struct btrfs_fs_info *fs_info);
|
void btrfs_exclop_start_unlock(struct btrfs_fs_info *fs_info);
|
||||||
void btrfs_exclop_finish(struct btrfs_fs_info *fs_info);
|
void btrfs_exclop_finish(struct btrfs_fs_info *fs_info);
|
||||||
|
void btrfs_exclop_balance(struct btrfs_fs_info *fs_info,
|
||||||
|
enum btrfs_exclusive_operation op);
|
||||||
|
|
||||||
|
|
||||||
/* file.c */
|
/* file.c */
|
||||||
int __init btrfs_auto_defrag_init(void);
|
int __init btrfs_auto_defrag_init(void);
|
||||||
|
|
|
@ -414,6 +414,29 @@ void btrfs_exclop_finish(struct btrfs_fs_info *fs_info)
|
||||||
sysfs_notify(&fs_info->fs_devices->fsid_kobj, NULL, "exclusive_operation");
|
sysfs_notify(&fs_info->fs_devices->fsid_kobj, NULL, "exclusive_operation");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void btrfs_exclop_balance(struct btrfs_fs_info *fs_info,
|
||||||
|
enum btrfs_exclusive_operation op)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case BTRFS_EXCLOP_BALANCE_PAUSED:
|
||||||
|
spin_lock(&fs_info->super_lock);
|
||||||
|
ASSERT(fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE ||
|
||||||
|
fs_info->exclusive_operation == BTRFS_EXCLOP_DEV_ADD);
|
||||||
|
fs_info->exclusive_operation = BTRFS_EXCLOP_BALANCE_PAUSED;
|
||||||
|
spin_unlock(&fs_info->super_lock);
|
||||||
|
break;
|
||||||
|
case BTRFS_EXCLOP_BALANCE:
|
||||||
|
spin_lock(&fs_info->super_lock);
|
||||||
|
ASSERT(fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE_PAUSED);
|
||||||
|
fs_info->exclusive_operation = BTRFS_EXCLOP_BALANCE;
|
||||||
|
spin_unlock(&fs_info->super_lock);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
btrfs_warn(fs_info,
|
||||||
|
"invalid exclop balance operation %d requested", op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
|
static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
|
||||||
{
|
{
|
||||||
struct inode *inode = file_inode(file);
|
struct inode *inode = file_inode(file);
|
||||||
|
@ -4056,6 +4079,7 @@ locked:
|
||||||
spin_lock(&fs_info->balance_lock);
|
spin_lock(&fs_info->balance_lock);
|
||||||
bctl->flags |= BTRFS_BALANCE_RESUME;
|
bctl->flags |= BTRFS_BALANCE_RESUME;
|
||||||
spin_unlock(&fs_info->balance_lock);
|
spin_unlock(&fs_info->balance_lock);
|
||||||
|
btrfs_exclop_balance(fs_info, BTRFS_EXCLOP_BALANCE);
|
||||||
|
|
||||||
goto do_balance;
|
goto do_balance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4394,8 +4394,10 @@ int btrfs_balance(struct btrfs_fs_info *fs_info,
|
||||||
ret = __btrfs_balance(fs_info);
|
ret = __btrfs_balance(fs_info);
|
||||||
|
|
||||||
mutex_lock(&fs_info->balance_mutex);
|
mutex_lock(&fs_info->balance_mutex);
|
||||||
if (ret == -ECANCELED && atomic_read(&fs_info->balance_pause_req))
|
if (ret == -ECANCELED && atomic_read(&fs_info->balance_pause_req)) {
|
||||||
btrfs_info(fs_info, "balance: paused");
|
btrfs_info(fs_info, "balance: paused");
|
||||||
|
btrfs_exclop_balance(fs_info, BTRFS_EXCLOP_BALANCE_PAUSED);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Balance can be canceled by:
|
* Balance can be canceled by:
|
||||||
*
|
*
|
||||||
|
@ -4471,6 +4473,10 @@ int btrfs_resume_balance_async(struct btrfs_fs_info *fs_info)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_lock(&fs_info->super_lock);
|
||||||
|
ASSERT(fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE_PAUSED);
|
||||||
|
fs_info->exclusive_operation = BTRFS_EXCLOP_BALANCE;
|
||||||
|
spin_unlock(&fs_info->super_lock);
|
||||||
/*
|
/*
|
||||||
* A ro->rw remount sequence should continue with the paused balance
|
* A ro->rw remount sequence should continue with the paused balance
|
||||||
* regardless of who pauses it, system or the user as of now, so set
|
* regardless of who pauses it, system or the user as of now, so set
|
||||||
|
@ -4539,7 +4545,7 @@ int btrfs_recover_balance(struct btrfs_fs_info *fs_info)
|
||||||
* is in a paused state and must have fs_info::balance_ctl properly
|
* is in a paused state and must have fs_info::balance_ctl properly
|
||||||
* set up.
|
* set up.
|
||||||
*/
|
*/
|
||||||
if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_BALANCE))
|
if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_BALANCE_PAUSED))
|
||||||
btrfs_warn(fs_info,
|
btrfs_warn(fs_info,
|
||||||
"balance: cannot set exclusive op status, resume manually");
|
"balance: cannot set exclusive op status, resume manually");
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue