Loading fs/btrfs/ioctl.c +185 −0 Original line number Diff line number Diff line Loading @@ -3390,6 +3390,183 @@ static long btrfs_ioctl_balance_progress(struct btrfs_root *root, return ret; } static long btrfs_ioctl_quota_ctl(struct btrfs_root *root, void __user *arg) { struct btrfs_ioctl_quota_ctl_args *sa; struct btrfs_trans_handle *trans = NULL; int ret; int err; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (root->fs_info->sb->s_flags & MS_RDONLY) return -EROFS; sa = memdup_user(arg, sizeof(*sa)); if (IS_ERR(sa)) return PTR_ERR(sa); if (sa->cmd != BTRFS_QUOTA_CTL_RESCAN) { trans = btrfs_start_transaction(root, 2); if (IS_ERR(trans)) { ret = PTR_ERR(trans); goto out; } } switch (sa->cmd) { case BTRFS_QUOTA_CTL_ENABLE: ret = btrfs_quota_enable(trans, root->fs_info); break; case BTRFS_QUOTA_CTL_DISABLE: ret = btrfs_quota_disable(trans, root->fs_info); break; case BTRFS_QUOTA_CTL_RESCAN: ret = btrfs_quota_rescan(root->fs_info); break; default: ret = -EINVAL; break; } if (copy_to_user(arg, sa, sizeof(*sa))) ret = -EFAULT; if (trans) { err = btrfs_commit_transaction(trans, root); if (err && !ret) ret = err; } out: kfree(sa); return ret; } static long btrfs_ioctl_qgroup_assign(struct btrfs_root *root, void __user *arg) { struct btrfs_ioctl_qgroup_assign_args *sa; struct btrfs_trans_handle *trans; int ret; int err; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (root->fs_info->sb->s_flags & MS_RDONLY) return -EROFS; sa = memdup_user(arg, sizeof(*sa)); if (IS_ERR(sa)) return PTR_ERR(sa); trans = btrfs_join_transaction(root); if (IS_ERR(trans)) { ret = PTR_ERR(trans); goto out; } /* FIXME: check if the IDs really exist */ if (sa->assign) { ret = btrfs_add_qgroup_relation(trans, root->fs_info, sa->src, sa->dst); } else { ret = btrfs_del_qgroup_relation(trans, root->fs_info, sa->src, sa->dst); } err = btrfs_end_transaction(trans, root); if (err && !ret) ret = err; out: kfree(sa); return ret; } static long btrfs_ioctl_qgroup_create(struct btrfs_root *root, void __user *arg) { struct btrfs_ioctl_qgroup_create_args *sa; struct btrfs_trans_handle *trans; int ret; int err; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (root->fs_info->sb->s_flags & MS_RDONLY) return -EROFS; sa = memdup_user(arg, sizeof(*sa)); if (IS_ERR(sa)) return PTR_ERR(sa); trans = btrfs_join_transaction(root); if (IS_ERR(trans)) { ret = PTR_ERR(trans); goto out; } /* FIXME: check if the IDs really exist */ if (sa->create) { ret = btrfs_create_qgroup(trans, root->fs_info, sa->qgroupid, NULL); } else { ret = btrfs_remove_qgroup(trans, root->fs_info, sa->qgroupid); } err = btrfs_end_transaction(trans, root); if (err && !ret) ret = err; out: kfree(sa); return ret; } static long btrfs_ioctl_qgroup_limit(struct btrfs_root *root, void __user *arg) { struct btrfs_ioctl_qgroup_limit_args *sa; struct btrfs_trans_handle *trans; int ret; int err; u64 qgroupid; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (root->fs_info->sb->s_flags & MS_RDONLY) return -EROFS; sa = memdup_user(arg, sizeof(*sa)); if (IS_ERR(sa)) return PTR_ERR(sa); trans = btrfs_join_transaction(root); if (IS_ERR(trans)) { ret = PTR_ERR(trans); goto out; } qgroupid = sa->qgroupid; if (!qgroupid) { /* take the current subvol as qgroup */ qgroupid = root->root_key.objectid; } /* FIXME: check if the IDs really exist */ ret = btrfs_limit_qgroup(trans, root->fs_info, qgroupid, &sa->lim); err = btrfs_end_transaction(trans, root); if (err && !ret) ret = err; out: kfree(sa); return ret; } long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { Loading Loading @@ -3476,6 +3653,14 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_get_dev_stats(root, argp, 0); case BTRFS_IOC_GET_AND_RESET_DEV_STATS: return btrfs_ioctl_get_dev_stats(root, argp, 1); case BTRFS_IOC_QUOTA_CTL: return btrfs_ioctl_quota_ctl(root, argp); case BTRFS_IOC_QGROUP_ASSIGN: return btrfs_ioctl_qgroup_assign(root, argp); case BTRFS_IOC_QGROUP_CREATE: return btrfs_ioctl_qgroup_create(root, argp); case BTRFS_IOC_QGROUP_LIMIT: return btrfs_ioctl_qgroup_limit(root, argp); } return -ENOTTY; Loading fs/btrfs/ioctl.h +27 −0 Original line number Diff line number Diff line Loading @@ -319,6 +319,25 @@ struct btrfs_ioctl_get_dev_stats { __u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */ }; #define BTRFS_QUOTA_CTL_ENABLE 1 #define BTRFS_QUOTA_CTL_DISABLE 2 #define BTRFS_QUOTA_CTL_RESCAN 3 struct btrfs_ioctl_quota_ctl_args { __u64 cmd; __u64 status; }; struct btrfs_ioctl_qgroup_assign_args { __u64 assign; __u64 src; __u64 dst; }; struct btrfs_ioctl_qgroup_create_args { __u64 create; __u64 qgroupid; }; #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ Loading Loading @@ -388,4 +407,12 @@ struct btrfs_ioctl_get_dev_stats { #define BTRFS_IOC_GET_AND_RESET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 53, \ struct btrfs_ioctl_get_dev_stats) #define BTRFS_IOC_QUOTA_CTL _IOWR(BTRFS_IOCTL_MAGIC, 40, \ struct btrfs_ioctl_quota_ctl_args) #define BTRFS_IOC_QGROUP_ASSIGN _IOW(BTRFS_IOCTL_MAGIC, 41, \ struct btrfs_ioctl_qgroup_assign_args) #define BTRFS_IOC_QGROUP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 42, \ struct btrfs_ioctl_qgroup_create_args) #define BTRFS_IOC_QGROUP_LIMIT _IOR(BTRFS_IOCTL_MAGIC, 43, \ struct btrfs_ioctl_qgroup_limit_args) #endif Loading
fs/btrfs/ioctl.c +185 −0 Original line number Diff line number Diff line Loading @@ -3390,6 +3390,183 @@ static long btrfs_ioctl_balance_progress(struct btrfs_root *root, return ret; } static long btrfs_ioctl_quota_ctl(struct btrfs_root *root, void __user *arg) { struct btrfs_ioctl_quota_ctl_args *sa; struct btrfs_trans_handle *trans = NULL; int ret; int err; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (root->fs_info->sb->s_flags & MS_RDONLY) return -EROFS; sa = memdup_user(arg, sizeof(*sa)); if (IS_ERR(sa)) return PTR_ERR(sa); if (sa->cmd != BTRFS_QUOTA_CTL_RESCAN) { trans = btrfs_start_transaction(root, 2); if (IS_ERR(trans)) { ret = PTR_ERR(trans); goto out; } } switch (sa->cmd) { case BTRFS_QUOTA_CTL_ENABLE: ret = btrfs_quota_enable(trans, root->fs_info); break; case BTRFS_QUOTA_CTL_DISABLE: ret = btrfs_quota_disable(trans, root->fs_info); break; case BTRFS_QUOTA_CTL_RESCAN: ret = btrfs_quota_rescan(root->fs_info); break; default: ret = -EINVAL; break; } if (copy_to_user(arg, sa, sizeof(*sa))) ret = -EFAULT; if (trans) { err = btrfs_commit_transaction(trans, root); if (err && !ret) ret = err; } out: kfree(sa); return ret; } static long btrfs_ioctl_qgroup_assign(struct btrfs_root *root, void __user *arg) { struct btrfs_ioctl_qgroup_assign_args *sa; struct btrfs_trans_handle *trans; int ret; int err; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (root->fs_info->sb->s_flags & MS_RDONLY) return -EROFS; sa = memdup_user(arg, sizeof(*sa)); if (IS_ERR(sa)) return PTR_ERR(sa); trans = btrfs_join_transaction(root); if (IS_ERR(trans)) { ret = PTR_ERR(trans); goto out; } /* FIXME: check if the IDs really exist */ if (sa->assign) { ret = btrfs_add_qgroup_relation(trans, root->fs_info, sa->src, sa->dst); } else { ret = btrfs_del_qgroup_relation(trans, root->fs_info, sa->src, sa->dst); } err = btrfs_end_transaction(trans, root); if (err && !ret) ret = err; out: kfree(sa); return ret; } static long btrfs_ioctl_qgroup_create(struct btrfs_root *root, void __user *arg) { struct btrfs_ioctl_qgroup_create_args *sa; struct btrfs_trans_handle *trans; int ret; int err; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (root->fs_info->sb->s_flags & MS_RDONLY) return -EROFS; sa = memdup_user(arg, sizeof(*sa)); if (IS_ERR(sa)) return PTR_ERR(sa); trans = btrfs_join_transaction(root); if (IS_ERR(trans)) { ret = PTR_ERR(trans); goto out; } /* FIXME: check if the IDs really exist */ if (sa->create) { ret = btrfs_create_qgroup(trans, root->fs_info, sa->qgroupid, NULL); } else { ret = btrfs_remove_qgroup(trans, root->fs_info, sa->qgroupid); } err = btrfs_end_transaction(trans, root); if (err && !ret) ret = err; out: kfree(sa); return ret; } static long btrfs_ioctl_qgroup_limit(struct btrfs_root *root, void __user *arg) { struct btrfs_ioctl_qgroup_limit_args *sa; struct btrfs_trans_handle *trans; int ret; int err; u64 qgroupid; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (root->fs_info->sb->s_flags & MS_RDONLY) return -EROFS; sa = memdup_user(arg, sizeof(*sa)); if (IS_ERR(sa)) return PTR_ERR(sa); trans = btrfs_join_transaction(root); if (IS_ERR(trans)) { ret = PTR_ERR(trans); goto out; } qgroupid = sa->qgroupid; if (!qgroupid) { /* take the current subvol as qgroup */ qgroupid = root->root_key.objectid; } /* FIXME: check if the IDs really exist */ ret = btrfs_limit_qgroup(trans, root->fs_info, qgroupid, &sa->lim); err = btrfs_end_transaction(trans, root); if (err && !ret) ret = err; out: kfree(sa); return ret; } long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { Loading Loading @@ -3476,6 +3653,14 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_get_dev_stats(root, argp, 0); case BTRFS_IOC_GET_AND_RESET_DEV_STATS: return btrfs_ioctl_get_dev_stats(root, argp, 1); case BTRFS_IOC_QUOTA_CTL: return btrfs_ioctl_quota_ctl(root, argp); case BTRFS_IOC_QGROUP_ASSIGN: return btrfs_ioctl_qgroup_assign(root, argp); case BTRFS_IOC_QGROUP_CREATE: return btrfs_ioctl_qgroup_create(root, argp); case BTRFS_IOC_QGROUP_LIMIT: return btrfs_ioctl_qgroup_limit(root, argp); } return -ENOTTY; Loading
fs/btrfs/ioctl.h +27 −0 Original line number Diff line number Diff line Loading @@ -319,6 +319,25 @@ struct btrfs_ioctl_get_dev_stats { __u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */ }; #define BTRFS_QUOTA_CTL_ENABLE 1 #define BTRFS_QUOTA_CTL_DISABLE 2 #define BTRFS_QUOTA_CTL_RESCAN 3 struct btrfs_ioctl_quota_ctl_args { __u64 cmd; __u64 status; }; struct btrfs_ioctl_qgroup_assign_args { __u64 assign; __u64 src; __u64 dst; }; struct btrfs_ioctl_qgroup_create_args { __u64 create; __u64 qgroupid; }; #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ Loading Loading @@ -388,4 +407,12 @@ struct btrfs_ioctl_get_dev_stats { #define BTRFS_IOC_GET_AND_RESET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 53, \ struct btrfs_ioctl_get_dev_stats) #define BTRFS_IOC_QUOTA_CTL _IOWR(BTRFS_IOCTL_MAGIC, 40, \ struct btrfs_ioctl_quota_ctl_args) #define BTRFS_IOC_QGROUP_ASSIGN _IOW(BTRFS_IOCTL_MAGIC, 41, \ struct btrfs_ioctl_qgroup_assign_args) #define BTRFS_IOC_QGROUP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 42, \ struct btrfs_ioctl_qgroup_create_args) #define BTRFS_IOC_QGROUP_LIMIT _IOR(BTRFS_IOCTL_MAGIC, 43, \ struct btrfs_ioctl_qgroup_limit_args) #endif