Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 171938e5 authored by David Sterba's avatar David Sterba
Browse files

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: default avatarAnand Jain <anand.jain@oracle.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 48a89bc4
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -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;

+2 −3
Original line number Diff line number Diff line
@@ -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;
}
+15 −18
Original line number Diff line number Diff line
@@ -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 @@ static noinline int btrfs_ioctl_resize(struct file *file,
	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 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
	}

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 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)

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 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
	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;
+3 −3
Original line number Diff line number Diff line
@@ -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 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
		__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);