]> git.hungrycats.org Git - linux/commitdiff
btrfs: stripe_meta: let a group go read-only for relocation against the reserve
authorZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Sun, 6 Sep 2026 13:54:37 +0000 (09:54 -0400)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Wed, 16 Sep 2026 21:40:05 +0000 (17:40 -0400)
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
fs/btrfs/block-group.c

index a018e2eae154b3fe45618986e259f4a9b106ddef..6c64f1476a2dc26ea239030586a636c31aa31a31 100644 (file)
@@ -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;
        }