diff options
Diffstat (limited to 'fs/bcachefs/fs-ioctl.c')
-rw-r--r-- | fs/bcachefs/fs-ioctl.c | 91 |
1 files changed, 85 insertions, 6 deletions
diff --git a/fs/bcachefs/fs-ioctl.c b/fs/bcachefs/fs-ioctl.c index 8b9d3c7d1f57..20b46126c066 100644 --- a/fs/bcachefs/fs-ioctl.c +++ b/fs/bcachefs/fs-ioctl.c @@ -199,8 +199,9 @@ static int bch2_ioc_goingdown(struct bch_fs *c, u32 __user *arg) return ret; } -static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp, - struct bch_ioctl_subvolume arg) +static long __bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp, + struct bch_ioctl_subvolume_v2 arg, + struct printbuf *err) { struct inode *dir; struct bch_inode_info *inode; @@ -214,13 +215,17 @@ static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp, unsigned create_flags = BCH_CREATE_SUBVOL; if (arg.flags & ~(BCH_SUBVOL_SNAPSHOT_CREATE| - BCH_SUBVOL_SNAPSHOT_RO)) + BCH_SUBVOL_SNAPSHOT_RO)) { + prt_str(err, "invalid flasg"); return -EINVAL; + } if (!(arg.flags & BCH_SUBVOL_SNAPSHOT_CREATE) && (arg.src_ptr || - (arg.flags & BCH_SUBVOL_SNAPSHOT_RO))) + (arg.flags & BCH_SUBVOL_SNAPSHOT_RO))) { + prt_str(err, "invalid flasg"); return -EINVAL; + } if (arg.flags & BCH_SUBVOL_SNAPSHOT_CREATE) create_flags |= BCH_CREATE_SNAPSHOT; @@ -243,6 +248,7 @@ static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp, if (src_path.dentry->d_sb->s_fs_info != c) { path_put(&src_path); + prt_str(err, "src_path not on dst filesystem"); error = -EXDEV; goto err1; } @@ -258,6 +264,7 @@ static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp, goto err2; if (dst_dentry->d_sb->s_fs_info != c) { + prt_str(err, "dst_path not on dst filesystem"); error = -EXDEV; goto err3; } @@ -276,6 +283,7 @@ static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp, s_user_ns = dir->i_sb->s_user_ns; if (!kuid_has_mapping(s_user_ns, current_fsuid()) || !kgid_has_mapping(s_user_ns, current_fsgid())) { + prt_str(err, "current uid/gid not mapped into fs namespace"); error = -EOVERFLOW; goto err3; } @@ -315,8 +323,35 @@ err1: return error; } -static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp, - struct bch_ioctl_subvolume arg) +static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp, + struct bch_ioctl_subvolume arg) +{ + struct bch_ioctl_subvolume_v2 arg_v2 = { + .flags = arg.flags, + .dirfd = arg.dirfd, + .mode = arg.mode, + .dst_ptr = arg.dst_ptr, + .src_ptr = arg.src_ptr, + }; + + CLASS(printbuf, err)(); + long ret = __bch2_ioctl_subvolume_create(c, filp, arg_v2, &err); + if (ret) + bch_err_msg(c, ret, "%s", err.buf); + return ret; +} + +static long bch2_ioctl_subvolume_create_v2(struct bch_fs *c, struct file *filp, + struct bch_ioctl_subvolume_v2 arg) +{ + CLASS(printbuf, err)(); + long ret = __bch2_ioctl_subvolume_create(c, filp, arg, &err); + return bch2_copy_ioctl_err_msg(&arg.err, &err, ret); +} + +static long __bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp, + struct bch_ioctl_subvolume_v2 arg, + struct printbuf *err) { const char __user *name = (void __user *)(unsigned long)arg.dst_ptr; struct path path; @@ -350,6 +385,32 @@ err: return ret; } +static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp, + struct bch_ioctl_subvolume arg) +{ + struct bch_ioctl_subvolume_v2 arg_v2 = { + .flags = arg.flags, + .dirfd = arg.dirfd, + .mode = arg.mode, + .dst_ptr = arg.dst_ptr, + .src_ptr = arg.src_ptr, + }; + + CLASS(printbuf, err)(); + long ret = __bch2_ioctl_subvolume_destroy(c, filp, arg_v2, &err); + if (ret) + bch_err_msg(c, ret, "%s", err.buf); + return ret; +} + +static long bch2_ioctl_subvolume_destroy_v2(struct bch_fs *c, struct file *filp, + struct bch_ioctl_subvolume_v2 arg) +{ + CLASS(printbuf, err)(); + long ret = __bch2_ioctl_subvolume_destroy(c, filp, arg, &err); + return bch2_copy_ioctl_err_msg(&arg.err, &err, ret); +} + long bch2_fs_file_ioctl(struct file *file, unsigned cmd, unsigned long arg) { struct bch_inode_info *inode = file_bch_inode(file); @@ -391,6 +452,15 @@ long bch2_fs_file_ioctl(struct file *file, unsigned cmd, unsigned long arg) break; } + case BCH_IOCTL_SUBVOLUME_CREATE_v2: { + struct bch_ioctl_subvolume_v2 i; + + ret = copy_from_user(&i, (void __user *) arg, sizeof(i)) + ? -EFAULT + : bch2_ioctl_subvolume_create_v2(c, file, i); + break; + } + case BCH_IOCTL_SUBVOLUME_DESTROY: { struct bch_ioctl_subvolume i; @@ -400,6 +470,15 @@ long bch2_fs_file_ioctl(struct file *file, unsigned cmd, unsigned long arg) break; } + case BCH_IOCTL_SUBVOLUME_DESTROY_v2: { + struct bch_ioctl_subvolume_v2 i; + + ret = copy_from_user(&i, (void __user *) arg, sizeof(i)) + ? -EFAULT + : bch2_ioctl_subvolume_destroy_v2(c, file, i); + break; + } + default: ret = bch2_fs_ioctl(c, cmd, (void __user *) arg); break; |