]> git.hungrycats.org Git - linux/commitdiff
btrfs: stripe_alloc: relocate a queued stripe group even while it has reserved or...
authorZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Sun, 6 Sep 2026 05:14:31 +0000 (01:14 -0400)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Fri, 18 Sep 2026 21:36:26 +0000 (17:36 -0400)
The reclaim worker defers any group that has bytes reserved or pinned,
on the theory that it was queued for falling below the used threshold
and may be about to go empty on its own.  A stripe_alloc or stripe_meta
group is queued for the opposite reason -- free space trapped in
partially used stripes, which no amount of waiting frees -- and under
COW churn a metadata group has blocks reserved or pinned at every
moment, so the worker skipped every one of seven queued metadata
groups for the whole of a fill-to-the-edge test and relocated none.
Relocation already waits for in-flight allocations and writers on its
own; take the group.

Assisted-by: Claude:claude-fable-5
fs/btrfs/block-group.c

index 312dca95ae1bdec53dd3514eb25012d2b2172335..5e052418b68bea79637c03c33065d924f5b5b636 100644 (file)
@@ -4399,12 +4399,21 @@ static int btrfs_reclaim_block_group(struct btrfs_block_group *bg, int *reclaime
 
        spin_lock(&space_info->lock);
        spin_lock(&bg->lock);
-       if (bg->reserved || bg->pinned || bg->ro) {
+       if (bg->ro ||
+           ((bg->reserved || bg->pinned) &&
+            !btrfs_is_stripe_alloc_bg(bg) &&
+            !btrfs_is_stripe_meta_bg(bg))) {
                /*
                 * We want to bail if we made new allocations or have
                 * outstanding allocations in this block group.  We do
                 * the ro check in case balance is currently acting on
                 * this block group.
+                *
+                * Not for a stripe_alloc or stripe_meta group: under
+                * COW churn it always has blocks reserved or pinned,
+                * so the bail-out would defer it forever, while the
+                * trapped free space it was queued for only grows.
+                * Relocation waits for in-flight allocations itself.
                 */
                spin_unlock(&bg->lock);
                spin_unlock(&space_info->lock);