From: Wang Shilong <[email protected]>

The original code forgot to check 'inherit',we should gurantee
that all the qgroups in the struct 'inherit' exist before
btrfs_qgroup_inherit().

Signed-off-by: Wang Shilong <[email protected]>
Reviewed-by: Miao Xie <[email protected]>
---
 fs/btrfs/ctree.h  |    2 ++
 fs/btrfs/ioctl.c  |    6 ++++++
 fs/btrfs/qgroup.c |   29 ++++++++++++++++++++++++++---
 3 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 1ca1c63..0e73385 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3855,6 +3855,8 @@ int btrfs_qgroup_account_ref(struct btrfs_trans_handle 
*trans,
                             struct btrfs_delayed_extent_op *extent_op);
 int btrfs_run_qgroups(struct btrfs_trans_handle *trans,
                      struct btrfs_fs_info *fs_info);
+int btrfs_may_inherit_qgroup(struct btrfs_root *root,
+                            struct btrfs_qgroup_inherit *inherit);
 int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
                         struct btrfs_fs_info *fs_info, u64 srcid, u64 objectid,
                         struct btrfs_qgroup_inherit *inherit);
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 701d812..96fda7e 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -753,6 +753,11 @@ static noinline int btrfs_mksubvol(struct path *parent,
        if (btrfs_root_refs(&BTRFS_I(dir)->root->root_item) == 0)
                goto out_up_read;
        mutex_lock(&BTRFS_I(dir)->root->fs_info->quota_lock);
+
+       error = btrfs_may_inherit_qgroup(BTRFS_I(dir)->root, inherit);
+       if (error)
+               goto out_unlock_mutex;
+
        if (snap_src) {
                error = create_snapshot(snap_src, dir, dentry, name, namelen,
                                        async_transid, readonly, inherit);
@@ -762,6 +767,7 @@ static noinline int btrfs_mksubvol(struct path *parent,
        }
        if (!error)
                fsnotify_mkdir(dir, dentry);
+out_unlock_mutex:
        mutex_unlock(&BTRFS_I(dir)->root->fs_info->quota_lock);
 out_up_read:
        up_read(&BTRFS_I(dir)->root->fs_info->subvol_sem);
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 0e09ac6..14fca77 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -1359,9 +1359,6 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
        if (!fs_info->quota_enabled)
                return 0;
 
-       if (!quota_root)
-               return -EINVAL;
-
        /*
         * create a tracking group for the subvol itself
         */
@@ -1701,3 +1698,29 @@ int btrfs_may_assign_qgroup(struct btrfs_root *root,
                return 0;
        return -ENOENT;
 }
+
+int btrfs_may_inherit_qgroup(struct btrfs_root *root,
+                            struct btrfs_qgroup_inherit *inherit)
+{
+       u64 i = 0;
+       u64 *i_qgroups = NULL;
+       u64 nums = 0;
+       struct btrfs_qgroup *qgroup = NULL;
+
+       if (!inherit)
+               return 0;
+       if (!root->fs_info->quota_root)
+               return -EINVAL;
+
+       i_qgroups = (u64 *)(inherit + 1);
+       nums = inherit->num_qgroups + 2 * inherit->num_ref_copies +
+              2 * inherit->num_excl_copies;
+       for (i = 0; i < nums; ++i) {
+               qgroup = find_qgroup_rb(root->fs_info, *i_qgroups);
+               if (!qgroup)
+                       return -EINVAL;
+
+               ++i_qgroups;
+       }
+       return 0;
+}
-- 
1.7.7.6

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

Reply via email to