diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 851f2355f3c8..8b851ac7c3fa 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1061,6 +1061,12 @@ struct btrfs_block_group_item { __le64 flags; } __attribute__ ((__packed__)); +#define BTRFS_QGROUP_LEVEL_SHIFT 48 +static inline u64 btrfs_qgroup_level(u64 qgroupid) +{ + return qgroupid >> BTRFS_QGROUP_LEVEL_SHIFT; +} + /* * is subvolume quota turned on? */ diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 464d1e237512..4fb9610beec7 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -1009,6 +1009,10 @@ int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans, struct btrfs_qgroup_list *list; int ret = 0; + /* Check the level of src and dst first */ + if (btrfs_qgroup_level(src) >= btrfs_qgroup_level(dst)) + return -EINVAL; + mutex_lock(&fs_info->qgroup_ioctl_lock); quota_root = fs_info->quota_root; if (!quota_root) {