From: Qu Wenruo <wqu@suse.com>
To: linux-btrfs@vger.kernel.org
Subject: Re: [PATCH 1/2] btrfs: slightly loose the requirement for qgroup removal
Date: Fri, 19 Apr 2024 18:02:47 +0930 [thread overview]
Message-ID: <58795dd2-44bb-44b5-bae6-17fc03ed4740@suse.com> (raw)
In-Reply-To: <acdae2db72282b45ff6d2e11df788a9b146ffe92.1713508989.git.wqu@suse.com>
在 2024/4/19 16:20, Qu Wenruo 写道:
> [BUG]
> Currently if one is utilizing "qgroups/drop_subtree_threshold" sysfs,
> and a snapshot with level higher than that value is dropped, btrfs will
> not be able to delete the qgroup until next qgroup rescan:
>
> uuid=ffffffff-eeee-dddd-cccc-000000000000
>
> wipefs -fa $dev
> mkfs.btrfs -f $dev -O quota -s 4k -n 4k -U $uuid
> mount $dev $mnt
>
> btrfs subvolume create $mnt/subv1/
> for (( i = 0; i < 1024; i++ )); do
> xfs_io -f -c "pwrite 0 2k" $mnt/subv1/file_$i > /dev/null
> done
> sync
> btrfs subv snapshot $mnt/subv1 $mnt/snapshot
> btrfs quota enable $mnt
> btrfs quota rescan -w $mnt
> sync
> echo 1 > /sys/fs/btrfs/$uuid/qgroups/drop_subtree_threshold
> btrfs subvolume delete $mnt/snapshot
> btrfs subv sync $mnt
> btrfs qgroup show -prce --sync $mnt
> btrfs qgroup destroy 0/256 $mnt
My bad, the target qgroup show be 0/257.
Would update the commit message.
Thanks,
Qu
> umount $mnt
>
> The final qgroup removal would fail with the following error:
>
> ERROR: unable to destroy quota group: Device or resource busy
>
> [CAUSE]
> The above script would generate a subvolume of level 2, then snapshot
> it, enable qgroup, set the drop_subtree_threshold, then drop the
> snapshot.
>
> Since the subvolume drop would meet the threshold, qgroup would be
> marked inconsistent and skip accounting to avoid hanging the system at
> transaction commit.
>
> But currently we do not allow a qgroup with any rfer/excl numbers to be
> dropped, and this is not really compatible with the new
> drop_subtree_threshold behavior.
>
> [FIX]
> Instead of a strong requirement for zero rfer/excl numbers, just check
> if there is any child for higher level qgroup, and for subvolume qgroups
> check if there is a corresponding subvolume for it.
>
> For rsv values, just do a WARN_ON() in case.
>
> Signed-off-by: Qu Wenruo <wqu@suse.com>
> ---
> fs/btrfs/qgroup.c | 48 ++++++++++++++++++++++++++++++++++++++++-------
> 1 file changed, 41 insertions(+), 7 deletions(-)
>
> diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
> index 9a9f84c4d3b8..e6fcce4372a4 100644
> --- a/fs/btrfs/qgroup.c
> +++ b/fs/btrfs/qgroup.c
> @@ -1736,13 +1736,38 @@ int btrfs_create_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
> return ret;
> }
>
> -static bool qgroup_has_usage(struct btrfs_qgroup *qgroup)
> +static bool can_delete_qgroup(struct btrfs_fs_info *fs_info,
> + struct btrfs_qgroup *qgroup)
> {
> - return (qgroup->rfer > 0 || qgroup->rfer_cmpr > 0 ||
> - qgroup->excl > 0 || qgroup->excl_cmpr > 0 ||
> - qgroup->rsv.values[BTRFS_QGROUP_RSV_DATA] > 0 ||
> - qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PREALLOC] > 0 ||
> - qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PERTRANS] > 0);
> + struct btrfs_key key;
> + struct btrfs_path *path;
> + int ret;
> +
> + /* For higher level qgroup, we can only delete it if it has no child. */
> + if (btrfs_qgroup_level(qgroup->qgroupid)) {
> + if (!list_empty(&qgroup->members))
> + return false;
> + return true;
> + }
> +
> + /*
> + * For level-0 qgroups, we can only delete it if it has no subvolume
> + * for it.
> + * This means even a subvolume is unlinked but not yet fully dropped,
> + * we can not delete the qgroup.
> + */
> + key.objectid = qgroup->qgroupid;
> + key.type = BTRFS_ROOT_ITEM_KEY;
> + key.offset = -1ULL;
> + path = btrfs_alloc_path();
> + if (!path)
> + return false;
> +
> + ret = btrfs_find_root(fs_info->tree_root, &key, path, NULL, NULL);
> + btrfs_free_path(path);
> + if (ret > 0)
> + return true;
> + return false;
> }
>
> int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
> @@ -1764,7 +1789,7 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
> goto out;
> }
>
> - if (is_fstree(qgroupid) && qgroup_has_usage(qgroup)) {
> + if (!can_delete_qgroup(fs_info, qgroup)) {
> ret = -EBUSY;
> goto out;
> }
> @@ -1775,6 +1800,15 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
> goto out;
> }
>
> + /*
> + * Warn on reserved space. The subvolume should has no child nor
> + * corresponding subvolume.
> + * Thus its reserved space should all be zero.
> + */
> + WARN_ON(qgroup->rsv.values[BTRFS_QGROUP_RSV_DATA] ||
> + qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PREALLOC] ||
> + qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PERTRANS]);
> +
> ret = del_qgroup_item(trans, qgroupid);
> if (ret && ret != -ENOENT)
> goto out;
next prev parent reply other threads:[~2024-04-19 8:32 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-19 6:50 [PATCH 0/2] btrfs: qgroup: stale qgroups related impromvents Qu Wenruo
2024-04-19 6:50 ` [PATCH 1/2] btrfs: slightly loose the requirement for qgroup removal Qu Wenruo
2024-04-19 8:32 ` Qu Wenruo [this message]
2024-04-19 6:50 ` [PATCH 2/2] btrfs: automatically remove the subvolume qgroup Qu Wenruo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=58795dd2-44bb-44b5-bae6-17fc03ed4740@suse.com \
--to=wqu@suse.com \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox