}
 }
 
+static int can_allocate_chunk_zoned(struct btrfs_fs_info *fs_info,
+                                   struct find_free_extent_ctl *ffe_ctl)
+{
+       /* If we can activate new zone, just allocate a chunk and use it */
+       if (btrfs_can_activate_zone(fs_info->fs_devices, ffe_ctl->flags))
+               return 0;
+
+       /*
+        * We already reached the max active zones. Try to finish one block
+        * group to make a room for a new block group. This is only possible
+        * for a data block group because btrfs_zone_finish() may need to wait
+        * for a running transaction which can cause a deadlock for metadata
+        * allocation.
+        */
+       if (ffe_ctl->flags & BTRFS_BLOCK_GROUP_DATA) {
+               int ret = btrfs_zone_finish_one_bg(fs_info);
+
+               if (ret == 1)
+                       return 0;
+               else if (ret < 0)
+                       return ret;
+       }
+
+       /*
+        * If we have enough free space left in an already active block group
+        * and we can't activate any other zone now, do not allow allocating a
+        * new chunk and let find_free_extent() retry with a smaller size.
+        */
+       if (ffe_ctl->max_extent_size >= ffe_ctl->min_alloc_size)
+               return -ENOSPC;
+
+       /*
+        * We cannot activate a new block group and no enough space left in any
+        * block groups. So, allocating a new block group may not help. But,
+        * there is nothing to do anyway, so let's go with it.
+        */
+       return 0;
+}
+
 static int can_allocate_chunk(struct btrfs_fs_info *fs_info,
                              struct find_free_extent_ctl *ffe_ctl)
 {
        case BTRFS_EXTENT_ALLOC_CLUSTERED:
                return 0;
        case BTRFS_EXTENT_ALLOC_ZONED:
-               /*
-                * If we have enough free space left in an already
-                * active block group and we can't activate any other
-                * zone now, do not allow allocating a new chunk and
-                * let find_free_extent() retry with a smaller size.
-                */
-               if (ffe_ctl->max_extent_size >= ffe_ctl->min_alloc_size &&
-                   !btrfs_can_activate_zone(fs_info->fs_devices, ffe_ctl->flags))
-                       return -ENOSPC;
-               return 0;
+               return can_allocate_chunk_zoned(fs_info, ffe_ctl);
        default:
                BUG();
        }
 
        spin_unlock(&block_group->lock);
        btrfs_put_block_group(block_group);
 }
+
+int btrfs_zone_finish_one_bg(struct btrfs_fs_info *fs_info)
+{
+       struct btrfs_block_group *block_group;
+       struct btrfs_block_group *min_bg = NULL;
+       u64 min_avail = U64_MAX;
+       int ret;
+
+       spin_lock(&fs_info->zone_active_bgs_lock);
+       list_for_each_entry(block_group, &fs_info->zone_active_bgs,
+                           active_bg_list) {
+               u64 avail;
+
+               spin_lock(&block_group->lock);
+               if (block_group->reserved ||
+                   (block_group->flags & BTRFS_BLOCK_GROUP_SYSTEM)) {
+                       spin_unlock(&block_group->lock);
+                       continue;
+               }
+
+               avail = block_group->zone_capacity - block_group->alloc_offset;
+               if (min_avail > avail) {
+                       if (min_bg)
+                               btrfs_put_block_group(min_bg);
+                       min_bg = block_group;
+                       min_avail = avail;
+                       btrfs_get_block_group(min_bg);
+               }
+               spin_unlock(&block_group->lock);
+       }
+       spin_unlock(&fs_info->zone_active_bgs_lock);
+
+       if (!min_bg)
+               return 0;
+
+       ret = btrfs_zone_finish(min_bg);
+       btrfs_put_block_group(min_bg);
+
+       return ret < 0 ? ret : 1;
+}
 
 bool btrfs_zoned_should_reclaim(struct btrfs_fs_info *fs_info);
 void btrfs_zoned_release_data_reloc_bg(struct btrfs_fs_info *fs_info, u64 logical,
                                       u64 length);
+int btrfs_zone_finish_one_bg(struct btrfs_fs_info *fs_info);
 #else /* CONFIG_BLK_DEV_ZONED */
 static inline int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos,
                                     struct blk_zone *zone)
 
 static inline void btrfs_zoned_release_data_reloc_bg(struct btrfs_fs_info *fs_info,
                                                     u64 logical, u64 length) { }
+
+static inline int btrfs_zone_finish_one_bg(struct btrfs_fs_info *fs_info)
+{
+       return 1;
+}
+
 #endif
 
 static inline bool btrfs_dev_is_sequential(struct btrfs_device *device, u64 pos)