diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index a8c95eee91b7..006b2f5173de 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -438,7 +438,8 @@ static void io_submit_add_bh(struct ext4_io_submit *io, struct inode *inode, struct folio *folio, struct folio *io_folio, - struct buffer_head *bh) + struct buffer_head *bh, + size_t io_off) { if (io->io_bio && (bh->b_blocknr != io->io_next_block || !fscrypt_mergeable_bio_bh(io->io_bio, bh))) { @@ -449,7 +450,7 @@ static void io_submit_add_bh(struct ext4_io_submit *io, io_submit_init_bio(io, bh); io->io_bio->bi_write_hint = inode->i_write_hint; } - if (!bio_add_folio(io->io_bio, io_folio, bh->b_size, bh_offset(bh))) + if (!bio_add_folio(io->io_bio, io_folio, bh->b_size, io_off)) goto submit_and_retry; wbc_account_cgroup_owner(io->io_wbc, folio, bh->b_size); io->io_next_block++; @@ -585,9 +586,20 @@ int ext4_bio_write_folio(struct ext4_io_submit *io, struct folio *folio, /* Now submit buffers to write */ do { + size_t io_off; + if (!buffer_async_write(bh)) continue; - io_submit_add_bh(io, inode, folio, io_folio, bh); + /* + * When io_folio is a single-page bounce buffer (fscrypt), + * normalise to PAGE_SIZE to handle all block sizes correctly. + * Using 0 would break sub-page block sizes (e.g. 1024-byte + * blocks) where multiple bh offsets exist within one page + */ + io_off = (io_folio == folio) + ? bh_offset(bh) + : bh_offset(bh) % PAGE_SIZE; + io_submit_add_bh(io, inode, folio, io_folio, bh, io_off); } while ((bh = bh->b_this_page) != head); return 0;