btrfs: stripe_alloc: hand groups full of trapped free space to the reclaim worker
Zoned filesystems mark a block group for reclaim as soon as its
unusable bytes reach bg_reclaim_threshold percent of its capacity, so
space that can no longer be written is recycled without an operator
running balance. stripe_alloc had no equivalent. The non-zoned
trigger consults the threshold only where a free drops a group's used
bytes across it, and the test hosts were already running every mount
with bg_reclaim_threshold=75 when this was measured: trapped tails
still accumulated until balance (1.86 GiB of 6.5 GiB after a few hours
of churn), while every byte-based check counted them as free, because
that predicate keys on used bytes only and fires only at the crossing
-- a group hollowed out after it was already below the threshold, or
one whose used bytes never moved while its stripes trapped, is never
queued, and a group at the same used fraction with nothing trapped is.
Mark a group for the existing reclaim worker when its trapped bytes
reach the threshold; the worker re-checks with
should_reclaim_block_group(). The predicate, factored out as
btrfs_stripe_bg_wants_reclaim(), compares the trapped bytes with the
group's free space (length minus used) rather than its length -- a
stripe_alloc group also holds claimable whole stripes, and in practice
fragmentation settles around two thirds of the group trapped with a
fifth used, nothing left worth writing into yet below any sensible
fraction of the length -- and requires room for the group's live data
in the rest of the claimable supply after the bytes already promised to
admitted writers, so a group that cannot be relocated is left alone
until space is freed instead of being retried every commit while the
read-only transitions starve writers.
The trigger runs from the cleaner, which the transaction thread wakes
every cycle whether or not a transaction exists, as well as at the
commit-time rescan: on an idle filesystem nothing rescans, and a group
already on another list (a chunk created in the running transaction is
still on trans->new_bgs) cannot be linked to the reclaim list, so the
five-minute hysteresis stamp is taken only when the mark actually
lands. The worker re-checks whatever it takes, so a stale read costs at
most one wasted attempt. bg_reclaim_threshold defaults to 0 on
non-zoned filesystems, so nothing changes until the sysfs knob is set;
the default is left for review. Relocation needs inc_block_group_ro()
to succeed, hence the earlier fix.