summaryrefslogtreecommitdiff
path: root/fs/bcachefs/chardev.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/bcachefs/chardev.c')
-rw-r--r--fs/bcachefs/chardev.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c
index e6ed64dc11b7..3b8c1409bbf6 100644
--- a/fs/bcachefs/chardev.c
+++ b/fs/bcachefs/chardev.c
@@ -293,6 +293,38 @@ static long bch2_ioctl_disk_set_state(struct bch_fs *c,
return ret;
}
+static long bch2_ioctl_disk_set_state_v2(struct bch_fs *c,
+ struct bch_ioctl_disk_set_state_v2 arg)
+{
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if ((arg.flags & ~(BCH_FORCE_IF_DATA_LOST|
+ BCH_FORCE_IF_METADATA_LOST|
+ BCH_FORCE_IF_DEGRADED|
+ BCH_BY_INDEX)) ||
+ arg.pad[0] || arg.pad[1] || arg.pad[2] ||
+ arg.new_state >= BCH_MEMBER_STATE_NR)
+ return -EINVAL;
+
+ CLASS(bch2_device_lookup, ca)(c, arg.dev, arg.flags);
+ if (IS_ERR(ca))
+ return PTR_ERR(ca);
+
+ CLASS(printbuf, err)();
+ int ret = bch2_dev_set_state(c, ca, arg.new_state, arg.flags, &err);
+ if (ret) {
+ if (err.pos > arg.err.msg_len)
+ return -ERANGE;
+
+ prt_printf(&err, "\nerror=%s", bch2_err_str(ret));
+ ret = copy_to_user_errcode((void __user *)(ulong)arg.err.msg_ptr,
+ err.buf,
+ err.pos) ?: ret;
+ }
+ return ret;
+}
+
struct bch_data_ctx {
struct thread_with_file thr;
@@ -693,6 +725,8 @@ long bch2_fs_ioctl(struct bch_fs *c, unsigned cmd, void __user *arg)
BCH_IOCTL(disk_offline, struct bch_ioctl_disk);
case BCH_IOCTL_DISK_SET_STATE:
BCH_IOCTL(disk_set_state, struct bch_ioctl_disk_set_state);
+ case BCH_IOCTL_DISK_SET_STATE_v2:
+ BCH_IOCTL(disk_set_state_v2, struct bch_ioctl_disk_set_state_v2);
case BCH_IOCTL_DATA:
BCH_IOCTL(data, struct bch_ioctl_data);
case BCH_IOCTL_DISK_RESIZE: