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 <[email protected]>
---
 fs/iomap/bio.c      | 19 ++++++++++++++++---
 fs/iomap/internal.h |  1 +
 fs/iomap/ioend.c    |  8 +++++---
 3 files changed, 22 insertions(+), 6 deletions(-)

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 800d12f45438..72f20e8c8893 100644
--- a/fs/iomap/ioend.c
+++ b/fs/iomap/ioend.c
@@ -36,7 +36,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;
@@ -68,7 +68,7 @@ static void ioend_writeback_end_bio(struct bio *bio)
        struct iomap_ioend *ioend = iomap_ioend_from_bio(bio);
 
        ioend->io_error = blk_status_to_errno(bio->bi_status);
-       iomap_finish_ioend_buffered(ioend);
+       iomap_finish_ioend_buffered_write(ioend);
 }
 
 /*
@@ -260,7 +260,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);
 }
 
 /*
-- 
2.47.3


Reply via email to