Commit f5a6b1c5 authored by Dongsheng Yang's avatar Dongsheng Yang Committed by Chris Mason

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: default avatarDongsheng Yang <yangds.fnst@cn.fujitsu.com>
Signed-off-by: default avatarChris Mason <clm@fb.com>
parent 09870d27
...@@ -1048,7 +1048,7 @@ int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans, ...@@ -1048,7 +1048,7 @@ int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans,
return ret; return ret;
} }
int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, int __del_qgroup_relation(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 src, u64 dst) struct btrfs_fs_info *fs_info, u64 src, u64 dst)
{ {
struct btrfs_root *quota_root; struct btrfs_root *quota_root;
...@@ -1058,7 +1058,6 @@ int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, ...@@ -1058,7 +1058,6 @@ int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans,
int ret = 0; int ret = 0;
int err; int err;
mutex_lock(&fs_info->qgroup_ioctl_lock);
quota_root = fs_info->quota_root; quota_root = fs_info->quota_root;
if (!quota_root) { if (!quota_root) {
ret = -EINVAL; ret = -EINVAL;
...@@ -1089,7 +1088,18 @@ int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, ...@@ -1089,7 +1088,18 @@ int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans,
del_relation_rb(fs_info, src, dst); del_relation_rb(fs_info, src, dst);
spin_unlock(&fs_info->qgroup_lock); spin_unlock(&fs_info->qgroup_lock);
out: out:
return ret;
}
int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 src, u64 dst)
{
int ret = 0;
mutex_lock(&fs_info->qgroup_ioctl_lock);
ret = __del_qgroup_relation(trans, fs_info, src, dst);
mutex_unlock(&fs_info->qgroup_ioctl_lock); mutex_unlock(&fs_info->qgroup_ioctl_lock);
return ret; return ret;
} }
...@@ -1132,6 +1142,7 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, ...@@ -1132,6 +1142,7 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans,
{ {
struct btrfs_root *quota_root; struct btrfs_root *quota_root;
struct btrfs_qgroup *qgroup; struct btrfs_qgroup *qgroup;
struct btrfs_qgroup_list *list;
int ret = 0; int ret = 0;
mutex_lock(&fs_info->qgroup_ioctl_lock); mutex_lock(&fs_info->qgroup_ioctl_lock);
...@@ -1146,15 +1157,24 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, ...@@ -1146,15 +1157,24 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans,
ret = -ENOENT; ret = -ENOENT;
goto out; goto out;
} else { } else {
/* check if there are no relations to this qgroup */ /* check if there are no children of this qgroup */
if (!list_empty(&qgroup->groups) || if (!list_empty(&qgroup->members)) {
!list_empty(&qgroup->members)) {
ret = -EBUSY; ret = -EBUSY;
goto out; goto out;
} }
} }
ret = del_qgroup_item(trans, quota_root, qgroupid); ret = del_qgroup_item(trans, quota_root, qgroupid);
while (!list_empty(&qgroup->groups)) {
list = list_first_entry(&qgroup->groups,
struct btrfs_qgroup_list, next_group);
ret = __del_qgroup_relation(trans, fs_info,
qgroupid,
list->group->qgroupid);
if (ret)
goto out;
}
spin_lock(&fs_info->qgroup_lock); spin_lock(&fs_info->qgroup_lock);
del_qgroup_rb(quota_root->fs_info, qgroupid); del_qgroup_rb(quota_root->fs_info, qgroupid);
spin_unlock(&fs_info->qgroup_lock); spin_unlock(&fs_info->qgroup_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment