]> git.hungrycats.org Git - linux/commit
btrfs: stripe_alloc: hold the probe margin until the metadata reservation charges it
authorZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Sat, 12 Sep 2026 05:41:46 +0000 (01:41 -0400)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Fri, 18 Sep 2026 21:36:29 +0000 (17:36 -0400)
commit58948c83bcda8c0f9df292bf1a4728d8d0248cd9
tree5117b5759391f48161d8bfa9c0436596b413712b
parent0ba3620a218b66f38a37e80ca8ca3a0aaf30abab
btrfs: stripe_alloc: hold the probe margin until the metadata reservation charges it

btrfs_check_data_free_space() admits a write for its bytes plus a
whole-stripe margin per extent, then releases the margin at once, on the
understanding that btrfs_delalloc_reserve_metadata() re-charges it into
bytes_stripe_margin moments later.  Between the two nothing holds it:
at the fill edge, eight fsstress writers were admitted into each other's
released margins, and the stripes their claims then needed had already
gone to their neighbours.  The failure-time dump showed exactly that
shape -- claimable 0, bytes_may_use holding only the failing write, one
stripe of margin per outstanding extent, nothing stranded -- and it
survived charging preallocation by whole stripes and holding a stripe
across it, because it was never preallocation's stripe.

Let the callers that go on to reserve metadata keep the probe's margin
in bytes_may_use and release it only after that reservation has charged
bytes_stripe_margin: the buffered write, page_mkwrite, the block
truncation, the direct IO path (carried in btrfs_dio_data across the
two functions), the log-tail carry and btrfs_delalloc_reserve_space().
The one caller that reserves no metadata, the v1 space cache write-out,
keeps the immediate release.

Assisted-by: Claude:claude-fable-5
Assisted-by: Claude:claude-fable-5-1
fs/btrfs/defrag.c
fs/btrfs/delalloc-space.c
fs/btrfs/delalloc-space.h
fs/btrfs/direct-io.c
fs/btrfs/file.c
fs/btrfs/inode.c