@@ -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);
@@ -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);
@@ -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;
+}