From: Zygo Blaxell Date: Sun, 6 Sep 2026 13:54:37 +0000 (-0400) Subject: btrfs: stripe_meta: let a group go read-only for relocation against the reserve X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b3ea6b9817a9695e6bebcecd5561a40c6d461a51;p=linux btrfs: stripe_meta: let a group go read-only for relocation against the reserve The read-only guard keeps admitted bytes placeable by refusing to take a group's usable free space out of the supply when the space_info could not absorb it. With the whole-stripe reserve counted as used, that refusal comes by the width of the reserve at the fill edge: two eligible metadata groups sat marked for reclaim through a 300 second wait and the worker dropped each on inc_block_group_ro() -- the space_info was 7 MiB short of the check with 376 MiB of whole stripes claimable, 352 MiB of them the reserve that exists for this move. Going read-only is the first step of relocation, so let the guard draw on the reserve the way relocation's own reservations do. Assisted-by: Claude:claude-fable-5 --- diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c index a018e2eae154b..6c64f1476a2dc 100644 --- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -3901,8 +3901,15 @@ static int inc_block_group_ro(struct btrfs_block_group *cache, bool force) if (READ_ONCE(cache->stripe_unusable_ready)) trapped = min(READ_ONCE(cache->stripe_unusable), num_bytes); + /* + * The stripe_meta reserve is the room a group's live blocks + * move into when it is relocated, and going read-only is the + * first step of exactly that: count the reserve as available + * here, or the guard refuses every relocation at the edge by + * the width of the reserve. + */ if (btrfs_can_overcommit(cache->fs_info, sinfo, num_bytes - trapped, - BTRFS_RESERVE_NO_FLUSH, false)) + BTRFS_RESERVE_NO_FLUSH, true)) ret = 0; }