summaryrefslogtreecommitdiff
path: root/libbcache/chardev.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcache/chardev.c')
-rw-r--r--libbcache/chardev.c189
1 files changed, 118 insertions, 71 deletions
diff --git a/libbcache/chardev.c b/libbcache/chardev.c
index d98a3ee1..c764a9d0 100644
--- a/libbcache/chardev.c
+++ b/libbcache/chardev.c
@@ -24,6 +24,9 @@ static long bch_ioctl_assemble(struct bch_ioctl_assemble __user *user_arg)
if (copy_from_user(&arg, user_arg, sizeof(arg)))
return -EFAULT;
+ if (arg.flags || arg.pad)
+ return -EINVAL;
+
user_devs = kmalloc_array(arg.nr_devs, sizeof(u64), GFP_KERNEL);
if (!devs)
return -ENOMEM;
@@ -69,6 +72,9 @@ static long bch_ioctl_incremental(struct bch_ioctl_incremental __user *user_arg)
if (copy_from_user(&arg, user_arg, sizeof(arg)))
return -EFAULT;
+ if (arg.flags || arg.pad)
+ return -EINVAL;
+
path = strndup_user((const char __user *)(unsigned long) arg.dev, PATH_MAX);
if (!path)
return -ENOMEM;
@@ -96,30 +102,31 @@ static long bch_global_ioctl(unsigned cmd, void __user *arg)
}
}
-static long bch_ioctl_stop(struct bch_fs *c)
+static long bch_ioctl_query_uuid(struct bch_fs *c,
+ struct bch_ioctl_query_uuid __user *user_arg)
{
- bch_fs_stop_async(c);
- return 0;
+ return copy_to_user(&user_arg->uuid,
+ &c->sb.user_uuid,
+ sizeof(c->sb.user_uuid));
}
-static long bch_ioctl_disk_add(struct bch_fs *c,
- struct bch_ioctl_disk_add __user *user_arg)
+static long bch_ioctl_start(struct bch_fs *c, struct bch_ioctl_start __user *user_arg)
{
- struct bch_ioctl_disk_add arg;
- char *path;
- int ret;
+ struct bch_ioctl_start arg;
if (copy_from_user(&arg, user_arg, sizeof(arg)))
return -EFAULT;
- path = strndup_user((const char __user *)(unsigned long) arg.dev, PATH_MAX);
- if (!path)
- return -ENOMEM;
+ if (arg.flags || arg.pad)
+ return -EINVAL;
- ret = bch_dev_add(c, path);
- kfree(path);
+ return bch_fs_start(c) ? -EIO : 0;
+}
- return ret;
+static long bch_ioctl_stop(struct bch_fs *c)
+{
+ bch_fs_stop(c);
+ return 0;
}
/* returns with ref on ca->ref */
@@ -150,29 +157,49 @@ found:
return ca;
}
-static long bch_ioctl_disk_remove(struct bch_fs *c,
- struct bch_ioctl_disk_remove __user *user_arg)
+#if 0
+static struct bch_member *bch_uuid_lookup(struct bch_fs *c, uuid_le uuid)
{
- struct bch_ioctl_disk_remove arg;
- struct bch_dev *ca;
+ struct bch_sb_field_members *mi = bch_sb_get_members(c->disk_sb);
+ unsigned i;
+
+ lockdep_assert_held(&c->sb_lock);
+
+ for (i = 0; i < c->disk_sb->nr_devices; i++)
+ if (!memcmp(&mi->members[i].uuid, &uuid, sizeof(uuid)))
+ return &mi->members[i];
+
+ return NULL;
+}
+#endif
+
+static long bch_ioctl_disk_add(struct bch_fs *c,
+ struct bch_ioctl_disk __user *user_arg)
+{
+ struct bch_ioctl_disk arg;
+ char *path;
int ret;
if (copy_from_user(&arg, user_arg, sizeof(arg)))
return -EFAULT;
- ca = bch_device_lookup(c, (const char __user *)(unsigned long) arg.dev);
- if (IS_ERR(ca))
- return PTR_ERR(ca);
+ if (arg.flags || arg.pad)
+ return -EINVAL;
- ret = bch_dev_remove(c, ca, arg.flags);
+ path = strndup_user((const char __user *)(unsigned long) arg.dev, PATH_MAX);
+ if (!path)
+ return -ENOMEM;
+
+ ret = bch_dev_add(c, path);
+ kfree(path);
return ret;
}
-static long bch_ioctl_disk_set_state(struct bch_fs *c,
- struct bch_ioctl_disk_set_state __user *user_arg)
+static long bch_ioctl_disk_remove(struct bch_fs *c,
+ struct bch_ioctl_disk __user *user_arg)
{
- struct bch_ioctl_disk_set_state arg;
+ struct bch_ioctl_disk arg;
struct bch_dev *ca;
int ret;
@@ -183,75 +210,94 @@ static long bch_ioctl_disk_set_state(struct bch_fs *c,
if (IS_ERR(ca))
return PTR_ERR(ca);
- ret = bch_dev_set_state(c, ca, arg.new_state, arg.flags);
+ ret = bch_dev_remove(c, ca, arg.flags);
percpu_ref_put(&ca->ref);
return ret;
}
-static struct bch_member *bch_uuid_lookup(struct bch_fs *c, uuid_le uuid)
+static long bch_ioctl_disk_online(struct bch_fs *c,
+ struct bch_ioctl_disk __user *user_arg)
{
- struct bch_sb_field_members *mi = bch_sb_get_members(c->disk_sb);
- unsigned i;
+ struct bch_ioctl_disk arg;
+ char *path;
+ int ret;
- lockdep_assert_held(&c->sb_lock);
+ if (copy_from_user(&arg, user_arg, sizeof(arg)))
+ return -EFAULT;
- for (i = 0; i < c->disk_sb->nr_devices; i++)
- if (!memcmp(&mi->members[i].uuid, &uuid, sizeof(uuid)))
- return &mi->members[i];
+ if (arg.flags || arg.pad)
+ return -EINVAL;
- return NULL;
+ path = strndup_user((const char __user *)(unsigned long) arg.dev, PATH_MAX);
+ if (!path)
+ return -ENOMEM;
+
+ ret = bch_dev_online(c, path);
+ kfree(path);
+ return ret;
}
-static long bch_ioctl_disk_remove_by_uuid(struct bch_fs *c,
- struct bch_ioctl_disk_remove_by_uuid __user *user_arg)
+static long bch_ioctl_disk_offline(struct bch_fs *c,
+ struct bch_ioctl_disk __user *user_arg)
{
- struct bch_ioctl_disk_fail_by_uuid arg;
- struct bch_member *m;
- int ret = -ENOENT;
+ struct bch_ioctl_disk arg;
+ struct bch_dev *ca;
+ int ret;
if (copy_from_user(&arg, user_arg, sizeof(arg)))
return -EFAULT;
- mutex_lock(&c->sb_lock);
- if ((m = bch_uuid_lookup(c, arg.dev))) {
- /* XXX: */
- SET_BCH_MEMBER_STATE(m, BCH_MEMBER_STATE_FAILED);
- bch_write_super(c);
- ret = 0;
- }
- mutex_unlock(&c->sb_lock);
+ if (arg.pad)
+ return -EINVAL;
+ ca = bch_device_lookup(c, (const char __user *)(unsigned long) arg.dev);
+ if (IS_ERR(ca))
+ return PTR_ERR(ca);
+
+ ret = bch_dev_offline(c, ca, arg.flags);
+ percpu_ref_put(&ca->ref);
return ret;
}
-static long bch_ioctl_disk_fail_by_uuid(struct bch_fs *c,
- struct bch_ioctl_disk_fail_by_uuid __user *user_arg)
+static long bch_ioctl_disk_set_state(struct bch_fs *c,
+ struct bch_ioctl_disk_set_state __user *user_arg)
{
- struct bch_ioctl_disk_fail_by_uuid arg;
- struct bch_member *m;
- int ret = -ENOENT;
+ struct bch_ioctl_disk_set_state arg;
+ struct bch_dev *ca;
+ int ret;
if (copy_from_user(&arg, user_arg, sizeof(arg)))
return -EFAULT;
- mutex_lock(&c->sb_lock);
- if ((m = bch_uuid_lookup(c, arg.dev))) {
- SET_BCH_MEMBER_STATE(m, BCH_MEMBER_STATE_FAILED);
- bch_write_super(c);
- ret = 0;
- }
- mutex_unlock(&c->sb_lock);
+ ca = bch_device_lookup(c, (const char __user *)(unsigned long) arg.dev);
+ if (IS_ERR(ca))
+ return PTR_ERR(ca);
+ ret = bch_dev_set_state(c, ca, arg.new_state, arg.flags);
+
+ percpu_ref_put(&ca->ref);
return ret;
}
-static long bch_ioctl_query_uuid(struct bch_fs *c,
- struct bch_ioctl_query_uuid __user *user_arg)
+static long bch_ioctl_disk_evacuate(struct bch_fs *c,
+ struct bch_ioctl_disk __user *user_arg)
{
- return copy_to_user(&user_arg->uuid,
- &c->sb.user_uuid,
- sizeof(c->sb.user_uuid));
+ struct bch_ioctl_disk arg;
+ struct bch_dev *ca;
+ int ret;
+
+ if (copy_from_user(&arg, user_arg, sizeof(arg)))
+ return -EFAULT;
+
+ ca = bch_device_lookup(c, (const char __user *)(unsigned long) arg.dev);
+ if (IS_ERR(ca))
+ return PTR_ERR(ca);
+
+ ret = bch_dev_migrate(c, ca);
+
+ percpu_ref_put(&ca->ref);
+ return ret;
}
long bch_fs_ioctl(struct bch_fs *c, unsigned cmd, void __user *arg)
@@ -267,8 +313,8 @@ long bch_fs_ioctl(struct bch_fs *c, unsigned cmd, void __user *arg)
/* ioctls that do require admin cap: */
switch (cmd) {
- case BCH_IOCTL_RUN:
- return -ENOTTY;
+ case BCH_IOCTL_START:
+ return bch_ioctl_start(c, arg);
case BCH_IOCTL_STOP:
return bch_ioctl_stop(c);
@@ -276,13 +322,14 @@ long bch_fs_ioctl(struct bch_fs *c, unsigned cmd, void __user *arg)
return bch_ioctl_disk_add(c, arg);
case BCH_IOCTL_DISK_REMOVE:
return bch_ioctl_disk_remove(c, arg);
+ case BCH_IOCTL_DISK_ONLINE:
+ return bch_ioctl_disk_online(c, arg);
+ case BCH_IOCTL_DISK_OFFLINE:
+ return bch_ioctl_disk_offline(c, arg);
case BCH_IOCTL_DISK_SET_STATE:
return bch_ioctl_disk_set_state(c, arg);
-
- case BCH_IOCTL_DISK_REMOVE_BY_UUID:
- return bch_ioctl_disk_remove_by_uuid(c, arg);
- case BCH_IOCTL_DISK_FAIL_BY_UUID:
- return bch_ioctl_disk_fail_by_uuid(c, arg);
+ case BCH_IOCTL_DISK_EVACUATE:
+ return bch_ioctl_disk_evacuate(c, arg);
default:
return -ENOTTY;