Skip to content

Commit 1e92637

Browse files
boryaskdave
authored andcommitted
btrfs: check for subvolume before deleting squota qgroup
The invariant that we want to maintain with subvolume qgroups is that the qgroup can only be deleted if there is no root. With squotas, we thought that it was sufficient to just check the usage, because we assumed that deleting a subvolume will drive it's qgroups usage to 0, and thus 0 usage implies no subvolume. However, this is false, for two reasons: - A subvol whose extents are all from before squotas was enabled. - A subvol that was created in this transaction and for which we have not yet run any delayed refs. In both cases, deleting the qgroup breaks the desired invariant and we are left with a subvolume with no qgroup but squotas are enabled. Fix this by unifying the deletion check logic between full qgroups and squotas. Squotas do all the same checks *and* the additional usage == 0 check, which is the one extra rule peculiar to squotas. Link: https://lore.kernel.org/linux-btrfs/adnBhWfJQ1n3hZC8@merlins.org/ Fixes: a8df356 ("btrfs: forbid deleting live subvol qgroup") Reviewed-by: Qu Wenruo <wqu@suse.com> Signed-off-by: Boris Burkov <boris@bur.io> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 975e63c commit 1e92637

1 file changed

Lines changed: 25 additions & 25 deletions

File tree

fs/btrfs/qgroup.c

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1715,32 +1715,24 @@ int btrfs_create_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
17151715
return ret;
17161716
}
17171717

1718-
static bool can_delete_parent_qgroup(struct btrfs_qgroup *qgroup)
1719-
1718+
static bool can_delete_parent_qgroup(struct btrfs_fs_info *fs_info, struct btrfs_qgroup *qgroup)
17201719
{
17211720
ASSERT(btrfs_qgroup_level(qgroup->qgroupid));
1721+
if (btrfs_qgroup_mode(fs_info) == BTRFS_QGROUP_MODE_SIMPLE)
1722+
squota_check_parent_usage(fs_info, qgroup);
17221723
return list_empty(&qgroup->members);
17231724
}
17241725

17251726
/*
1726-
* Return true if we can delete the squota qgroup and false otherwise.
1727-
*
1728-
* Rules for whether we can delete:
1729-
*
1730-
* A subvolume qgroup can be removed iff the subvolume is fully deleted, which
1731-
* is iff there is 0 usage in the qgroup.
1732-
*
1733-
* A higher level qgroup can be removed iff it has no members.
1734-
* Note: We audit its usage to warn on inconsitencies without blocking deletion.
1727+
* Because a shared extent can outlive its owning subvolume, we cannot delete a
1728+
* subvol squota qgroup until all of the extents it owns are gone, even if the
1729+
* subvolume itself has been deleted.
17351730
*/
1736-
static bool can_delete_squota_qgroup(struct btrfs_fs_info *fs_info, struct btrfs_qgroup *qgroup)
1731+
static bool can_delete_squota_subvol_qgroup(struct btrfs_fs_info *fs_info,
1732+
struct btrfs_qgroup *qgroup)
17371733
{
17381734
ASSERT(btrfs_qgroup_mode(fs_info) == BTRFS_QGROUP_MODE_SIMPLE);
1739-
1740-
if (btrfs_qgroup_level(qgroup->qgroupid) > 0) {
1741-
squota_check_parent_usage(fs_info, qgroup);
1742-
return can_delete_parent_qgroup(qgroup);
1743-
}
1735+
ASSERT(btrfs_qgroup_level(qgroup->qgroupid) == 0);
17441736

17451737
return !(qgroup->rfer || qgroup->excl || qgroup->rfer_cmpr || qgroup->excl_cmpr);
17461738
}
@@ -1754,14 +1746,11 @@ static int can_delete_qgroup(struct btrfs_fs_info *fs_info, struct btrfs_qgroup
17541746
{
17551747
struct btrfs_key key;
17561748
BTRFS_PATH_AUTO_FREE(path);
1757-
1758-
/* Since squotas cannot be inconsistent, they have special rules for deletion. */
1759-
if (btrfs_qgroup_mode(fs_info) == BTRFS_QGROUP_MODE_SIMPLE)
1760-
return can_delete_squota_qgroup(fs_info, qgroup);
1749+
int ret;
17611750

17621751
/* For higher level qgroup, we can only delete it if it has no child. */
17631752
if (btrfs_qgroup_level(qgroup->qgroupid))
1764-
return can_delete_parent_qgroup(qgroup);
1753+
return can_delete_parent_qgroup(fs_info, qgroup);
17651754

17661755
/*
17671756
* For level-0 qgroups, we can only delete it if it has no subvolume
@@ -1777,10 +1766,21 @@ static int can_delete_qgroup(struct btrfs_fs_info *fs_info, struct btrfs_qgroup
17771766
return -ENOMEM;
17781767

17791768
/*
1780-
* The @ret from btrfs_find_root() exactly matches our definition for
1781-
* the return value, thus can be returned directly.
1769+
* Any subvol qgroup, regardless of mode, cannot be deleted if the
1770+
* subvol still exists.
1771+
*/
1772+
ret = btrfs_find_root(fs_info->tree_root, &key, path, NULL, NULL);
1773+
/*
1774+
* btrfs_find_root returns <0 on error, 0 if found, and >0 if not,
1775+
* so the "found" and "error" cases match our desired return values.
17821776
*/
1783-
return btrfs_find_root(fs_info->tree_root, &key, path, NULL, NULL);
1777+
if (ret <= 0)
1778+
return ret;
1779+
1780+
/* Squotas require additional checks, even if the subvol is deleted. */
1781+
if (btrfs_qgroup_mode(fs_info) == BTRFS_QGROUP_MODE_SIMPLE)
1782+
return can_delete_squota_subvol_qgroup(fs_info, qgroup);
1783+
return 1;
17841784
}
17851785

17861786
int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)

0 commit comments

Comments
 (0)