Re: [PATCH] ext4: fix quota accounting WARN in bigalloc punch hole
From: Qiliang Yuan
Date: Sat May 30 2026 - 03:49:30 EST
On 5/29/2026 6:37 PM, Zhang Yi wrote:
> On 5/29/2026 4:34 PM, Qiliang Yuan wrote:
>> Thanks for the review! Let me explain the issue with your specific
>> example.
>
> Thanks for the explanation, some comments below.
>
>> ext4_remove_blocks() sees that block 0's cluster has a pending
>> reservation → calls ext4_rereserve_cluster() → dquot_reclaim_block()
>> tries to move 16KB from dqb_curspace to dqb_rsvspace. But
>> dqb_curspace may already be insufficient (depending on whether
>> other allocs/frees have happened), triggering:
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> How exactly did it happen? All data cluster allocations are precisely
> calculated. In addition, the current example cannot reproduce the issue
> you encountered.
>
>> The key point is: pending from __revise_pending() indicates clusters
>> that *still contain delayed blocks outside the newly inserted extent*.
>> These clusters' quota reservations must be preserved — get_rsvd()
>
> Whether to reserve a quota is determined not by whether there are
> delalloc extents left, but by whether there are only pure delalloc
> extents in this cluster range.
You are right about the simple case — I missed the ext4_clu_alloc_state()
logic in ext4_insert_delayed_blocks(). When a cluster already has
allocated blocks, subsequent delalloc within that cluster does not
increase rsvspace, so releasing rsvspace after DIO allocation is
correct there.
However, the syzkaller reproducer's scenario is more complex. It uses
three operations:
1. DIO write at sub-block-aligned offset 0x6400 with RWF_DSYNC
(pwritev2, 0x140000 bytes at offset 0x6400)
2. Delalloc single-byte write at offset 0x8080c61 (far away cluster)
3. PUNCH_HOLE from offset 0x7f covering 0x8000c61 bytes
The DIO and delalloc are in different, distant clusters. The
sub-block-aligned DIO may cause it to fall through a different
code path — possibly zeroing or partial writeback within the cluster
boundary.
I'll instrument a kernel to trace the exact rsvspace/curspace
transitions and get back with concrete numbers showing where the
mismatch occurs. This should settle whether the root cause is
in resv_used += pending or something else.
Thanks for the detailed review!
--
Qiliang Yuan