summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
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 /fs/btrfs/ioctl.c
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>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c48
1 files changed, 48 insertions, 0 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;