@@ -432,7 +432,8 @@ static noinline int create_subvol(struct inode *dir,
struct dentry *dentry,
char *name, int namelen,
u64 *async_transid,
- struct btrfs_qgroup_inherit *inherit)
+ struct btrfs_qgroup_inherit *inherit,
+ u8 qgroup_type)
{
struct btrfs_trans_handle *trans;
struct btrfs_key key;
@@ -476,7 +477,7 @@ static noinline int create_subvol(struct inode *dir,
trans->block_rsv = &block_rsv;
trans->bytes_reserved = block_rsv.size;
- ret = btrfs_qgroup_inherit(trans, root->fs_info, 0, objectid, inherit);
+ ret = btrfs_qgroup_inherit(trans, root->fs_info, 0, objectid, inherit, qgroup_type);
if (ret)
goto fail;
@@ -808,7 +809,8 @@ static noinline int btrfs_mksubvol(struct path *parent,
char *name, int namelen,
struct btrfs_root *snap_src,
u64 *async_transid, bool readonly,
- struct btrfs_qgroup_inherit *inherit)
+ struct btrfs_qgroup_inherit *inherit,
+ u8 qgroup_type)
{
struct inode *dir = parent->dentry->d_inode;
struct dentry *dentry;
@@ -851,7 +853,7 @@ static noinline int btrfs_mksubvol(struct path *parent,
async_transid, readonly, inherit);
} else {
error = create_subvol(dir, dentry, name, namelen,
- async_transid, inherit);
+ async_transid, inherit, qgroup_type);
}
if (!error)
fsnotify_mkdir(dir, dentry);
@@ -1594,7 +1596,8 @@ out:
static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
char *name, unsigned long fd, int subvol,
u64 *transid, bool readonly,
- struct btrfs_qgroup_inherit *inherit)
+ struct btrfs_qgroup_inherit *inherit,
+ u8 qgroup_type)
{
int namelen;
int ret = 0;
@@ -1617,7 +1620,8 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
if (subvol) {
ret = btrfs_mksubvol(&file->f_path, name, namelen,
- NULL, transid, readonly, inherit);
+ NULL, transid, readonly, inherit,
+ qgroup_type);
} else {
struct fd src = fdget(fd);
struct inode *src_inode;
@@ -1640,7 +1644,8 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
} else {
ret = btrfs_mksubvol(&file->f_path, name, namelen,
BTRFS_I(src_inode)->root,
- transid, readonly, inherit);
+ transid, readonly, inherit,
+ qgroup_type);
}
fdput(src);
}
@@ -1663,7 +1668,8 @@ static noinline int btrfs_ioctl_snap_create(struct file *file,
ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
vol_args->fd, subvol,
- NULL, false, NULL);
+ NULL, false, NULL,
+ BTRFS_QGROUP_TYPE_DEFAULT);
kfree(vol_args);
return ret;
@@ -1673,11 +1679,13 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
void __user *arg, int subvol)
{
struct btrfs_ioctl_vol_args_v2 *vol_args;
+ struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
int ret;
u64 transid = 0;
u64 *ptr = NULL;
bool readonly = false;
struct btrfs_qgroup_inherit *inherit = NULL;
+ u8 qgroup_type = 0;
vol_args = memdup_user(arg, sizeof(*vol_args));
if (IS_ERR(vol_args))
@@ -1707,9 +1715,19 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
}
}
+ qgroup_type = vol_args->qgroup_type;
+ if (qgroup_type) {
+ if (!btrfs_fs_incompat(root->fs_info, QGROUP_TYPE)) {
+ ret = -EINVAL;
+ goto free_args;
+ }
+ } else {
+ qgroup_type = BTRFS_QGROUP_TYPE_DEFAULT;
+ }
+
ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
vol_args->fd, subvol, ptr,
- readonly, inherit);
+ readonly, inherit, qgroup_type);
if (ret)
goto free_inherit;
@@ -4674,7 +4692,7 @@ static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg)
}
/* FIXME: check if the IDs really exist */
- if (sa->create) {
+ if (sa->create & 0x1) {
u8 type = (sa->create >> BTRFS_QGROUP_TYPE_SHIFT);
if (type) {
if (!btrfs_fs_incompat(root->fs_info, QGROUP_TYPE)) {
@@ -2262,7 +2262,7 @@ out:
*/
int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 srcid, u64 objectid,
- struct btrfs_qgroup_inherit *inherit)
+ struct btrfs_qgroup_inherit *inherit, u8 type)
{
int ret = 0;
int i;
@@ -2273,6 +2273,9 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
u32 level_size = 0;
u64 nums;
+ if (!type)
+ type = BTRFS_QGROUP_TYPE_DEFAULT;
+
mutex_lock(&fs_info->qgroup_ioctl_lock);
if (!fs_info->quota_enabled)
goto out;
@@ -2304,7 +2307,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
/*
* create a tracking group for the subvol itself
*/
- ret = add_qgroup_item(trans, quota_root, objectid, BTRFS_QGROUP_TYPE_DEFAULT);
+ ret = add_qgroup_item(trans, quota_root, objectid, type);
if (ret)
goto out;
@@ -2347,7 +2350,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
spin_lock(&fs_info->qgroup_lock);
- dstgroup = add_qgroup_rb(fs_info, objectid, BTRFS_QGROUP_TYPE_DEFAULT);
+ dstgroup = add_qgroup_rb(fs_info, objectid, type);
if (IS_ERR(dstgroup)) {
ret = PTR_ERR(dstgroup);
goto unlock;
@@ -117,7 +117,7 @@ int btrfs_run_qgroups(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info);
int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 srcid, u64 objectid,
- struct btrfs_qgroup_inherit *inherit);
+ struct btrfs_qgroup_inherit *inherit, u8 type);
int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes, u8 type);
void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes, u8 type);
@@ -1388,7 +1388,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
ret = btrfs_qgroup_inherit(trans, fs_info,
root->root_key.objectid,
- objectid, pending->inherit);
+ objectid, pending->inherit, 0);
if (ret) {
btrfs_abort_transaction(trans, root, ret);
goto fail;
@@ -73,6 +73,7 @@ struct btrfs_ioctl_vol_args_v2 {
struct {
__u64 size;
struct btrfs_qgroup_inherit __user *qgroup_inherit;
+ __u8 qgroup_type;
};
__u64 unused[4];
};
Although we have a type in each qgroup, the all qgroups are created in a default mode. This patch provide a method to user to specify the type of qgroup for a sub volume. It uses an unused byte in btrfs_ioctl_vol_args_v2 to pass a qgroup type from userspace to kernel. Then kernel can create a qgroup with requested type to the subvolume. Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com> --- fs/btrfs/ioctl.c | 38 ++++++++++++++++++++++++++++---------- fs/btrfs/qgroup.c | 9 ++++++--- fs/btrfs/qgroup.h | 2 +- fs/btrfs/transaction.c | 2 +- include/uapi/linux/btrfs.h | 1 + 5 files changed, 37 insertions(+), 15 deletions(-)