]> git.hungrycats.org Git - linux/commit
btrfs: stripe_alloc: charge the held stripe margin against every admission
authorZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Fri, 11 Sep 2026 16:36:25 +0000 (12:36 -0400)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Fri, 18 Sep 2026 21:36:29 +0000 (17:36 -0400)
commit45c5aa6a46516ee69c6615565a6a128f518c35e1
treea56fafaa0b76762889cfb61e53872556cbd222bb
parentf090f8355797d03558881825b12f1aee89c6cef7
btrfs: stripe_alloc: charge the held stripe margin against every admission

The data admission gate is meant to refuse a write at reservation time
when the whole-stripe supply cannot cover it, so that write() returns
ENOSPC instead of writeback finding no stripe later.  It compared
bytes_may_use + bytes against bytes_stripe_claimable and left out
bytes_stripe_margin, the whole-stripe collateral every outstanding data
extent holds against the commit that closes its open run and traps the
tail.  The margin is charged against total_bytes through
btrfs_space_info_used(), but not against the supply the admitted bytes
actually draw on.

Each commit shrinks that supply by the trapped tails, with nothing
holding it, so at the fill edge a write that passed admission reached
find_free_extent() and failed: "data writeback allocation of 4096 bytes
returned ENOSPC despite reservation margin; buffered data in this range
will be dropped", followed by the cow_file_range() failures 35 seconds
later in the same fill.  Relocation was admitted the same way, against
supply the margin was reserving, and at the fill edge of a degraded
acceptance run it consumed the whole stripes that small writes' claims
then needed: about fifty 4-32 KiB writes per run failed at writeback in
bursts that tracked the block group relocations to the minute.

The margin is owed to writers already admitted, so every later
admission must respect it: add the held margin to the admitted bytes on
both the ordinary and the relocation path.  This over-refuses by the
margin, which the commit rescan raising bytes_stripe_claimable and the
FLUSH_DATA ticket retry heal, and stays within phase 1's pessimistic
contract; relocation that cannot be covered waits on its ticket like
anyone else, and the margin returns as the writes complete.

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