aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDongsheng Yang <yangds.fnst@cn.fujitsu.com>2014-11-24 10:27:09 -0500
committerChris Mason <clm@fb.com>2015-04-13 10:52:52 -0400
commitf5a6b1c53bdd44f79e3904c0f5e59f956b49b2c8 (patch)
tree48a56daac94c95f58f3a6c10ef5c10bf0d7d0c19
parent09870d2772b284d0061a5e4d1e1cdf6fb6764344 (diff)
btrfs: qgroup: allow to remove qgroup which has parent but no child.
When a qgroup has parents but no child, it should be removable in Theory I think. But currently, we can not remove it when it has either parent or child. Example: # btrfs quota enable /mnt # btrfs qgroup create 1/0 /mnt # btrfs qgroup create 2/0 /mnt # btrfs qgroup assign 1/0 2/0 /mnt # btrfs qgroup show -pcre /mnt qgroupid rfer excl max_rfer max_excl parent child -------- ---- ---- -------- -------- ------ ----- 0/5 16384 16384 0 0 --- --- 1/0 0 0 0 0 2/0 --- 2/0 0 0 0 0 --- 1/0 At this time, there is no subvol or qgroup depending on it. Just a qgroup 2/0 is its parent, but 2/0 can work well without 1/0. So I think 1/0 should be removalbe. But: # btrfs qgroup destroy 1/0 /mnt ERROR: unable to destroy quota group: Device or resource busy This patch remove the check of qgroup->parent in removing it, then we can remove a qgroup when it has a parent. Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com> Signed-off-by: Chris Mason <clm@fb.com>
-rw-r--r--fs/btrfs/qgroup.c30
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
1051int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, 1051int __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);
1091out: 1090out:
1091 return ret;
1092}
1093
1094int 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);