diff options
| -rw-r--r-- | fs/btrfs/scrub.c | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index edad1a40f797..367ab0911c01 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
| @@ -3835,13 +3835,18 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, | |||
| 3835 | return -EINVAL; | 3835 | return -EINVAL; |
| 3836 | } | 3836 | } |
| 3837 | 3837 | ||
| 3838 | /* Allocate outside of device_list_mutex */ | ||
| 3839 | sctx = scrub_setup_ctx(fs_info, is_dev_replace); | ||
| 3840 | if (IS_ERR(sctx)) | ||
| 3841 | return PTR_ERR(sctx); | ||
| 3838 | 3842 | ||
| 3839 | mutex_lock(&fs_info->fs_devices->device_list_mutex); | 3843 | mutex_lock(&fs_info->fs_devices->device_list_mutex); |
| 3840 | dev = btrfs_find_device(fs_info, devid, NULL, NULL); | 3844 | dev = btrfs_find_device(fs_info, devid, NULL, NULL); |
| 3841 | if (!dev || (test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state) && | 3845 | if (!dev || (test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state) && |
| 3842 | !is_dev_replace)) { | 3846 | !is_dev_replace)) { |
| 3843 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); | 3847 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); |
| 3844 | return -ENODEV; | 3848 | ret = -ENODEV; |
| 3849 | goto out_free_ctx; | ||
| 3845 | } | 3850 | } |
| 3846 | 3851 | ||
| 3847 | if (!is_dev_replace && !readonly && | 3852 | if (!is_dev_replace && !readonly && |
| @@ -3849,7 +3854,8 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, | |||
| 3849 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); | 3854 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); |
| 3850 | btrfs_err_in_rcu(fs_info, "scrub: device %s is not writable", | 3855 | btrfs_err_in_rcu(fs_info, "scrub: device %s is not writable", |
| 3851 | rcu_str_deref(dev->name)); | 3856 | rcu_str_deref(dev->name)); |
| 3852 | return -EROFS; | 3857 | ret = -EROFS; |
| 3858 | goto out_free_ctx; | ||
| 3853 | } | 3859 | } |
| 3854 | 3860 | ||
| 3855 | mutex_lock(&fs_info->scrub_lock); | 3861 | mutex_lock(&fs_info->scrub_lock); |
| @@ -3857,7 +3863,8 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, | |||
| 3857 | test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &dev->dev_state)) { | 3863 | test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &dev->dev_state)) { |
| 3858 | mutex_unlock(&fs_info->scrub_lock); | 3864 | mutex_unlock(&fs_info->scrub_lock); |
| 3859 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); | 3865 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); |
| 3860 | return -EIO; | 3866 | ret = -EIO; |
| 3867 | goto out_free_ctx; | ||
| 3861 | } | 3868 | } |
| 3862 | 3869 | ||
| 3863 | down_read(&fs_info->dev_replace.rwsem); | 3870 | down_read(&fs_info->dev_replace.rwsem); |
| @@ -3867,7 +3874,8 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, | |||
| 3867 | up_read(&fs_info->dev_replace.rwsem); | 3874 | up_read(&fs_info->dev_replace.rwsem); |
| 3868 | mutex_unlock(&fs_info->scrub_lock); | 3875 | mutex_unlock(&fs_info->scrub_lock); |
| 3869 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); | 3876 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); |
| 3870 | return -EINPROGRESS; | 3877 | ret = -EINPROGRESS; |
| 3878 | goto out_free_ctx; | ||
| 3871 | } | 3879 | } |
| 3872 | up_read(&fs_info->dev_replace.rwsem); | 3880 | up_read(&fs_info->dev_replace.rwsem); |
| 3873 | 3881 | ||
| @@ -3875,16 +3883,9 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, | |||
| 3875 | if (ret) { | 3883 | if (ret) { |
| 3876 | mutex_unlock(&fs_info->scrub_lock); | 3884 | mutex_unlock(&fs_info->scrub_lock); |
| 3877 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); | 3885 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); |
| 3878 | return ret; | 3886 | goto out_free_ctx; |
| 3879 | } | 3887 | } |
| 3880 | 3888 | ||
| 3881 | sctx = scrub_setup_ctx(fs_info, is_dev_replace); | ||
| 3882 | if (IS_ERR(sctx)) { | ||
| 3883 | mutex_unlock(&fs_info->scrub_lock); | ||
| 3884 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); | ||
| 3885 | scrub_workers_put(fs_info); | ||
| 3886 | return PTR_ERR(sctx); | ||
| 3887 | } | ||
| 3888 | sctx->readonly = readonly; | 3889 | sctx->readonly = readonly; |
| 3889 | dev->scrub_ctx = sctx; | 3890 | dev->scrub_ctx = sctx; |
| 3890 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); | 3891 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); |
| @@ -3938,6 +3939,11 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, | |||
| 3938 | scrub_put_ctx(sctx); | 3939 | scrub_put_ctx(sctx); |
| 3939 | 3940 | ||
| 3940 | return ret; | 3941 | return ret; |
| 3942 | |||
| 3943 | out_free_ctx: | ||
| 3944 | scrub_free_ctx(sctx); | ||
| 3945 | |||
| 3946 | return ret; | ||
| 3941 | } | 3947 | } |
| 3942 | 3948 | ||
| 3943 | void btrfs_scrub_pause(struct btrfs_fs_info *fs_info) | 3949 | void btrfs_scrub_pause(struct btrfs_fs_info *fs_info) |
