struct btrfs_dio_data {
        ssize_t submitted;
        struct extent_changeset *data_reserved;
+       struct btrfs_ordered_extent *ordered;
        bool data_space_reserved;
        bool nocow_done;
 };
 }
 
 static struct extent_map *btrfs_create_dio_extent(struct btrfs_inode *inode,
+                                                 struct btrfs_dio_data *dio_data,
                                                  const u64 start,
                                                  const u64 len,
                                                  const u64 orig_start,
                                                  const int type)
 {
        struct extent_map *em = NULL;
-       int ret;
+       struct btrfs_ordered_extent *ordered;
 
        if (type != BTRFS_ORDERED_NOCOW) {
                em = create_io_em(inode, start, len, orig_start, block_start,
                if (IS_ERR(em))
                        goto out;
        }
-       ret = btrfs_add_ordered_extent(inode, start, len, len, block_start,
-                                      block_len, 0,
-                                      (1 << type) |
-                                      (1 << BTRFS_ORDERED_DIRECT),
-                                      BTRFS_COMPRESS_NONE);
-       if (ret) {
+       ordered = btrfs_alloc_ordered_extent(inode, start, len, len,
+                                            block_start, block_len, 0,
+                                            (1 << type) |
+                                            (1 << BTRFS_ORDERED_DIRECT),
+                                            BTRFS_COMPRESS_NONE);
+       if (IS_ERR(ordered)) {
                if (em) {
                        free_extent_map(em);
                        btrfs_drop_extent_map_range(inode, start,
                                                    start + len - 1, false);
                }
-               em = ERR_PTR(ret);
+               em = ERR_CAST(ordered);
+       } else {
+               ASSERT(!dio_data->ordered);
+               dio_data->ordered = ordered;
        }
  out:
 
 }
 
 static struct extent_map *btrfs_new_extent_direct(struct btrfs_inode *inode,
+                                                 struct btrfs_dio_data *dio_data,
                                                  u64 start, u64 len)
 {
        struct btrfs_root *root = inode->root;
        if (ret)
                return ERR_PTR(ret);
 
-       em = btrfs_create_dio_extent(inode, start, ins.offset, start,
+       em = btrfs_create_dio_extent(inode, dio_data, start, ins.offset, start,
                                     ins.objectid, ins.offset, ins.offset,
                                     ins.offset, BTRFS_ORDERED_REGULAR);
        btrfs_dec_block_group_reservations(fs_info, ins.objectid);
                }
                space_reserved = true;
 
-               em2 = btrfs_create_dio_extent(BTRFS_I(inode), start, len,
+               em2 = btrfs_create_dio_extent(BTRFS_I(inode), dio_data, start, len,
                                              orig_start, block_start,
                                              len, orig_block_len,
                                              ram_bytes, type);
                        goto out;
                space_reserved = true;
 
-               em = btrfs_new_extent_direct(BTRFS_I(inode), start, len);
+               em = btrfs_new_extent_direct(BTRFS_I(inode), dio_data, start, len);
                if (IS_ERR(em)) {
                        ret = PTR_ERR(em);
                        goto out;
                                      pos + length - 1, NULL);
                ret = -ENOTBLK;
        }
+       if (write) {
+               btrfs_put_ordered_extent(dio_data->ordered);
+               dio_data->ordered = NULL;
+       }
 
        if (write)
                extent_changeset_free(dio_data->data_reserved);
 
 ssize_t btrfs_dio_read(struct kiocb *iocb, struct iov_iter *iter, size_t done_before)
 {
-       struct btrfs_dio_data data;
+       struct btrfs_dio_data data = { 0 };
 
        return iomap_dio_rw(iocb, iter, &btrfs_dio_iomap_ops, &btrfs_dio_ops,
                            IOMAP_DIO_PARTIAL, &data, done_before);
 struct iomap_dio *btrfs_dio_write(struct kiocb *iocb, struct iov_iter *iter,
                                  size_t done_before)
 {
-       struct btrfs_dio_data data;
+       struct btrfs_dio_data data = { 0 };
 
        return __iomap_dio_rw(iocb, iter, &btrfs_dio_iomap_ops, &btrfs_dio_ops,
                            IOMAP_DIO_PARTIAL, &data, done_before);