* write()-time ENOSPC), corrected upward by the commit rescan.
*/
u64 stripe_claimable;
+ /*
+ * Upper bound on the longest run btrfs_claim_free_stripe_run() can
+ * find, learned from actual scans: (u64)-1 means unknown, 0 means an
+ * exhaustive scan proved there is no claimable run. Claims fail in
+ * O(1) while the bound is below one full stripe; adding free space
+ * resets it to unknown. Unlike stripe_claimable (an accounting
+ * estimate), this caches what the scan itself proved, so it stays
+ * correct even when the accounting errs high. Protected by
+ * free_space_ctl->tree_lock; only meaningful once the block group is
+ * fully cached.
+ */
+ u64 max_claimable_run;
bool stripe_unusable_ready;
/*
spin_lock(&ctl->tree_lock);
+ /*
+ * New free space may merge into a claimable stripe run; forget any
+ * cached "no claimable run" verdict (see btrfs_claim_free_stripe_run()).
+ */
+ block_group->max_claimable_run = (u64)-1;
+
if (try_merge_free_space(ctl, info, true))
goto link;
spin_lock(&ctl->tree_lock);
+ /*
+ * Fail fast without scanning when a previous exhaustive scan proved
+ * this block group has no claimable run (max_claimable_run == 0, set
+ * below): only adding free space can create one, and
+ * __btrfs_add_free_space() resets the bound when it does. Also skip
+ * when the total free space cannot possibly hold one full stripe.
+ * Without this, a fragmented block group costs a full O(size) scan
+ * under ctl->tree_lock for EVERY failed claim - one per small
+ * allocation - which starves the delalloc workers at 100% CPU on
+ * large aged filesystems. Only trust the bound once the block group
+ * is fully cached: cache loading links entries directly, bypassing
+ * __btrfs_add_free_space(), so the reset would be missed.
+ */
+ if (btrfs_block_group_done(block_group) &&
+ (block_group->max_claimable_run < fsl ||
+ ctl->free_space < fsl)) {
+ spin_unlock(&ctl->tree_lock);
+ return -ENOSPC;
+ }
+
entry = find_free_stripe_run(block_group, want_bytes, &run_start, &run_len);
if (!entry) {
/*
return -ENOMEM;
spin_lock(&ctl->tree_lock);
if (!find_free_stripe_run_slow(block_group, want_bytes,
- &run_start, &run_len))
+ &run_start, &run_len)) {
+ /*
+ * The exhaustive scan found no claimable run at all
+ * (the slow path accepts any run of at least one full
+ * stripe). Cache that verdict so subsequent claims
+ * fail in O(1) until free space is added.
+ */
+ if (btrfs_block_group_done(block_group))
+ block_group->max_claimable_run = 0;
goto out;
+ }
spare_used = claim_stripe_run_pieces(block_group, run_start,
run_len, spare);
stripe_claimable_mod(block_group, -(s64)run_len);