From: Zygo Blaxell Date: Sun, 6 Sep 2026 05:14:31 +0000 (-0400) Subject: btrfs: stripe_alloc: relocate a queued stripe group even while it has reserved or... X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cc4826cb4097c8f6edb37d4393e4a2e27c18e482;p=linux btrfs: stripe_alloc: relocate a queued stripe group even while it has reserved or pinned bytes 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 --- diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c index 2de9d007456cb..71f5129f3f4fd 100644 --- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -4297,12 +4297,21 @@ void btrfs_reclaim_bgs_work(struct work_struct *work) 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);