summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Brauner <brauner@kernel.org>2026-07-01 15:26:51 +0200
committerChristian Brauner <brauner@kernel.org>2026-07-01 15:26:51 +0200
commit24dddc384fb9aec2d7eea5463ca6dac98a3b3854 (patch)
treee2f5d7bf6bb5a26fbd4cde69bd6ed4290455a591
parent6c732471740bc2ac9b0946134f9f551dc75f4369 (diff)
parentc1fb97d31782f5a8c66d127624626accbb0dd8bc (diff)
downloadlwn-24dddc384fb9aec2d7eea5463ca6dac98a3b3854.tar.gz
lwn-24dddc384fb9aec2d7eea5463ca6dac98a3b3854.zip
Merge patch series "iomap: consolidate bio submission"
Christoph Hellwig <hch@lst.de> says: This patch changes how iomap submits bios for reads. The old behavior to build up bios across iomap was already considered problematic for a while, but we now ran into a erofs bug because of it, so it's time to finally fix it. * patches from https://patch.msgid.link/20260629121750.3392300-2-hch@lst.de: iomap: submit read bio after each extent fuse: call fuse_send_readpages explicitly from fuse_readahead iomap: consolidate bio submission Link: https://patch.msgid.link/20260629121750.3392300-2-hch@lst.de Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
-rw-r--r--fs/exfat/iomap.c5
-rw-r--r--fs/fuse/file.c14
-rw-r--r--fs/iomap/bio.c15
-rw-r--r--fs/iomap/buffered-io.c16
-rw-r--r--fs/ntfs/aops.c6
-rw-r--r--fs/ntfs3/inode.c5
-rw-r--r--fs/xfs/xfs_aops.c3
-rw-r--r--include/linux/iomap.h2
8 files changed, 30 insertions, 36 deletions
diff --git a/fs/exfat/iomap.c b/fs/exfat/iomap.c
index 1aac38e63fe6..190fc6471f84 100644
--- a/fs/exfat/iomap.c
+++ b/fs/exfat/iomap.c
@@ -253,10 +253,7 @@ static void exfat_iomap_read_end_io(struct bio *bio)
static void exfat_iomap_bio_submit_read(const struct iomap_iter *iter,
struct iomap_read_folio_ctx *ctx)
{
- struct bio *bio = ctx->read_ctx;
-
- bio->bi_end_io = exfat_iomap_read_end_io;
- submit_bio(bio);
+ iomap_bio_submit_read_endio(iter, ctx, exfat_iomap_read_end_io);
}
const struct iomap_read_ops exfat_iomap_bio_read_ops = {
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index e052a0d44dee..ceada75310b8 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -981,19 +981,8 @@ static int fuse_iomap_read_folio_range_async(const struct iomap_iter *iter,
return ret;
}
-static void fuse_iomap_submit_read(const struct iomap_iter *iter,
- struct iomap_read_folio_ctx *ctx)
-{
- struct fuse_fill_read_data *data = ctx->read_ctx;
-
- if (data->ia)
- fuse_send_readpages(data->ia, data->file, data->nr_bytes,
- data->fc->async_read);
-}
-
static const struct iomap_read_ops fuse_iomap_read_ops = {
.read_folio_range = fuse_iomap_read_folio_range_async,
- .submit_read = fuse_iomap_submit_read,
};
static int fuse_read_folio(struct file *file, struct folio *folio)
@@ -1116,6 +1105,9 @@ static void fuse_readahead(struct readahead_control *rac)
return;
iomap_readahead(&fuse_iomap_ops, &ctx, NULL);
+ if (data.ia)
+ fuse_send_readpages(data.ia, data.file, data.nr_bytes,
+ fc->async_read);
}
static ssize_t fuse_cache_read_iter(struct kiocb *iocb, struct iov_iter *to)
diff --git a/fs/iomap/bio.c b/fs/iomap/bio.c
index 4504f4633f17..dc8ac7e370a5 100644
--- a/fs/iomap/bio.c
+++ b/fs/iomap/bio.c
@@ -78,14 +78,24 @@ 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,
- struct iomap_read_folio_ctx *ctx)
+void iomap_bio_submit_read_endio(const struct iomap_iter *iter,
+ struct iomap_read_folio_ctx *ctx, bio_end_io_t end_io)
{
struct bio *bio = ctx->read_ctx;
+ bio->bi_end_io = end_io;
if (iter->iomap.flags & IOMAP_F_INTEGRITY)
fs_bio_integrity_alloc(bio);
submit_bio(bio);
+
+ ctx->read_ctx = NULL;
+}
+EXPORT_SYMBOL_GPL(iomap_bio_submit_read_endio);
+
+static void iomap_bio_submit_read(const struct iomap_iter *iter,
+ struct iomap_read_folio_ctx *ctx)
+{
+ return iomap_bio_submit_read_endio(iter, ctx, iomap_read_end_io);
}
static struct bio_set *iomap_read_bio_set(struct iomap_read_folio_ctx *ctx)
@@ -127,7 +137,6 @@ static void iomap_read_alloc_bio(const struct iomap_iter *iter,
if (ctx->rac)
bio->bi_opf |= REQ_RAHEAD;
bio->bi_iter.bi_sector = iomap_sector(iomap, iter->pos);
- bio->bi_end_io = iomap_read_end_io;
bio_add_folio_nofail(bio, folio, plen,
offset_in_folio(folio, iter->pos));
ctx->read_ctx = bio;
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 8d4806dc46d4..276720bc18dc 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -642,12 +642,12 @@ void iomap_read_folio(const struct iomap_ops *ops,
fsverity_readahead(ctx->vi, folio->index,
folio_nr_pages(folio));
- while ((ret = iomap_iter(&iter, ops)) > 0)
+ while ((ret = iomap_iter(&iter, ops)) > 0) {
iter.status = iomap_read_folio_iter(&iter, ctx,
&bytes_submitted);
-
- if (ctx->read_ctx && ctx->ops->submit_read)
- ctx->ops->submit_read(&iter, ctx);
+ if (ctx->read_ctx && ctx->ops->submit_read)
+ ctx->ops->submit_read(&iter, ctx);
+ }
if (ctx->cur_folio)
iomap_read_end(ctx->cur_folio, bytes_submitted);
@@ -718,12 +718,12 @@ void iomap_readahead(const struct iomap_ops *ops,
fsverity_readahead(ctx->vi, readahead_index(rac),
readahead_count(rac));
- while (iomap_iter(&iter, ops) > 0)
+ while (iomap_iter(&iter, ops) > 0) {
iter.status = iomap_readahead_iter(&iter, ctx,
&cur_bytes_submitted);
-
- if (ctx->read_ctx && ctx->ops->submit_read)
- ctx->ops->submit_read(&iter, ctx);
+ if (ctx->read_ctx && ctx->ops->submit_read)
+ ctx->ops->submit_read(&iter, ctx);
+ }
if (ctx->cur_folio)
iomap_read_end(ctx->cur_folio, cur_bytes_submitted);
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index 1fbf832ad165..f2bb56506046 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -38,11 +38,9 @@ static void ntfs_iomap_read_end_io(struct bio *bio)
}
static void ntfs_iomap_bio_submit_read(const struct iomap_iter *iter,
- struct iomap_read_folio_ctx *ctx)
+ struct iomap_read_folio_ctx *ctx)
{
- struct bio *bio = ctx->read_ctx;
- bio->bi_end_io = ntfs_iomap_read_end_io;
- submit_bio(bio);
+ iomap_bio_submit_read_endio(iter, ctx, ntfs_iomap_read_end_io);
}
static const struct iomap_read_ops ntfs_iomap_bio_read_ops = {
diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
index c43101cc064d..0c9bd669117d 100644
--- a/fs/ntfs3/inode.c
+++ b/fs/ntfs3/inode.c
@@ -608,10 +608,7 @@ static void ntfs_iomap_read_end_io(struct bio *bio)
static void ntfs_iomap_bio_submit_read(const struct iomap_iter *iter,
struct iomap_read_folio_ctx *ctx)
{
- struct bio *bio = ctx->read_ctx;
-
- bio->bi_end_io = ntfs_iomap_read_end_io;
- submit_bio(bio);
+ iomap_bio_submit_read_endio(iter, ctx, ntfs_iomap_read_end_io);
}
static const struct iomap_read_ops ntfs_iomap_bio_read_ops = {
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 2a0c54256e93..51293b6f331f 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -764,8 +764,7 @@ xfs_bio_submit_read(
/* defer read completions to the ioend workqueue */
iomap_init_ioend(iter->inode, bio, ctx->read_ctx_file_offset, 0);
- bio->bi_end_io = xfs_end_bio;
- submit_bio(bio);
+ iomap_bio_submit_read_endio(iter, ctx, xfs_end_bio);
}
static const struct iomap_read_ops xfs_iomap_read_ops = {
diff --git a/include/linux/iomap.h b/include/linux/iomap.h
index 3582ed1fe236..56b43d594e6e 100644
--- a/include/linux/iomap.h
+++ b/include/linux/iomap.h
@@ -622,6 +622,8 @@ extern struct bio_set iomap_ioend_bioset;
#ifdef CONFIG_BLOCK
int iomap_bio_read_folio_range(const struct iomap_iter *iter,
struct iomap_read_folio_ctx *ctx, size_t plen);
+void iomap_bio_submit_read_endio(const struct iomap_iter *iter,
+ struct iomap_read_folio_ctx *ctx, bio_end_io_t end_io);
extern const struct iomap_read_ops iomap_bio_read_ops;