From: Wang Shilong <[email protected]> When we delete subvolume, the corresponding qgroup will be dead, because Qgroupid/Subvolumeid is not resued.
Qgroup accounting will also be triggered to update subvolume qgroup's parent qgroup's referenced size. Signed-off-by: Wang Shilong <[email protected]> --- fs/btrfs/ctree.h | 2 ++ fs/btrfs/ioctl.c | 5 ++++- fs/btrfs/qgroup.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 941019d..19a6575 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -3997,6 +3997,8 @@ int btrfs_create_qgroup(struct btrfs_trans_handle *trans, char *name); int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, u64 qgroupid); +int btrfs_remove_subvolume_qgroup(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, u64 qgroupid); int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, u64 qgroupid, struct btrfs_qgroup_limit *limit); diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 6523108..fdff50d 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2250,7 +2250,10 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, goto out_end_trans; } } - + ret = btrfs_remove_subvolume_qgroup(trans, root->fs_info, + dest->root_key.objectid); + if (ret) + btrfs_abort_transaction(trans, root, ret); out_end_trans: trans->block_rsv = NULL; trans->bytes_reserved = 0; diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 32bedb5..9e9dba9 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -1985,3 +1985,68 @@ btrfs_qgroup_rescan_resume(struct btrfs_fs_info *fs_info) btrfs_queue_worker(&fs_info->qgroup_rescan_workers, &fs_info->qgroup_rescan_work); } + +int btrfs_remove_subvolume_qgroup(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, + u64 qgroupid) +{ + struct btrfs_root *quota_root; + struct btrfs_qgroup *qgroup; + struct btrfs_qgroup_list *list; + int ret = 0; + + mutex_lock(&fs_info->qgroup_ioctl_lock); + quota_root = fs_info->quota_root; + if (!quota_root) { + ret = -EINVAL; + goto out; + } + + qgroup = find_qgroup_rb(fs_info, qgroupid); + if (!qgroup) { + ret = -ENOENT; + goto out; + } + + list_for_each_entry(list, &qgroup->groups, next_group) { + ret = del_qgroup_relation_item(trans, quota_root, qgroupid, + list->group->qgroupid); + if (ret && ret != -ENOENT) + goto out; + ret = del_qgroup_relation_item(trans, quota_root, + list->group->qgroupid, qgroupid); + if (ret && ret != -ENOENT) + goto out; + } + + /* + * this should not happen with strict hierarchical level + * qgroup. + */ + list_for_each_entry(list, &qgroup->members, next_group) { + ret = del_qgroup_relation_item(trans, quota_root, + list->member->qgroupid, qgroupid); + if (ret && ret != -ENOENT) + goto out; + ret = del_qgroup_relation_item(trans, quota_root, + qgroupid, list->member->qgroupid); + if (ret && ret != -ENOENT) + goto out; + } + ret = del_qgroup_item(trans, quota_root, qgroupid); + if (ret && ret != -ENOENT) + goto out; + spin_lock(&fs_info->qgroup_lock); + ret = qgroup_account_ref_step2(quota_root->fs_info, + quota_root->fs_info->qgroup_ulist, -1, + qgroup->rfer, qgroup); + del_qgroup_rb(quota_root->fs_info, qgroupid); + spin_unlock(&fs_info->qgroup_lock); +out: + mutex_unlock(&fs_info->qgroup_ioctl_lock); + if (ret == -ENOENT) + ret = 0; + return ret; + +} + -- 1.7.11.7 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
