u64 alloc_hint = 0;
        u64 locked_end;
        u64 actual_end = 0;
+       u64 data_space_needed = 0;
+       u64 data_space_reserved = 0;
+       u64 qgroup_reserved = 0;
        struct extent_map *em;
        int blocksize = btrfs_inode_sectorsize(BTRFS_I(inode));
        int ret;
        if (mode & FALLOC_FL_PUNCH_HOLE)
                return btrfs_punch_hole(file, offset, len);
 
-       /*
-        * Only trigger disk allocation, don't trigger qgroup reserve
-        *
-        * For qgroup space, it will be checked later.
-        */
-       if (!(mode & FALLOC_FL_ZERO_RANGE)) {
-               ret = btrfs_alloc_data_chunk_ondemand(BTRFS_I(inode),
-                                                     alloc_end - alloc_start);
-               if (ret < 0)
-                       return ret;
-       }
-
        btrfs_inode_lock(inode, BTRFS_ILOCK_MMAP);
 
        if (!(mode & FALLOC_FL_KEEP_SIZE) && offset + len > inode->i_size) {
                if (em->block_start == EXTENT_MAP_HOLE ||
                    (cur_offset >= inode->i_size &&
                     !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) {
-                       ret = add_falloc_range(&reserve_list, cur_offset,
-                                              last_byte - cur_offset);
+                       const u64 range_len = last_byte - cur_offset;
+
+                       ret = add_falloc_range(&reserve_list, cur_offset, range_len);
                        if (ret < 0) {
                                free_extent_map(em);
                                break;
                        }
                        ret = btrfs_qgroup_reserve_data(BTRFS_I(inode),
-                                       &data_reserved, cur_offset,
-                                       last_byte - cur_offset);
+                                       &data_reserved, cur_offset, range_len);
                        if (ret < 0) {
-                               cur_offset = last_byte;
                                free_extent_map(em);
                                break;
                        }
-               } else {
-                       /*
-                        * Do not need to reserve unwritten extent for this
-                        * range, free reserved data space first, otherwise
-                        * it'll result in false ENOSPC error.
-                        */
-                       btrfs_free_reserved_data_space(BTRFS_I(inode),
-                               data_reserved, cur_offset,
-                               last_byte - cur_offset);
+                       qgroup_reserved += range_len;
+                       data_space_needed += range_len;
                }
                free_extent_map(em);
                cur_offset = last_byte;
        }
 
+       if (!ret && data_space_needed > 0) {
+               /*
+                * We are safe to reserve space here as we can't have delalloc
+                * in the range, see above.
+                */
+               ret = btrfs_alloc_data_chunk_ondemand(BTRFS_I(inode),
+                                                     data_space_needed);
+               if (!ret)
+                       data_space_reserved = data_space_needed;
+       }
+
        /*
         * If ret is still 0, means we're OK to fallocate.
         * Or just cleanup the list and exit.
         */
        list_for_each_entry_safe(range, tmp, &reserve_list, list) {
-               if (!ret)
+               if (!ret) {
                        ret = btrfs_prealloc_file_range(inode, mode,
                                        range->start,
                                        range->len, i_blocksize(inode),
                                        offset + len, &alloc_hint);
-               else
+                       /*
+                        * btrfs_prealloc_file_range() releases space even
+                        * if it returns an error.
+                        */
+                       data_space_reserved -= range->len;
+                       qgroup_reserved -= range->len;
+               } else if (data_space_reserved > 0) {
                        btrfs_free_reserved_data_space(BTRFS_I(inode),
-                                       data_reserved, range->start,
-                                       range->len);
+                                              data_reserved, range->start,
+                                              range->len);
+                       data_space_reserved -= range->len;
+                       qgroup_reserved -= range->len;
+               } else if (qgroup_reserved > 0) {
+                       btrfs_qgroup_free_data(BTRFS_I(inode), data_reserved,
+                                              range->start, range->len);
+                       qgroup_reserved -= range->len;
+               }
                list_del(&range->list);
                kfree(range);
        }
                             &cached_state);
 out:
        btrfs_inode_unlock(inode, BTRFS_ILOCK_MMAP);
-       /* Let go of our reservation. */
-       if (ret != 0 && !(mode & FALLOC_FL_ZERO_RANGE))
-               btrfs_free_reserved_data_space(BTRFS_I(inode), data_reserved,
-                               cur_offset, alloc_end - cur_offset);
        extent_changeset_free(data_reserved);
        return ret;
 }