]> git.hungrycats.org Git - linux/commit
btrfs: stripe_alloc: admit data reservations by whole stripes
authorZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Fri, 11 Sep 2026 22:25:09 +0000 (18:25 -0400)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Wed, 16 Sep 2026 21:40:06 +0000 (17:40 -0400)
commitce9f0599f1959eeb3efbbe41e99b83b2fe2b03b9
treec8fdc079f1d1c14c8f8c1b8da80cabf89acb22ad
parent680e308a925d9b8e6a2339aac7a87be3c43be928
btrfs: stripe_alloc: admit data reservations by whole stripes

An allocation of N bytes that has to open a stripe run claims
round_up(N, full stripe) whole stripes.  A delalloc write is admitted
with a full-stripe margin per outstanding extent, which covers that
roundup for itself, and relocation is admitted for round_up(N) + 1
stripe.  A preallocation was admitted for N alone: fallocate() has no
outstanding extent and holds no margin, so each one short of a stripe
took up to a stripe more from the whole-stripe supply than the gate had
charged.  The supply behind writes admitted earlier shrank by that much
and at the fill edge their claims found nothing.

With the stranded-stripe accounting and the relocation margin in place,
the failure-time dump on a degraded fsstress fill showed exactly this:
every failed write had bytes_stripe_claimable 0, bytes_may_use equal to
its own size, one stripe of margin per outstanding extent, nothing
stranded, no group read-only and no relocation group dedicated -- the
gate's arithmetic was consistent and still the stripes were gone, with
a preallocation's reservation in flight in the dump.

Charge every non-relocation admission the roundup to whole stripes.  The
excess is not held past admission (a preallocation allocates in the same
call), so a concurrent admission in that window can still overrun by a
stripe; holding it would need the reservation to carry the roundup until
the allocation lands, a later refinement.

Assisted-by: Claude:claude-fable-5
fs/btrfs/space-info.c