]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
iomap: support ioends for buffered reads
authorChristoph Hellwig <hch@lst.de>
Mon, 23 Feb 2026 13:20:14 +0000 (05:20 -0800)
committerChristian Brauner <brauner@kernel.org>
Tue, 10 Mar 2026 09:29:15 +0000 (10:29 +0100)
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 <hch@lst.de>
Link: https://patch.msgid.link/20260223132021.292832-15-hch@lst.de
Tested-by: Anuj Gupta <anuj20.g@samsung.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/iomap/bio.c
fs/iomap/internal.h
fs/iomap/ioend.c

index 259a2bf95a43aae50ed934899fafc95d15cb0e53..b4de67bdd5133f9a6f1d1e9f9e76a3e5c1232c56 100644 (file)
@@ -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,
index 3a4e4aad2bd12865da97fa565ae2b7b9de5598ee..b39dbc17e3f059fb602797fb072d8f3f57c0fee4 100644 (file)
@@ -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
index 60546fa14dfe4d3506c31c18646e7e02ab3804b2..450ab002eb9130f5c0b112d3ba24db8a64dab4f7 100644 (file)
@@ -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);
 }
 
 /*