diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/qgroup.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index f9fb52e52bb6..f175471da882 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c | |||
@@ -956,6 +956,7 @@ int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans, | |||
956 | struct btrfs_root *quota_root; | 956 | struct btrfs_root *quota_root; |
957 | struct btrfs_qgroup *parent; | 957 | struct btrfs_qgroup *parent; |
958 | struct btrfs_qgroup *member; | 958 | struct btrfs_qgroup *member; |
959 | struct btrfs_qgroup_list *list; | ||
959 | int ret = 0; | 960 | int ret = 0; |
960 | 961 | ||
961 | mutex_lock(&fs_info->qgroup_ioctl_lock); | 962 | mutex_lock(&fs_info->qgroup_ioctl_lock); |
@@ -971,6 +972,14 @@ int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans, | |||
971 | goto out; | 972 | goto out; |
972 | } | 973 | } |
973 | 974 | ||
975 | /* check if such qgroup relation exist firstly */ | ||
976 | list_for_each_entry(list, &member->groups, next_group) { | ||
977 | if (list->group == parent) { | ||
978 | ret = -EEXIST; | ||
979 | goto out; | ||
980 | } | ||
981 | } | ||
982 | |||
974 | ret = add_qgroup_relation_item(trans, quota_root, src, dst); | 983 | ret = add_qgroup_relation_item(trans, quota_root, src, dst); |
975 | if (ret) | 984 | if (ret) |
976 | goto out; | 985 | goto out; |
@@ -993,6 +1002,9 @@ int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, | |||
993 | struct btrfs_fs_info *fs_info, u64 src, u64 dst) | 1002 | struct btrfs_fs_info *fs_info, u64 src, u64 dst) |
994 | { | 1003 | { |
995 | struct btrfs_root *quota_root; | 1004 | struct btrfs_root *quota_root; |
1005 | struct btrfs_qgroup *parent; | ||
1006 | struct btrfs_qgroup *member; | ||
1007 | struct btrfs_qgroup_list *list; | ||
996 | int ret = 0; | 1008 | int ret = 0; |
997 | int err; | 1009 | int err; |
998 | 1010 | ||
@@ -1003,6 +1015,21 @@ int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, | |||
1003 | goto out; | 1015 | goto out; |
1004 | } | 1016 | } |
1005 | 1017 | ||
1018 | member = find_qgroup_rb(fs_info, src); | ||
1019 | parent = find_qgroup_rb(fs_info, dst); | ||
1020 | if (!member || !parent) { | ||
1021 | ret = -EINVAL; | ||
1022 | goto out; | ||
1023 | } | ||
1024 | |||
1025 | /* check if such qgroup relation exist firstly */ | ||
1026 | list_for_each_entry(list, &member->groups, next_group) { | ||
1027 | if (list->group == parent) | ||
1028 | goto exist; | ||
1029 | } | ||
1030 | ret = -ENOENT; | ||
1031 | goto out; | ||
1032 | exist: | ||
1006 | ret = del_qgroup_relation_item(trans, quota_root, src, dst); | 1033 | ret = del_qgroup_relation_item(trans, quota_root, src, dst); |
1007 | err = del_qgroup_relation_item(trans, quota_root, dst, src); | 1034 | err = del_qgroup_relation_item(trans, quota_root, dst, src); |
1008 | if (err && !ret) | 1035 | if (err && !ret) |
@@ -1010,7 +1037,6 @@ int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, | |||
1010 | 1037 | ||
1011 | spin_lock(&fs_info->qgroup_lock); | 1038 | spin_lock(&fs_info->qgroup_lock); |
1012 | del_relation_rb(fs_info, src, dst); | 1039 | del_relation_rb(fs_info, src, dst); |
1013 | |||
1014 | spin_unlock(&fs_info->qgroup_lock); | 1040 | spin_unlock(&fs_info->qgroup_lock); |
1015 | out: | 1041 | out: |
1016 | mutex_unlock(&fs_info->qgroup_ioctl_lock); | 1042 | mutex_unlock(&fs_info->qgroup_ioctl_lock); |
@@ -1030,8 +1056,15 @@ int btrfs_create_qgroup(struct btrfs_trans_handle *trans, | |||
1030 | ret = -EINVAL; | 1056 | ret = -EINVAL; |
1031 | goto out; | 1057 | goto out; |
1032 | } | 1058 | } |
1059 | qgroup = find_qgroup_rb(fs_info, qgroupid); | ||
1060 | if (qgroup) { | ||
1061 | ret = -EEXIST; | ||
1062 | goto out; | ||
1063 | } | ||
1033 | 1064 | ||
1034 | ret = add_qgroup_item(trans, quota_root, qgroupid); | 1065 | ret = add_qgroup_item(trans, quota_root, qgroupid); |
1066 | if (ret) | ||
1067 | goto out; | ||
1035 | 1068 | ||
1036 | spin_lock(&fs_info->qgroup_lock); | 1069 | spin_lock(&fs_info->qgroup_lock); |
1037 | qgroup = add_qgroup_rb(fs_info, qgroupid); | 1070 | qgroup = add_qgroup_rb(fs_info, qgroupid); |
@@ -1058,15 +1091,18 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, | |||
1058 | goto out; | 1091 | goto out; |
1059 | } | 1092 | } |
1060 | 1093 | ||
1061 | /* check if there are no relations to this qgroup */ | ||
1062 | qgroup = find_qgroup_rb(fs_info, qgroupid); | 1094 | qgroup = find_qgroup_rb(fs_info, qgroupid); |
1063 | if (qgroup) { | 1095 | if (!qgroup) { |
1064 | if (!list_empty(&qgroup->groups) || !list_empty(&qgroup->members)) { | 1096 | ret = -ENOENT; |
1097 | goto out; | ||
1098 | } else { | ||
1099 | /* check if there are no relations to this qgroup */ | ||
1100 | if (!list_empty(&qgroup->groups) || | ||
1101 | !list_empty(&qgroup->members)) { | ||
1065 | ret = -EBUSY; | 1102 | ret = -EBUSY; |
1066 | goto out; | 1103 | goto out; |
1067 | } | 1104 | } |
1068 | } | 1105 | } |
1069 | |||
1070 | ret = del_qgroup_item(trans, quota_root, qgroupid); | 1106 | ret = del_qgroup_item(trans, quota_root, qgroupid); |
1071 | 1107 | ||
1072 | spin_lock(&fs_info->qgroup_lock); | 1108 | spin_lock(&fs_info->qgroup_lock); |