diff options
-rw-r--r-- | fs/btrfs/qgroup.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 4ec86b3eee21..464d1e237512 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c | |||
@@ -1048,7 +1048,7 @@ out: | |||
1048 | return ret; | 1048 | return ret; |
1049 | } | 1049 | } |
1050 | 1050 | ||
1051 | int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, | 1051 | int __del_qgroup_relation(struct btrfs_trans_handle *trans, |
1052 | struct btrfs_fs_info *fs_info, u64 src, u64 dst) | 1052 | struct btrfs_fs_info *fs_info, u64 src, u64 dst) |
1053 | { | 1053 | { |
1054 | struct btrfs_root *quota_root; | 1054 | struct btrfs_root *quota_root; |
@@ -1058,7 +1058,6 @@ int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, | |||
1058 | int ret = 0; | 1058 | int ret = 0; |
1059 | int err; | 1059 | int err; |
1060 | 1060 | ||
1061 | mutex_lock(&fs_info->qgroup_ioctl_lock); | ||
1062 | quota_root = fs_info->quota_root; | 1061 | quota_root = fs_info->quota_root; |
1063 | if (!quota_root) { | 1062 | if (!quota_root) { |
1064 | ret = -EINVAL; | 1063 | ret = -EINVAL; |
@@ -1089,7 +1088,18 @@ exist: | |||
1089 | del_relation_rb(fs_info, src, dst); | 1088 | del_relation_rb(fs_info, src, dst); |
1090 | spin_unlock(&fs_info->qgroup_lock); | 1089 | spin_unlock(&fs_info->qgroup_lock); |
1091 | out: | 1090 | out: |
1091 | return ret; | ||
1092 | } | ||
1093 | |||
1094 | int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, | ||
1095 | struct btrfs_fs_info *fs_info, u64 src, u64 dst) | ||
1096 | { | ||
1097 | int ret = 0; | ||
1098 | |||
1099 | mutex_lock(&fs_info->qgroup_ioctl_lock); | ||
1100 | ret = __del_qgroup_relation(trans, fs_info, src, dst); | ||
1092 | mutex_unlock(&fs_info->qgroup_ioctl_lock); | 1101 | mutex_unlock(&fs_info->qgroup_ioctl_lock); |
1102 | |||
1093 | return ret; | 1103 | return ret; |
1094 | } | 1104 | } |
1095 | 1105 | ||
@@ -1132,6 +1142,7 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, | |||
1132 | { | 1142 | { |
1133 | struct btrfs_root *quota_root; | 1143 | struct btrfs_root *quota_root; |
1134 | struct btrfs_qgroup *qgroup; | 1144 | struct btrfs_qgroup *qgroup; |
1145 | struct btrfs_qgroup_list *list; | ||
1135 | int ret = 0; | 1146 | int ret = 0; |
1136 | 1147 | ||
1137 | mutex_lock(&fs_info->qgroup_ioctl_lock); | 1148 | mutex_lock(&fs_info->qgroup_ioctl_lock); |
@@ -1146,15 +1157,24 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, | |||
1146 | ret = -ENOENT; | 1157 | ret = -ENOENT; |
1147 | goto out; | 1158 | goto out; |
1148 | } else { | 1159 | } else { |
1149 | /* check if there are no relations to this qgroup */ | 1160 | /* check if there are no children of this qgroup */ |
1150 | if (!list_empty(&qgroup->groups) || | 1161 | if (!list_empty(&qgroup->members)) { |
1151 | !list_empty(&qgroup->members)) { | ||
1152 | ret = -EBUSY; | 1162 | ret = -EBUSY; |
1153 | goto out; | 1163 | goto out; |
1154 | } | 1164 | } |
1155 | } | 1165 | } |
1156 | ret = del_qgroup_item(trans, quota_root, qgroupid); | 1166 | ret = del_qgroup_item(trans, quota_root, qgroupid); |
1157 | 1167 | ||
1168 | while (!list_empty(&qgroup->groups)) { | ||
1169 | list = list_first_entry(&qgroup->groups, | ||
1170 | struct btrfs_qgroup_list, next_group); | ||
1171 | ret = __del_qgroup_relation(trans, fs_info, | ||
1172 | qgroupid, | ||
1173 | list->group->qgroupid); | ||
1174 | if (ret) | ||
1175 | goto out; | ||
1176 | } | ||
1177 | |||
1158 | spin_lock(&fs_info->qgroup_lock); | 1178 | spin_lock(&fs_info->qgroup_lock); |
1159 | del_qgroup_rb(quota_root->fs_info, qgroupid); | 1179 | del_qgroup_rb(quota_root->fs_info, qgroupid); |
1160 | spin_unlock(&fs_info->qgroup_lock); | 1180 | spin_unlock(&fs_info->qgroup_lock); |