Re: [PATCH 4/5] btrfs-progs: check: count non-skinny tree blocks in simple quotas
From: Boris Burkov
Date: Wed Nov 04 2026 - 14:32:42 EST
On Wed, Nov 04, 2026 at 03:23:22AM -0700, Siddharth Mishra wrote:
> [BUG]
> On a filesystem without skinny-metadata, mkfs with simple quotas writes
> a qgroup that does not count the tree block of the fs tree:
>
> $ mkfs.btrfs -O squota,^skinny-metadata $dev
> $ btrfs inspect-internal dump-tree -t quota $dev
> item 1 key (0 QGROUP_INFO 0/5) itemoff 16203 itemsize 40
> generation 11
> referenced 0 referenced_compressed 0
> ^^^^^^^^^^^^
> exclusive 0 exclusive_compressed 0
>
> The kernel then warns about a squota underflow when the block is freed,
> and "btrfs check" reports no error, because it uses the same code.
>
> [CAUSE]
> simple_quota_account_extent() treats an extent as a tree block only if
> its key is METADATA_ITEM. Without skinny-metadata a tree block is an
> EXTENT_ITEM with the TREE_BLOCK flag, so it is handled like data: its
> first inline ref is a TREE_BLOCK_REF, not an owner ref, and the block is
> not counted. mkfs fills the qgroups with the same code.
>
> [FIX]
> Also treat an extent item with the TREE_BLOCK flag as a tree block, and
> take its owner from the tree block header.
>
> Fixes: 5bd97022f384 ("btrfs-progs: check: add support for squota")
> Signed-off-by: Siddharth Mishra <smish149@xxxxxxx>
> ---
> check/qgroup-verify.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/check/qgroup-verify.c b/check/qgroup-verify.c
> index b58ef366..d6681653 100644
> --- a/check/qgroup-verify.c
> +++ b/check/qgroup-verify.c
> @@ -1046,8 +1046,9 @@ static int simple_quota_account_extent(struct btrfs_fs_info *info,
> if (generation < counts.enable_gen)
> return 0;
>
> - type = btrfs_extent_inline_ref_type(leaf, iref);
> - if (!meta_item) {
> + if (!meta_item &&
> + !(btrfs_extent_flags(leaf, ei) & BTRFS_EXTENT_FLAG_TREE_BLOCK)) {
I sort of think lifting this higher to make simple_quota_account_extent
check for "is metadata" vs "is metadata item" makes a bit more sense.
Either way,
Reviewed-by: Boris Burkov <boris@xxxxxx>
> + type = btrfs_extent_inline_ref_type(leaf, iref);
> if (type == BTRFS_EXTENT_OWNER_REF_KEY) {
> struct btrfs_extent_owner_ref *oref;
>
> --
> 2.54.0
>