*/
 struct btrfs_bio_ctrl {
        struct btrfs_bio *bbio;
+       /* Last byte contained in bbio + 1 . */
+       loff_t next_file_offset;
        enum btrfs_compression_type compress_type;
        u32 len_to_oe_boundary;
        blk_opf_t opf;
 }
 
 static bool btrfs_bio_is_contig(struct btrfs_bio_ctrl *bio_ctrl,
-                               struct folio *folio, u64 disk_bytenr,
-                               unsigned int pg_offset)
+                               u64 disk_bytenr, loff_t file_offset)
 {
        struct bio *bio = &bio_ctrl->bbio->bio;
-       struct bio_vec *bvec = bio_last_bvec_all(bio);
        const sector_t sector = disk_bytenr >> SECTOR_SHIFT;
-       struct folio *bv_folio = page_folio(bvec->bv_page);
 
        if (bio_ctrl->compress_type != BTRFS_COMPRESS_NONE) {
                /*
        }
 
        /*
-        * The contig check requires the following conditions to be met:
-        *
-        * 1) The folios are belonging to the same inode
-        *    This is implied by the call chain.
-        *
-        * 2) The range has adjacent logical bytenr
-        *
-        * 3) The range has adjacent file offset
-        *    This is required for the usage of btrfs_bio->file_offset.
+        * To merge into a bio both the disk sector and the logical offset in
+        * the file need to be contiguous.
         */
-       return bio_end_sector(bio) == sector &&
-               folio_pos(bv_folio) + bvec->bv_offset + bvec->bv_len ==
-               folio_pos(folio) + pg_offset;
+       return bio_ctrl->next_file_offset == file_offset &&
+               bio_end_sector(bio) == sector;
 }
 
 static void alloc_new_bio(struct btrfs_inode *inode,
        bbio->file_offset = file_offset;
        bio_ctrl->bbio = bbio;
        bio_ctrl->len_to_oe_boundary = U32_MAX;
+       bio_ctrl->next_file_offset = file_offset;
 
        /* Limit data write bios to the ordered boundary. */
        if (bio_ctrl->wbc) {
                               size_t size, unsigned long pg_offset)
 {
        struct btrfs_inode *inode = folio_to_inode(folio);
+       loff_t file_offset = folio_pos(folio) + pg_offset;
 
        ASSERT(pg_offset + size <= folio_size(folio));
        ASSERT(bio_ctrl->end_io_func);
 
        if (bio_ctrl->bbio &&
-           !btrfs_bio_is_contig(bio_ctrl, folio, disk_bytenr, pg_offset))
+           !btrfs_bio_is_contig(bio_ctrl, disk_bytenr, file_offset))
                submit_one_bio(bio_ctrl);
 
        do {
                u32 len = size;
 
                /* Allocate new bio if needed */
-               if (!bio_ctrl->bbio) {
-                       alloc_new_bio(inode, bio_ctrl, disk_bytenr,
-                                     folio_pos(folio) + pg_offset);
-               }
+               if (!bio_ctrl->bbio)
+                       alloc_new_bio(inode, bio_ctrl, disk_bytenr, file_offset);
 
                /* Cap to the current ordered extent boundary if there is one. */
                if (len > bio_ctrl->len_to_oe_boundary) {
                        submit_one_bio(bio_ctrl);
                        continue;
                }
+               bio_ctrl->next_file_offset += len;
 
                if (bio_ctrl->wbc)
-                       wbc_account_cgroup_owner(bio_ctrl->wbc, folio,
-                                                len);
+                       wbc_account_cgroup_owner(bio_ctrl->wbc, folio, len);
 
                size -= len;
                pg_offset += len;
                disk_bytenr += len;
+               file_offset += len;
 
                /*
                 * len_to_oe_boundary defaults to U32_MAX, which isn't folio or