return bbio;
 }
 
-static blk_status_t btrfs_bio_extract_ordered_extent(struct btrfs_bio *bbio)
-{
-       struct btrfs_ordered_extent *ordered;
-       int ret;
-
-       ordered = btrfs_lookup_ordered_extent(bbio->inode, bbio->file_offset);
-       if (WARN_ON_ONCE(!ordered))
-               return BLK_STS_IOERR;
-       ret = btrfs_extract_ordered_extent(bbio, ordered);
-       btrfs_put_ordered_extent(ordered);
-
-       return errno_to_blk_status(ret);
-}
-
 static struct btrfs_bio *btrfs_split_bio(struct btrfs_fs_info *fs_info,
                                         struct btrfs_bio *orig_bbio,
                                         u64 map_length, bool use_append)
                if (use_append) {
                        bio->bi_opf &= ~REQ_OP_WRITE;
                        bio->bi_opf |= REQ_OP_ZONE_APPEND;
-                       ret = btrfs_bio_extract_ordered_extent(bbio);
-                       if (ret)
-                               goto fail_put_bio;
                }
 
                /*
 
 
 int btrfs_check_sector_csum(struct btrfs_fs_info *fs_info, struct page *page,
                            u32 pgoff, u8 *csum, const u8 * const csum_expected);
-int btrfs_extract_ordered_extent(struct btrfs_bio *bbio,
-                                struct btrfs_ordered_extent *ordered);
 bool btrfs_data_csum_ok(struct btrfs_bio *bbio, struct btrfs_device *dev,
                        u32 bio_offset, struct bio_vec *bv);
 noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len,
 
        }
 }
 
-int btrfs_extract_ordered_extent(struct btrfs_bio *bbio,
-                                struct btrfs_ordered_extent *ordered)
+static int btrfs_extract_ordered_extent(struct btrfs_bio *bbio,
+                                       struct btrfs_ordered_extent *ordered)
 {
        u64 start = (u64)bbio->bio.bi_iter.bi_sector << SECTOR_SHIFT;
        u64 len = bbio->bio.bi_iter.bi_size;
  * an ordered extent if the range of bytes in the file it covers are
  * fully written.
  */
-int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
+int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
 {
        struct btrfs_inode *inode = BTRFS_I(ordered_extent->inode);
        struct btrfs_root *root = inode->root;
                goto out;
        }
 
-       if (btrfs_is_zoned(fs_info)) {
-               btrfs_rewrite_logical_zoned(ordered_extent);
+       if (btrfs_is_zoned(fs_info))
                btrfs_zone_finish_endio(fs_info, ordered_extent->disk_bytenr,
                                        ordered_extent->disk_num_bytes);
-       }
 
        if (test_bit(BTRFS_ORDERED_TRUNCATED, &ordered_extent->flags)) {
                truncated = true;
        return ret;
 }
 
+int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered)
+{
+       if (btrfs_is_zoned(btrfs_sb(ordered->inode->i_sb)) &&
+           !test_bit(BTRFS_ORDERED_IOERR, &ordered->flags))
+               btrfs_finish_ordered_zoned(ordered);
+       return btrfs_finish_one_ordered(ordered);
+}
+
 void btrfs_writepage_endio_finish_ordered(struct btrfs_inode *inode,
                                          struct page *page, u64 start,
                                          u64 end, bool uptodate)
 
        t->last = NULL;
 }
 
+int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent);
 int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent);
 
 void btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry);
 
 #include "transaction.h"
 #include "dev-replace.h"
 #include "space-info.h"
+#include "super.h"
 #include "fs.h"
 #include "accessors.h"
 #include "bio.h"
                sum->logical += physical - bbio->orig_physical;
 }
 
-void btrfs_rewrite_logical_zoned(struct btrfs_ordered_extent *ordered)
+static void btrfs_rewrite_logical_zoned(struct btrfs_ordered_extent *ordered,
+                                       u64 logical)
 {
-       struct btrfs_inode *inode = BTRFS_I(ordered->inode);
-       struct extent_map_tree *em_tree = &inode->extent_tree;
+       struct extent_map_tree *em_tree = &BTRFS_I(ordered->inode)->extent_tree;
        struct extent_map *em;
-       struct btrfs_ordered_sum *sum =
-               list_first_entry(&ordered->list, typeof(*sum), list);
-       u64 logical = sum->logical;
-
-       if (ordered->disk_bytenr == logical)
-               goto out;
 
        ordered->disk_bytenr = logical;
 
        em->block_start = logical;
        free_extent_map(em);
        write_unlock(&em_tree->lock);
+}
+
+static bool btrfs_zoned_split_ordered(struct btrfs_ordered_extent *ordered,
+                                     u64 logical, u64 len)
+{
+       struct btrfs_ordered_extent *new;
+
+       if (!test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags) &&
+           split_extent_map(BTRFS_I(ordered->inode), ordered->file_offset,
+                            ordered->num_bytes, len))
+               return false;
+
+       new = btrfs_split_ordered_extent(ordered, len);
+       if (IS_ERR(new))
+               return false;
+
+       if (new->disk_bytenr != logical)
+               btrfs_rewrite_logical_zoned(new, logical);
+       btrfs_finish_one_ordered(new);
+       return true;
+}
+
+void btrfs_finish_ordered_zoned(struct btrfs_ordered_extent *ordered)
+{
+       struct btrfs_inode *inode = BTRFS_I(ordered->inode);
+       struct btrfs_fs_info *fs_info = inode->root->fs_info;
+       struct btrfs_ordered_sum *sum =
+               list_first_entry(&ordered->list, typeof(*sum), list);
+       u64 logical = sum->logical;
+       u64 len = sum->len;
+
+       while (len < ordered->disk_num_bytes) {
+               sum = list_next_entry(sum, list);
+               if (sum->logical == logical + len) {
+                       len += sum->len;
+                       continue;
+               }
+               if (!btrfs_zoned_split_ordered(ordered, logical, len)) {
+                       set_bit(BTRFS_ORDERED_IOERR, &ordered->flags);
+                       btrfs_err(fs_info, "failed to split ordered extent");
+                       goto out;
+               }
+               logical = sum->logical;
+               len = sum->len;
+       }
+
+       if (ordered->disk_bytenr != logical)
+               btrfs_rewrite_logical_zoned(ordered, logical);
 
 out:
        /*
         * here so that we don't attempt to log the csums later.
         */
        if ((inode->flags & BTRFS_INODE_NODATASUM) ||
-           test_bit(BTRFS_FS_STATE_NO_CSUMS, &inode->root->fs_info->fs_state)) {
-               list_del(&sum->list);
-               kfree(sum);
+           test_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state)) {
+               while ((sum = list_first_entry_or_null(&ordered->list,
+                                                      typeof(*sum), list))) {
+                       list_del(&sum->list);
+                       kfree(sum);
+               }
        }
 }
 
 
        struct blk_zone sb_zones[2 * BTRFS_SUPER_MIRROR_MAX];
 };
 
+void btrfs_finish_ordered_zoned(struct btrfs_ordered_extent *ordered);
+
 #ifdef CONFIG_BLK_DEV_ZONED
 int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos,
                       struct blk_zone *zone);
                            struct extent_buffer *eb);
 bool btrfs_use_zone_append(struct btrfs_bio *bbio);
 void btrfs_record_physical_zoned(struct btrfs_bio *bbio);
-void btrfs_rewrite_logical_zoned(struct btrfs_ordered_extent *ordered);
 bool btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
                                    struct extent_buffer *eb,
                                    struct btrfs_block_group **cache_ret);
 {
 }
 
-static inline void btrfs_rewrite_logical_zoned(
-                               struct btrfs_ordered_extent *ordered) { }
-
 static inline bool btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
                               struct extent_buffer *eb,
                               struct btrfs_block_group **cache_ret)