aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Sterba <dsterba@suse.com>2017-03-28 08:44:21 -0400
committerDavid Sterba <dsterba@suse.com>2017-04-18 08:07:25 -0400
commit171938e528079deced3226a17dcab12121312a64 (patch)
treed49869102dade6b05e5736b0df6fd48301e43bb7
parent48a89bc4f2ceab87bc858a8eb189636b09c846a7 (diff)
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>
-rw-r--r--fs/btrfs/ctree.h7
-rw-r--r--fs/btrfs/dev-replace.c5
-rw-r--r--fs/btrfs/ioctl.c33
-rw-r--r--fs/btrfs/volumes.c6
4 files changed, 25 insertions, 26 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index e9d77115e695..70631d773669 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -705,6 +705,11 @@ struct btrfs_delayed_root;
705#define BTRFS_FS_BTREE_ERR 11 705#define BTRFS_FS_BTREE_ERR 11
706#define BTRFS_FS_LOG1_ERR 12 706#define BTRFS_FS_LOG1_ERR 12
707#define BTRFS_FS_LOG2_ERR 13 707#define BTRFS_FS_LOG2_ERR 13
708/*
709 * Indicate that a whole-filesystem exclusive operation is running
710 * (device replace, resize, device add/delete, balance)
711 */
712#define BTRFS_FS_EXCL_OP 14
708 713
709struct btrfs_fs_info { 714struct btrfs_fs_info {
710 u8 fsid[BTRFS_FSID_SIZE]; 715 u8 fsid[BTRFS_FSID_SIZE];
@@ -1070,8 +1075,6 @@ struct btrfs_fs_info {
1070 /* device replace state */ 1075 /* device replace state */
1071 struct btrfs_dev_replace dev_replace; 1076 struct btrfs_dev_replace dev_replace;
1072 1077
1073 atomic_t mutually_exclusive_operation_running;
1074
1075 struct percpu_counter bio_counter; 1078 struct percpu_counter bio_counter;
1076 wait_queue_head_t replace_wait; 1079 wait_queue_head_t replace_wait;
1077 1080
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index e653921f05d9..de7b2c897fe0 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -784,8 +784,7 @@ int btrfs_resume_dev_replace_async(struct btrfs_fs_info *fs_info)
784 } 784 }
785 btrfs_dev_replace_unlock(dev_replace, 1); 785 btrfs_dev_replace_unlock(dev_replace, 1);
786 786
787 WARN_ON(atomic_xchg( 787 WARN_ON(test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags));
788 &fs_info->mutually_exclusive_operation_running, 1));
789 task = kthread_run(btrfs_dev_replace_kthread, fs_info, "btrfs-devrepl"); 788 task = kthread_run(btrfs_dev_replace_kthread, fs_info, "btrfs-devrepl");
790 return PTR_ERR_OR_ZERO(task); 789 return PTR_ERR_OR_ZERO(task);
791} 790}
@@ -814,7 +813,7 @@ static int btrfs_dev_replace_kthread(void *data)
814 (unsigned int)progress); 813 (unsigned int)progress);
815 } 814 }
816 btrfs_dev_replace_continue_on_mount(fs_info); 815 btrfs_dev_replace_continue_on_mount(fs_info);
817 atomic_set(&fs_info->mutually_exclusive_operation_running, 0); 816 clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
818 817
819 return 0; 818 return 0;
820} 819}
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index dabfc7ac48a6..a29dc3fd7152 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1504,7 +1504,7 @@ static noinline int btrfs_ioctl_resize(struct file *file,
1504 if (ret) 1504 if (ret)
1505 return ret; 1505 return ret;
1506 1506
1507 if (atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) { 1507 if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
1508 mnt_drop_write_file(file); 1508 mnt_drop_write_file(file);
1509 return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; 1509 return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
1510 } 1510 }
@@ -1619,7 +1619,7 @@ out_free:
1619 kfree(vol_args); 1619 kfree(vol_args);
1620out: 1620out:
1621 mutex_unlock(&fs_info->volume_mutex); 1621 mutex_unlock(&fs_info->volume_mutex);
1622 atomic_set(&fs_info->mutually_exclusive_operation_running, 0); 1622 clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
1623 mnt_drop_write_file(file); 1623 mnt_drop_write_file(file);
1624 return ret; 1624 return ret;
1625} 1625}
@@ -2661,7 +2661,7 @@ static long btrfs_ioctl_add_dev(struct btrfs_fs_info *fs_info, void __user *arg)
2661 if (!capable(CAP_SYS_ADMIN)) 2661 if (!capable(CAP_SYS_ADMIN))
2662 return -EPERM; 2662 return -EPERM;
2663 2663
2664 if (atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) 2664 if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags))
2665 return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; 2665 return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
2666 2666
2667 mutex_lock(&fs_info->volume_mutex); 2667 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)
2680 kfree(vol_args); 2680 kfree(vol_args);
2681out: 2681out:
2682 mutex_unlock(&fs_info->volume_mutex); 2682 mutex_unlock(&fs_info->volume_mutex);
2683 atomic_set(&fs_info->mutually_exclusive_operation_running, 0); 2683 clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
2684 return ret; 2684 return ret;
2685} 2685}
2686 2686
@@ -2708,7 +2708,7 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg)
2708 if (vol_args->flags & ~BTRFS_VOL_ARG_V2_FLAGS_SUPPORTED) 2708 if (vol_args->flags & ~BTRFS_VOL_ARG_V2_FLAGS_SUPPORTED)
2709 return -EOPNOTSUPP; 2709 return -EOPNOTSUPP;
2710 2710
2711 if (atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) { 2711 if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
2712 ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; 2712 ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
2713 goto out; 2713 goto out;
2714 } 2714 }
@@ -2721,7 +2721,7 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg)
2721 ret = btrfs_rm_device(fs_info, vol_args->name, 0); 2721 ret = btrfs_rm_device(fs_info, vol_args->name, 0);
2722 } 2722 }
2723 mutex_unlock(&fs_info->volume_mutex); 2723 mutex_unlock(&fs_info->volume_mutex);
2724 atomic_set(&fs_info->mutually_exclusive_operation_running, 0); 2724 clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
2725 2725
2726 if (!ret) { 2726 if (!ret) {
2727 if (vol_args->flags & BTRFS_DEVICE_SPEC_BY_ID) 2727 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)
2752 if (ret) 2752 if (ret)
2753 return ret; 2753 return ret;
2754 2754
2755 if (atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) { 2755 if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
2756 ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; 2756 ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
2757 goto out_drop_write; 2757 goto out_drop_write;
2758 } 2758 }
@@ -2772,7 +2772,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
2772 btrfs_info(fs_info, "disk deleted %s", vol_args->name); 2772 btrfs_info(fs_info, "disk deleted %s", vol_args->name);
2773 kfree(vol_args); 2773 kfree(vol_args);
2774out: 2774out:
2775 atomic_set(&fs_info->mutually_exclusive_operation_running, 0); 2775 clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
2776out_drop_write: 2776out_drop_write:
2777 mnt_drop_write_file(file); 2777 mnt_drop_write_file(file);
2778 2778
@@ -4442,13 +4442,11 @@ static long btrfs_ioctl_dev_replace(struct btrfs_fs_info *fs_info,
4442 ret = -EROFS; 4442 ret = -EROFS;
4443 goto out; 4443 goto out;
4444 } 4444 }
4445 if (atomic_xchg( 4445 if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
4446 &fs_info->mutually_exclusive_operation_running, 1)) {
4447 ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; 4446 ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
4448 } else { 4447 } else {
4449 ret = btrfs_dev_replace_by_ioctl(fs_info, p); 4448 ret = btrfs_dev_replace_by_ioctl(fs_info, p);
4450 atomic_set( 4449 clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
4451 &fs_info->mutually_exclusive_operation_running, 0);
4452 } 4450 }
4453 break; 4451 break;
4454 case BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS: 4452 case BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS:
@@ -4643,7 +4641,7 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
4643 return ret; 4641 return ret;
4644 4642
4645again: 4643again:
4646 if (!atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) { 4644 if (!test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
4647 mutex_lock(&fs_info->volume_mutex); 4645 mutex_lock(&fs_info->volume_mutex);
4648 mutex_lock(&fs_info->balance_mutex); 4646 mutex_lock(&fs_info->balance_mutex);
4649 need_unlock = true; 4647 need_unlock = true;
@@ -4689,7 +4687,7 @@ again:
4689 } 4687 }
4690 4688
4691locked: 4689locked:
4692 BUG_ON(!atomic_read(&fs_info->mutually_exclusive_operation_running)); 4690 BUG_ON(!test_bit(BTRFS_FS_EXCL_OP, &fs_info->flags));
4693 4691
4694 if (arg) { 4692 if (arg) {
4695 bargs = memdup_user(arg, sizeof(*bargs)); 4693 bargs = memdup_user(arg, sizeof(*bargs));
@@ -4745,11 +4743,10 @@ locked:
4745 4743
4746do_balance: 4744do_balance:
4747 /* 4745 /*
4748 * Ownership of bctl and mutually_exclusive_operation_running 4746 * Ownership of bctl and filesystem flag BTRFS_FS_EXCL_OP
4749 * goes to to btrfs_balance. bctl is freed in __cancel_balance, 4747 * goes to to btrfs_balance. bctl is freed in __cancel_balance,
4750 * or, if restriper was paused all the way until unmount, in 4748 * or, if restriper was paused all the way until unmount, in
4751 * free_fs_info. mutually_exclusive_operation_running is 4749 * free_fs_info. The flag is cleared in __cancel_balance.
4752 * cleared in __cancel_balance.
4753 */ 4750 */
4754 need_unlock = false; 4751 need_unlock = false;
4755 4752
@@ -4769,7 +4766,7 @@ out_unlock:
4769 mutex_unlock(&fs_info->balance_mutex); 4766 mutex_unlock(&fs_info->balance_mutex);
4770 mutex_unlock(&fs_info->volume_mutex); 4767 mutex_unlock(&fs_info->volume_mutex);
4771 if (need_unlock) 4768 if (need_unlock)
4772 atomic_set(&fs_info->mutually_exclusive_operation_running, 0); 4769 clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
4773out: 4770out:
4774 mnt_drop_write_file(file); 4771 mnt_drop_write_file(file);
4775 return ret; 4772 return ret;
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index df50a63bbc3f..2e425a909125 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -3761,7 +3761,7 @@ static void __cancel_balance(struct btrfs_fs_info *fs_info)
3761 if (ret) 3761 if (ret)
3762 btrfs_handle_fs_error(fs_info, ret, NULL); 3762 btrfs_handle_fs_error(fs_info, ret, NULL);
3763 3763
3764 atomic_set(&fs_info->mutually_exclusive_operation_running, 0); 3764 clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
3765} 3765}
3766 3766
3767/* Non-zero return value signifies invalidity */ 3767/* Non-zero return value signifies invalidity */
@@ -3941,7 +3941,7 @@ out:
3941 __cancel_balance(fs_info); 3941 __cancel_balance(fs_info);
3942 else { 3942 else {
3943 kfree(bctl); 3943 kfree(bctl);
3944 atomic_set(&fs_info->mutually_exclusive_operation_running, 0); 3944 clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
3945 } 3945 }
3946 return ret; 3946 return ret;
3947} 3947}
@@ -4031,7 +4031,7 @@ int btrfs_recover_balance(struct btrfs_fs_info *fs_info)
4031 btrfs_balance_sys(leaf, item, &disk_bargs); 4031 btrfs_balance_sys(leaf, item, &disk_bargs);
4032 btrfs_disk_balance_args_to_cpu(&bctl->sys, &disk_bargs); 4032 btrfs_disk_balance_args_to_cpu(&bctl->sys, &disk_bargs);
4033 4033
4034 WARN_ON(atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)); 4034 WARN_ON(test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags));
4035 4035
4036 mutex_lock(&fs_info->volume_mutex); 4036 mutex_lock(&fs_info->volume_mutex);
4037 mutex_lock(&fs_info->balance_mutex); 4037 mutex_lock(&fs_info->balance_mutex);