diff options
author | David Sterba <dsterba@suse.com> | 2017-03-28 08:44:21 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2017-04-18 08:07:25 -0400 |
commit | 171938e528079deced3226a17dcab12121312a64 (patch) | |
tree | d49869102dade6b05e5736b0df6fd48301e43bb7 | |
parent | 48a89bc4f2ceab87bc858a8eb189636b09c846a7 (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.h | 7 | ||||
-rw-r--r-- | fs/btrfs/dev-replace.c | 5 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 33 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 6 |
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 | ||
709 | struct btrfs_fs_info { | 714 | struct 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); |
1620 | out: | 1620 | out: |
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); |
2681 | out: | 2681 | out: |
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); |
2774 | out: | 2774 | out: |
2775 | atomic_set(&fs_info->mutually_exclusive_operation_running, 0); | 2775 | clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags); |
2776 | out_drop_write: | 2776 | out_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 | ||
4645 | again: | 4643 | again: |
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 | ||
4691 | locked: | 4689 | locked: |
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 | ||
4746 | do_balance: | 4744 | do_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); |
4773 | out: | 4770 | out: |
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); |