diff options
-rw-r--r-- | fs/btrfs/ioctl.c | 48 | ||||
-rw-r--r-- | fs/btrfs/ioctl.h | 7 |
2 files changed, 52 insertions, 3 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index e54b5e50c927..9a71fec86152 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #include "backref.h" | 55 | #include "backref.h" |
56 | #include "rcu-string.h" | 56 | #include "rcu-string.h" |
57 | #include "send.h" | 57 | #include "send.h" |
58 | #include "dev-replace.h" | ||
58 | 59 | ||
59 | /* Mask out flags that are inappropriate for the given type of inode. */ | 60 | /* Mask out flags that are inappropriate for the given type of inode. */ |
60 | static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) | 61 | static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) |
@@ -3171,6 +3172,51 @@ static long btrfs_ioctl_get_dev_stats(struct btrfs_root *root, | |||
3171 | return ret; | 3172 | return ret; |
3172 | } | 3173 | } |
3173 | 3174 | ||
3175 | static long btrfs_ioctl_dev_replace(struct btrfs_root *root, void __user *arg) | ||
3176 | { | ||
3177 | struct btrfs_ioctl_dev_replace_args *p; | ||
3178 | int ret; | ||
3179 | |||
3180 | if (!capable(CAP_SYS_ADMIN)) | ||
3181 | return -EPERM; | ||
3182 | |||
3183 | p = memdup_user(arg, sizeof(*p)); | ||
3184 | if (IS_ERR(p)) | ||
3185 | return PTR_ERR(p); | ||
3186 | |||
3187 | switch (p->cmd) { | ||
3188 | case BTRFS_IOCTL_DEV_REPLACE_CMD_START: | ||
3189 | if (atomic_xchg( | ||
3190 | &root->fs_info->mutually_exclusive_operation_running, | ||
3191 | 1)) { | ||
3192 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | ||
3193 | ret = -EINPROGRESS; | ||
3194 | } else { | ||
3195 | ret = btrfs_dev_replace_start(root, p); | ||
3196 | atomic_set( | ||
3197 | &root->fs_info->mutually_exclusive_operation_running, | ||
3198 | 0); | ||
3199 | } | ||
3200 | break; | ||
3201 | case BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS: | ||
3202 | btrfs_dev_replace_status(root->fs_info, p); | ||
3203 | ret = 0; | ||
3204 | break; | ||
3205 | case BTRFS_IOCTL_DEV_REPLACE_CMD_CANCEL: | ||
3206 | ret = btrfs_dev_replace_cancel(root->fs_info, p); | ||
3207 | break; | ||
3208 | default: | ||
3209 | ret = -EINVAL; | ||
3210 | break; | ||
3211 | } | ||
3212 | |||
3213 | if (copy_to_user(arg, p, sizeof(*p))) | ||
3214 | ret = -EFAULT; | ||
3215 | |||
3216 | kfree(p); | ||
3217 | return ret; | ||
3218 | } | ||
3219 | |||
3174 | static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg) | 3220 | static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg) |
3175 | { | 3221 | { |
3176 | int ret = 0; | 3222 | int ret = 0; |
@@ -3826,6 +3872,8 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
3826 | return btrfs_ioctl_qgroup_create(root, argp); | 3872 | return btrfs_ioctl_qgroup_create(root, argp); |
3827 | case BTRFS_IOC_QGROUP_LIMIT: | 3873 | case BTRFS_IOC_QGROUP_LIMIT: |
3828 | return btrfs_ioctl_qgroup_limit(root, argp); | 3874 | return btrfs_ioctl_qgroup_limit(root, argp); |
3875 | case BTRFS_IOC_DEV_REPLACE: | ||
3876 | return btrfs_ioctl_dev_replace(root, argp); | ||
3829 | } | 3877 | } |
3830 | 3878 | ||
3831 | return -ENOTTY; | 3879 | return -ENOTTY; |
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h index 62006ba02719..dabca9cc8c2e 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h | |||
@@ -30,6 +30,8 @@ struct btrfs_ioctl_vol_args { | |||
30 | char name[BTRFS_PATH_NAME_MAX + 1]; | 30 | char name[BTRFS_PATH_NAME_MAX + 1]; |
31 | }; | 31 | }; |
32 | 32 | ||
33 | #define BTRFS_DEVICE_PATH_NAME_MAX 1024 | ||
34 | |||
33 | #define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0) | 35 | #define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0) |
34 | #define BTRFS_SUBVOL_RDONLY (1ULL << 1) | 36 | #define BTRFS_SUBVOL_RDONLY (1ULL << 1) |
35 | #define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2) | 37 | #define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2) |
@@ -127,10 +129,10 @@ struct btrfs_ioctl_scrub_args { | |||
127 | #define BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID 1 | 129 | #define BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID 1 |
128 | struct btrfs_ioctl_dev_replace_start_params { | 130 | struct btrfs_ioctl_dev_replace_start_params { |
129 | __u64 srcdevid; /* in, if 0, use srcdev_name instead */ | 131 | __u64 srcdevid; /* in, if 0, use srcdev_name instead */ |
130 | __u8 srcdev_name[BTRFS_PATH_NAME_MAX + 1]; /* in */ | ||
131 | __u8 tgtdev_name[BTRFS_PATH_NAME_MAX + 1]; /* in */ | ||
132 | __u64 cont_reading_from_srcdev_mode; /* in, see #define | 132 | __u64 cont_reading_from_srcdev_mode; /* in, see #define |
133 | * above */ | 133 | * above */ |
134 | __u8 srcdev_name[BTRFS_DEVICE_PATH_NAME_MAX + 1]; /* in */ | ||
135 | __u8 tgtdev_name[BTRFS_DEVICE_PATH_NAME_MAX + 1]; /* in */ | ||
134 | }; | 136 | }; |
135 | 137 | ||
136 | #define BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED 0 | 138 | #define BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED 0 |
@@ -165,7 +167,6 @@ struct btrfs_ioctl_dev_replace_args { | |||
165 | __u64 spare[64]; | 167 | __u64 spare[64]; |
166 | }; | 168 | }; |
167 | 169 | ||
168 | #define BTRFS_DEVICE_PATH_NAME_MAX 1024 | ||
169 | struct btrfs_ioctl_dev_info_args { | 170 | struct btrfs_ioctl_dev_info_args { |
170 | __u64 devid; /* in/out */ | 171 | __u64 devid; /* in/out */ |
171 | __u8 uuid[BTRFS_UUID_SIZE]; /* in/out */ | 172 | __u8 uuid[BTRFS_UUID_SIZE]; /* in/out */ |