mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
btrfs: automatically remove the subvolume qgroup
Currently if we fully clean a subvolume (not only delete its directory, but fully clean all it's related data and root item), the associated qgroup would not be removed. We have "btrfs qgroup clear-stale" to handle such 0 level qgroups. Change the behavior to automatically removie the qgroup of a fully cleaned subvolume when possible: - Full qgroup but still consistent We can and should remove the qgroup. The qgroup numbers should be 0, without any rsv. - Full qgroup but inconsistent Can happen with drop_subtree_threshold feature (skip accounting and mark qgroup inconsistent). We can and should remove the qgroup. Higher level qgroup numbers will be incorrect, but since qgroup is already inconsistent, it should not be a problem. - Squota mode This is the special case, we can only drop the qgroup if its numbers are all 0. This would be handled by can_delete_qgroup(), so we only need to check the return value and ignore the -EBUSY error. Link: https://bugzilla.suse.com/show_bug.cgi?id=1222847 Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
a776bf5f3c
commit
839d6ea4f8
@ -5833,6 +5833,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref, int for_reloc)
|
|||||||
struct btrfs_root_item *root_item = &root->root_item;
|
struct btrfs_root_item *root_item = &root->root_item;
|
||||||
struct walk_control *wc;
|
struct walk_control *wc;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
|
const u64 rootid = btrfs_root_id(root);
|
||||||
int err = 0;
|
int err = 0;
|
||||||
int ret;
|
int ret;
|
||||||
int level;
|
int level;
|
||||||
@ -6063,6 +6064,13 @@ out_free:
|
|||||||
kfree(wc);
|
kfree(wc);
|
||||||
btrfs_free_path(path);
|
btrfs_free_path(path);
|
||||||
out:
|
out:
|
||||||
|
if (!err && root_dropped) {
|
||||||
|
ret = btrfs_qgroup_cleanup_dropped_subvolume(fs_info, rootid);
|
||||||
|
if (ret < 0)
|
||||||
|
btrfs_warn_rl(fs_info,
|
||||||
|
"failed to cleanup qgroup 0/%llu: %d",
|
||||||
|
rootid, ret);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* We were an unfinished drop root, check to see if there are any
|
* We were an unfinished drop root, check to see if there are any
|
||||||
* pending, and if not clear and wake up any waiters.
|
* pending, and if not clear and wake up any waiters.
|
||||||
|
@ -1889,6 +1889,41 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int btrfs_qgroup_cleanup_dropped_subvolume(struct btrfs_fs_info *fs_info, u64 subvolid)
|
||||||
|
{
|
||||||
|
struct btrfs_trans_handle *trans;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!is_fstree(subvolid) || !btrfs_qgroup_enabled(fs_info) || !fs_info->quota_root)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Commit current transaction to make sure all the rfer/excl numbers
|
||||||
|
* get updated.
|
||||||
|
*/
|
||||||
|
trans = btrfs_start_transaction(fs_info->quota_root, 0);
|
||||||
|
if (IS_ERR(trans))
|
||||||
|
return PTR_ERR(trans);
|
||||||
|
|
||||||
|
ret = btrfs_commit_transaction(trans);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Start new trans to delete the qgroup info and limit items. */
|
||||||
|
trans = btrfs_start_transaction(fs_info->quota_root, 2);
|
||||||
|
if (IS_ERR(trans))
|
||||||
|
return PTR_ERR(trans);
|
||||||
|
ret = btrfs_remove_qgroup(trans, subvolid);
|
||||||
|
btrfs_end_transaction(trans);
|
||||||
|
/*
|
||||||
|
* It's squota and the subvolume still has numbers needed for future
|
||||||
|
* accounting, in this case we can not delete it. Just skip it.
|
||||||
|
*/
|
||||||
|
if (ret == -EBUSY)
|
||||||
|
ret = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid,
|
int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid,
|
||||||
struct btrfs_qgroup_limit *limit)
|
struct btrfs_qgroup_limit *limit)
|
||||||
{
|
{
|
||||||
|
@ -327,6 +327,7 @@ int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, u64 src,
|
|||||||
u64 dst);
|
u64 dst);
|
||||||
int btrfs_create_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid);
|
int btrfs_create_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid);
|
||||||
int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid);
|
int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid);
|
||||||
|
int btrfs_qgroup_cleanup_dropped_subvolume(struct btrfs_fs_info *fs_info, u64 subvolid);
|
||||||
int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid,
|
int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid,
|
||||||
struct btrfs_qgroup_limit *limit);
|
struct btrfs_qgroup_limit *limit);
|
||||||
int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info);
|
int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info);
|
||||||
|
Loading…
Reference in New Issue
Block a user