From: Christoph Hellwig Date: Mon, 23 Feb 2026 13:20:14 +0000 (-0800) Subject: iomap: support ioends for buffered reads X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e8f9cf03c9dc94b475ae8f172ecd700806846a6d;p=thirdparty%2Fkernel%2Flinux.git iomap: support ioends for buffered reads Support using the ioend structure to defer I/O completion for buffered reads by calling into the buffered read I/O completion handler from iomap_finish_ioend. Signed-off-by: Christoph Hellwig Link: https://patch.msgid.link/20260223132021.292832-15-hch@lst.de Tested-by: Anuj Gupta Reviewed-by: "Darrick J. Wong" Signed-off-by: Christian Brauner --- diff --git a/fs/iomap/bio.c b/fs/iomap/bio.c index 259a2bf95a43..b4de67bdd513 100644 --- a/fs/iomap/bio.c +++ b/fs/iomap/bio.c @@ -8,14 +8,27 @@ #include "internal.h" #include "trace.h" -static void iomap_read_end_io(struct bio *bio) +static u32 __iomap_read_end_io(struct bio *bio, int error) { - int error = blk_status_to_errno(bio->bi_status); struct folio_iter fi; + u32 folio_count = 0; - bio_for_each_folio_all(fi, bio) + bio_for_each_folio_all(fi, bio) { iomap_finish_folio_read(fi.folio, fi.offset, fi.length, error); + folio_count++; + } bio_put(bio); + return folio_count; +} + +static void iomap_read_end_io(struct bio *bio) +{ + __iomap_read_end_io(bio, blk_status_to_errno(bio->bi_status)); +} + +u32 iomap_finish_ioend_buffered_read(struct iomap_ioend *ioend) +{ + return __iomap_read_end_io(&ioend->io_bio, ioend->io_error); } static void iomap_bio_submit_read(const struct iomap_iter *iter, diff --git a/fs/iomap/internal.h b/fs/iomap/internal.h index 3a4e4aad2bd1..b39dbc17e3f0 100644 --- a/fs/iomap/internal.h +++ b/fs/iomap/internal.h @@ -4,6 +4,7 @@ #define IOEND_BATCH_SIZE 4096 +u32 iomap_finish_ioend_buffered_read(struct iomap_ioend *ioend); u32 iomap_finish_ioend_direct(struct iomap_ioend *ioend); #ifdef CONFIG_BLOCK diff --git a/fs/iomap/ioend.c b/fs/iomap/ioend.c index 60546fa14dfe..450ab002eb91 100644 --- a/fs/iomap/ioend.c +++ b/fs/iomap/ioend.c @@ -37,7 +37,7 @@ EXPORT_SYMBOL_GPL(iomap_init_ioend); * state, release holds on bios, and finally free up memory. Do not use the * ioend after this. */ -static u32 iomap_finish_ioend_buffered(struct iomap_ioend *ioend) +static u32 iomap_finish_ioend_buffered_write(struct iomap_ioend *ioend) { struct inode *inode = ioend->io_inode; struct bio *bio = &ioend->io_bio; @@ -87,7 +87,7 @@ iomap_fail_ioends( while ((ioend = list_first_entry_or_null(&tmp, struct iomap_ioend, io_list))) { list_del_init(&ioend->io_list); - iomap_finish_ioend_buffered(ioend); + iomap_finish_ioend_buffered_write(ioend); cond_resched(); } } @@ -120,7 +120,7 @@ static void ioend_writeback_end_bio(struct bio *bio) return; } - iomap_finish_ioend_buffered(ioend); + iomap_finish_ioend_buffered_write(ioend); } /* @@ -313,7 +313,9 @@ static u32 iomap_finish_ioend(struct iomap_ioend *ioend, int error) return 0; if (ioend->io_flags & IOMAP_IOEND_DIRECT) return iomap_finish_ioend_direct(ioend); - return iomap_finish_ioend_buffered(ioend); + if (bio_op(&ioend->io_bio) == REQ_OP_READ) + return iomap_finish_ioend_buffered_read(ioend); + return iomap_finish_ioend_buffered_write(ioend); } /*