#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,
#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
* 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;
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();
}
}
return;
}
- iomap_finish_ioend_buffered(ioend);
+ iomap_finish_ioend_buffered_write(ioend);
}
/*
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);
}
/*