space_info = bg->space_info;
spin_unlock(&fs_info->unused_bgs_lock);
+ /*
+ * A stripe_alloc / stripe_meta group's live extents can only
+ * move into whole free stripes, and relocation never waits for
+ * them. Once the worker has emptied and removed enough groups,
+ * the ones left are the trapped ones it was queued to move next
+ * with next to nothing claimable, while gigabytes may sit
+ * unallocated: give it a chunk to relocate into, once per
+ * attempt. Here rather than in the reservation path so that a
+ * device shrink, which relocates without room by design, keeps
+ * failing cleanly instead of growing into space it cannot use.
+ */
+ if (btrfs_is_stripe_alloc_bg(bg) || btrfs_is_stripe_meta_bg(bg)) {
+ u64 elsewhere = READ_ONCE(space_info->bytes_stripe_claimable);
+
+ elsewhere -= min(elsewhere, READ_ONCE(bg->stripe_claimable));
+ if (elsewhere < READ_ONCE(bg->used)) {
+ struct btrfs_trans_handle *trans;
+
+ trans = btrfs_join_transaction(fs_info->tree_root);
+ if (!IS_ERR(trans)) {
+ btrfs_chunk_alloc(trans, space_info,
+ btrfs_get_alloc_profile(fs_info,
+ space_info->flags),
+ CHUNK_ALLOC_FORCE);
+ btrfs_end_transaction(trans);
+ }
+ }
+ }
+
/* Don't race with allocators so take the groups_sem */
down_write(&space_info->groups_sem);