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.f...@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(-)

diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index b1f46e8..a6d83c4 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -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)) {
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 0129dae..ba1997f 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -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;
diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h
index 0be0548..52cfdc2 100644
--- a/fs/btrfs/qgroup.h
+++ b/fs/btrfs/qgroup.h
@@ -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);
 
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 358f3ab..dfe2201 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -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;
diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h
index d4014e6..cb7a882 100644
--- a/include/uapi/linux/btrfs.h
+++ b/include/uapi/linux/btrfs.h
@@ -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];
        };
-- 
1.8.4.2

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to