btrfs: introduce btrfs_try_lock_balance

This function contains the factored out locking sequence of
btrfs_ioctl_balance. Having this piece of code separate helps to
simplify btrfs_ioctl_balance which has too complicated.  This will be
used in the next patch to streamline the logic in btrfs_ioctl_balance.

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:
Nikolay Borisov 2022-05-03 11:36:36 +03:00 committed by David Sterba
parent 1e87770cb3
commit 7fb10ed89e

View File

@ -4355,6 +4355,72 @@ void btrfs_update_ioctl_balance_args(struct btrfs_fs_info *fs_info,
spin_unlock(&fs_info->balance_lock);
}
/**
* Try to acquire fs_info::balance_mutex as well as set BTRFS_EXLCOP_BALANCE as
* required.
*
* @fs_info: the filesystem
* @excl_acquired: ptr to boolean value which is set to false in case balance
* is being resumed
*
* Return 0 on success in which case both fs_info::balance is acquired as well
* as exclusive ops are blocked. In case of failure return an error code.
*/
static int btrfs_try_lock_balance(struct btrfs_fs_info *fs_info, bool *excl_acquired)
{
int ret;
/*
* Exclusive operation is locked. Three possibilities:
* (1) some other op is running
* (2) balance is running
* (3) balance is paused -- special case (think resume)
*/
while (1) {
if (btrfs_exclop_start(fs_info, BTRFS_EXCLOP_BALANCE)) {
*excl_acquired = true;
mutex_lock(&fs_info->balance_mutex);
return 0;
}
mutex_lock(&fs_info->balance_mutex);
if (fs_info->balance_ctl) {
/* This is either (2) or (3) */
if (test_bit(BTRFS_FS_BALANCE_RUNNING, &fs_info->flags)) {
/* This is (2) */
ret = -EINPROGRESS;
goto out_failure;
} else {
mutex_unlock(&fs_info->balance_mutex);
/*
* Lock released to allow other waiters to
* continue, we'll reexamine the status again.
*/
mutex_lock(&fs_info->balance_mutex);
if (fs_info->balance_ctl &&
!test_bit(BTRFS_FS_BALANCE_RUNNING, &fs_info->flags)) {
/* This is (3) */
*excl_acquired = false;
return 0;
}
}
} else {
/* This is (1) */
ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
goto out_failure;
}
mutex_unlock(&fs_info->balance_mutex);
}
out_failure:
mutex_unlock(&fs_info->balance_mutex);
*excl_acquired = false;
return ret;
}
static long btrfs_ioctl_balance(struct file *file, void __user *arg)
{
struct btrfs_root *root = BTRFS_I(file_inode(file))->root;