aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Behrens <sbehrens@giantdisaster.de>2012-11-06 09:08:53 -0500
committerChris Mason <chris.mason@fusionio.com>2012-12-16 20:46:06 -0500
commit3f6bcfbd4149875662773eb40a62294cddf215d4 (patch)
tree0a53729e4e0a2427370a7ab10e12c36b21b827fd
parentad6d620e2a5704f6bf3a39c92a75aad962c51cb3 (diff)
Btrfs: add support for device replace ioctls
This is the commit that allows to start the device replace procedure. An ioctl() interface is added that supports starting and canceling the device replace procedure, and to retrieve the status and progress. Signed-off-by: Stefan Behrens <sbehrens@giantdisaster.de> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
-rw-r--r--fs/btrfs/ioctl.c48
-rw-r--r--fs/btrfs/ioctl.h7
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. */
60static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) 61static 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
3175static 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
3174static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg) 3220static 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
128struct btrfs_ioctl_dev_replace_start_params { 130struct 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
169struct btrfs_ioctl_dev_info_args { 170struct 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 */