btrfs: stripe_alloc: keep the relocation group's stripes out of the admission supply
do_allocation_stripe() dedicates one block group to data relocation
(fs_info->data_reloc_bg, as the zoned allocator does): while a
relocation runs, its allocations go only there and everyone else's skip
it, until the relocation finishes or the group fills. The admission
gate did not know: it counted that group's claimable stripes in the
supply for ordinary writes. At the fill edge with background reclaim
running, the dedicated group was the only one with claimable stripes
left, ordinary writes were admitted against them, and their writebacks
were dropped:
stripe_alloc DROP DUMP: sinfo may_use
3837952 claimable
561053696 ...
bg
7048265728 ... claimable
561053696 ... runs open <- data_reloc_bg
every other group: claimable 0
Track the dedicated group's claimable bytes in the space_info
(bytes_stripe_claimable_reloc: set when a group is dedicated, cleared
when the dedication is released or the group is removed, followed by
the per-group claimable deltas and re-summed by the commit rescan) and
admit ordinary reservations against the supply minus that amount.
Relocation itself is admitted against the whole supply, dedicated group
included. Confining it to the dedicated group's bytes was tried first
and refused relocation as soon as that group -- the first one the
allocator visits, often holding only a couple of free stripes -- ran
short of a reservation's whole stripes plus one, while hundreds of
megabytes of whole stripes sat in other groups: the allocator would
have dropped the dedication and moved on had it been asked, but the
gate failed each queued group with ENOSPC within fifteen milliseconds
and the reclaim worker retried every thirty seconds, with no relocation
ever completing. bytes_may_use is one counter for both sides, so the
sum admitted still fits in the supply.
Assisted-by: Claude:claude-fable-5
Assisted-by: Claude:claude-fable-5-1