Btrfs: add support for device replace ioctls
authorStefan Behrens <sbehrens@giantdisaster.de>
Tue, 6 Nov 2012 14:08:53 +0000 (15:08 +0100)
committerChris Mason <chris.mason@fusionio.com>
Mon, 17 Dec 2012 01:46:06 +0000 (20:46 -0500)
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>
fs/btrfs/ioctl.c
fs/btrfs/ioctl.h

index e54b5e50c92715dc1c60376af9c3bbb9ec0ab7e2..9a71fec86152fc3fe6a3847592a726b8fa6e1136 100644 (file)
@@ -55,6 +55,7 @@
 #include "backref.h"
 #include "rcu-string.h"
 #include "send.h"
+#include "dev-replace.h"
 
 /* Mask out flags that are inappropriate for the given type of inode. */
 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,
        return ret;
 }
 
+static long btrfs_ioctl_dev_replace(struct btrfs_root *root, void __user *arg)
+{
+       struct btrfs_ioctl_dev_replace_args *p;
+       int ret;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       p = memdup_user(arg, sizeof(*p));
+       if (IS_ERR(p))
+               return PTR_ERR(p);
+
+       switch (p->cmd) {
+       case BTRFS_IOCTL_DEV_REPLACE_CMD_START:
+               if (atomic_xchg(
+                       &root->fs_info->mutually_exclusive_operation_running,
+                       1)) {
+                       pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
+                       ret = -EINPROGRESS;
+               } else {
+                       ret = btrfs_dev_replace_start(root, p);
+                       atomic_set(
+                        &root->fs_info->mutually_exclusive_operation_running,
+                        0);
+               }
+               break;
+       case BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS:
+               btrfs_dev_replace_status(root->fs_info, p);
+               ret = 0;
+               break;
+       case BTRFS_IOCTL_DEV_REPLACE_CMD_CANCEL:
+               ret = btrfs_dev_replace_cancel(root->fs_info, p);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       if (copy_to_user(arg, p, sizeof(*p)))
+               ret = -EFAULT;
+
+       kfree(p);
+       return ret;
+}
+
 static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg)
 {
        int ret = 0;
@@ -3826,6 +3872,8 @@ long btrfs_ioctl(struct file *file, unsigned int
                return btrfs_ioctl_qgroup_create(root, argp);
        case BTRFS_IOC_QGROUP_LIMIT:
                return btrfs_ioctl_qgroup_limit(root, argp);
+       case BTRFS_IOC_DEV_REPLACE:
+               return btrfs_ioctl_dev_replace(root, argp);
        }
 
        return -ENOTTY;
index 62006ba0271931bef31637e8b0059d0f3da2d51c..dabca9cc8c2ebe72a7c440d2147e985bcc6b3c2c 100644 (file)
@@ -30,6 +30,8 @@ struct btrfs_ioctl_vol_args {
        char name[BTRFS_PATH_NAME_MAX + 1];
 };
 
+#define BTRFS_DEVICE_PATH_NAME_MAX 1024
+
 #define BTRFS_SUBVOL_CREATE_ASYNC      (1ULL << 0)
 #define BTRFS_SUBVOL_RDONLY            (1ULL << 1)
 #define BTRFS_SUBVOL_QGROUP_INHERIT    (1ULL << 2)
@@ -127,10 +129,10 @@ struct btrfs_ioctl_scrub_args {
 #define BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID    1
 struct btrfs_ioctl_dev_replace_start_params {
        __u64 srcdevid; /* in, if 0, use srcdev_name instead */
-       __u8 srcdev_name[BTRFS_PATH_NAME_MAX + 1];      /* in */
-       __u8 tgtdev_name[BTRFS_PATH_NAME_MAX + 1];      /* in */
        __u64 cont_reading_from_srcdev_mode;    /* in, see #define
                                                 * above */
+       __u8 srcdev_name[BTRFS_DEVICE_PATH_NAME_MAX + 1];       /* in */
+       __u8 tgtdev_name[BTRFS_DEVICE_PATH_NAME_MAX + 1];       /* in */
 };
 
 #define BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED    0
@@ -165,7 +167,6 @@ struct btrfs_ioctl_dev_replace_args {
        __u64 spare[64];
 };
 
-#define BTRFS_DEVICE_PATH_NAME_MAX 1024
 struct btrfs_ioctl_dev_info_args {
        __u64 devid;                            /* in/out */
        __u8 uuid[BTRFS_UUID_SIZE];             /* in/out */