diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index a5f1421eeee91b84c14af7abf290cbd227a3a21a..4eb7d2ba38f877b7b82a47ddad5976d47c12315b 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3510,6 +3510,20 @@ static int reserve_metadata_bytes(struct btrfs_root *root, u64 profile = btrfs_get_alloc_profile(root, 0); u64 avail; + /* + * If we have a lot of space that's pinned, don't bother doing + * the overcommit dance yet and just commit the transaction. + */ + avail = (space_info->total_bytes - space_info->bytes_used) * 8; + do_div(avail, 10); + if (space_info->bytes_pinned >= avail && flush && !trans && + !committed) { + space_info->flush = 1; + flushing = true; + spin_unlock(&space_info->lock); + goto commit; + } + spin_lock(&root->fs_info->free_chunk_lock); avail = root->fs_info->free_chunk_space; @@ -3581,6 +3595,7 @@ static int reserve_metadata_bytes(struct btrfs_root *root, if (trans) goto out; +commit: ret = -ENOSPC; if (committed) goto out;