btrfs: track exclusive filesystem operation in flags
There are several operations, usually started from ioctls, that cannot run concurrently. The status is tracked in mutually_exclusive_operation_running as an atomic_t. We can easily track the status as one of the per-filesystem flag bits with same synchronization guarantees. The conversion replaces: * atomic_xchg(..., 1) -> test_and_set_bit(FLAG, ...) * atomic_set(..., 0) -> clear_bit(FLAG, ...) Reviewed-by: Anand Jain <anand.jain@oracle.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
48a89bc4f2
commit
171938e528
|
@ -705,6 +705,11 @@ struct btrfs_delayed_root;
|
|||
#define BTRFS_FS_BTREE_ERR 11
|
||||
#define BTRFS_FS_LOG1_ERR 12
|
||||
#define BTRFS_FS_LOG2_ERR 13
|
||||
/*
|
||||
* Indicate that a whole-filesystem exclusive operation is running
|
||||
* (device replace, resize, device add/delete, balance)
|
||||
*/
|
||||
#define BTRFS_FS_EXCL_OP 14
|
||||
|
||||
struct btrfs_fs_info {
|
||||
u8 fsid[BTRFS_FSID_SIZE];
|
||||
|
@ -1070,8 +1075,6 @@ struct btrfs_fs_info {
|
|||
/* device replace state */
|
||||
struct btrfs_dev_replace dev_replace;
|
||||
|
||||
atomic_t mutually_exclusive_operation_running;
|
||||
|
||||
struct percpu_counter bio_counter;
|
||||
wait_queue_head_t replace_wait;
|
||||
|
||||
|
|
|
@ -784,8 +784,7 @@ int btrfs_resume_dev_replace_async(struct btrfs_fs_info *fs_info)
|
|||
}
|
||||
btrfs_dev_replace_unlock(dev_replace, 1);
|
||||
|
||||
WARN_ON(atomic_xchg(
|
||||
&fs_info->mutually_exclusive_operation_running, 1));
|
||||
WARN_ON(test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags));
|
||||
task = kthread_run(btrfs_dev_replace_kthread, fs_info, "btrfs-devrepl");
|
||||
return PTR_ERR_OR_ZERO(task);
|
||||
}
|
||||
|
@ -814,7 +813,7 @@ static int btrfs_dev_replace_kthread(void *data)
|
|||
(unsigned int)progress);
|
||||
}
|
||||
btrfs_dev_replace_continue_on_mount(fs_info);
|
||||
atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
|
||||
clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1504,7 +1504,7 @@ static noinline int btrfs_ioctl_resize(struct file *file,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) {
|
||||
if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
|
||||
mnt_drop_write_file(file);
|
||||
return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
|
||||
}
|
||||
|
@ -1619,7 +1619,7 @@ out_free:
|
|||
kfree(vol_args);
|
||||
out:
|
||||
mutex_unlock(&fs_info->volume_mutex);
|
||||
atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
|
||||
clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
|
||||
mnt_drop_write_file(file);
|
||||
return ret;
|
||||
}
|
||||
|
@ -2661,7 +2661,7 @@ static long btrfs_ioctl_add_dev(struct btrfs_fs_info *fs_info, void __user *arg)
|
|||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1))
|
||||
if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags))
|
||||
return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
|
||||
|
||||
mutex_lock(&fs_info->volume_mutex);
|
||||
|
@ -2680,7 +2680,7 @@ static long btrfs_ioctl_add_dev(struct btrfs_fs_info *fs_info, void __user *arg)
|
|||
kfree(vol_args);
|
||||
out:
|
||||
mutex_unlock(&fs_info->volume_mutex);
|
||||
atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
|
||||
clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2708,7 +2708,7 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg)
|
|||
if (vol_args->flags & ~BTRFS_VOL_ARG_V2_FLAGS_SUPPORTED)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) {
|
||||
if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
|
||||
ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
|
||||
goto out;
|
||||
}
|
||||
|
@ -2721,7 +2721,7 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg)
|
|||
ret = btrfs_rm_device(fs_info, vol_args->name, 0);
|
||||
}
|
||||
mutex_unlock(&fs_info->volume_mutex);
|
||||
atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
|
||||
clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
|
||||
|
||||
if (!ret) {
|
||||
if (vol_args->flags & BTRFS_DEVICE_SPEC_BY_ID)
|
||||
|
@ -2752,7 +2752,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) {
|
||||
if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
|
||||
ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
|
||||
goto out_drop_write;
|
||||
}
|
||||
|
@ -2772,7 +2772,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
|
|||
btrfs_info(fs_info, "disk deleted %s", vol_args->name);
|
||||
kfree(vol_args);
|
||||
out:
|
||||
atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
|
||||
clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
|
||||
out_drop_write:
|
||||
mnt_drop_write_file(file);
|
||||
|
||||
|
@ -4442,13 +4442,11 @@ static long btrfs_ioctl_dev_replace(struct btrfs_fs_info *fs_info,
|
|||
ret = -EROFS;
|
||||
goto out;
|
||||
}
|
||||
if (atomic_xchg(
|
||||
&fs_info->mutually_exclusive_operation_running, 1)) {
|
||||
if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
|
||||
ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
|
||||
} else {
|
||||
ret = btrfs_dev_replace_by_ioctl(fs_info, p);
|
||||
atomic_set(
|
||||
&fs_info->mutually_exclusive_operation_running, 0);
|
||||
clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
|
||||
}
|
||||
break;
|
||||
case BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS:
|
||||
|
@ -4643,7 +4641,7 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
|
|||
return ret;
|
||||
|
||||
again:
|
||||
if (!atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) {
|
||||
if (!test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
|
||||
mutex_lock(&fs_info->volume_mutex);
|
||||
mutex_lock(&fs_info->balance_mutex);
|
||||
need_unlock = true;
|
||||
|
@ -4689,7 +4687,7 @@ again:
|
|||
}
|
||||
|
||||
locked:
|
||||
BUG_ON(!atomic_read(&fs_info->mutually_exclusive_operation_running));
|
||||
BUG_ON(!test_bit(BTRFS_FS_EXCL_OP, &fs_info->flags));
|
||||
|
||||
if (arg) {
|
||||
bargs = memdup_user(arg, sizeof(*bargs));
|
||||
|
@ -4745,11 +4743,10 @@ locked:
|
|||
|
||||
do_balance:
|
||||
/*
|
||||
* Ownership of bctl and mutually_exclusive_operation_running
|
||||
* Ownership of bctl and filesystem flag BTRFS_FS_EXCL_OP
|
||||
* goes to to btrfs_balance. bctl is freed in __cancel_balance,
|
||||
* or, if restriper was paused all the way until unmount, in
|
||||
* free_fs_info. mutually_exclusive_operation_running is
|
||||
* cleared in __cancel_balance.
|
||||
* free_fs_info. The flag is cleared in __cancel_balance.
|
||||
*/
|
||||
need_unlock = false;
|
||||
|
||||
|
@ -4769,7 +4766,7 @@ out_unlock:
|
|||
mutex_unlock(&fs_info->balance_mutex);
|
||||
mutex_unlock(&fs_info->volume_mutex);
|
||||
if (need_unlock)
|
||||
atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
|
||||
clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
|
||||
out:
|
||||
mnt_drop_write_file(file);
|
||||
return ret;
|
||||
|
|
|
@ -3761,7 +3761,7 @@ static void __cancel_balance(struct btrfs_fs_info *fs_info)
|
|||
if (ret)
|
||||
btrfs_handle_fs_error(fs_info, ret, NULL);
|
||||
|
||||
atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
|
||||
clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
|
||||
}
|
||||
|
||||
/* Non-zero return value signifies invalidity */
|
||||
|
@ -3941,7 +3941,7 @@ out:
|
|||
__cancel_balance(fs_info);
|
||||
else {
|
||||
kfree(bctl);
|
||||
atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
|
||||
clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -4031,7 +4031,7 @@ int btrfs_recover_balance(struct btrfs_fs_info *fs_info)
|
|||
btrfs_balance_sys(leaf, item, &disk_bargs);
|
||||
btrfs_disk_balance_args_to_cpu(&bctl->sys, &disk_bargs);
|
||||
|
||||
WARN_ON(atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1));
|
||||
WARN_ON(test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags));
|
||||
|
||||
mutex_lock(&fs_info->volume_mutex);
|
||||
mutex_lock(&fs_info->balance_mutex);
|
||||
|
|
Loading…
Reference in New Issue