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
