summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/iomap/buffered-io.c45
-rw-r--r--include/linux/iomap.h1
2 files changed, 36 insertions, 10 deletions
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 6f4c97a6d7e9..f5abfa40e3fb 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -292,8 +292,12 @@ static loff_t iomap_readpage_iter(const struct iomap_iter *iter,
gfp_t orig_gfp = gfp;
unsigned int nr_vecs = DIV_ROUND_UP(length, PAGE_SIZE);
- if (ctx->bio)
- submit_bio(ctx->bio);
+ if (ctx->bio) {
+ if (iomap->flags & IOMAP_F_NOSUBMIT)
+ bio_endio(ctx->bio);
+ else
+ submit_bio(ctx->bio);
+ }
if (ctx->rac) /* same as readahead_gfp_mask */
gfp |= __GFP_NORETRY | __GFP_NOWARN;
@@ -346,7 +350,10 @@ int iomap_read_folio(struct folio *folio, const struct iomap_ops *ops)
folio_set_error(folio);
if (ctx.bio) {
- submit_bio(ctx.bio);
+ if (iter.iomap.flags & IOMAP_F_NOSUBMIT)
+ bio_endio(ctx.bio);
+ else
+ submit_bio(ctx.bio);
WARN_ON_ONCE(!ctx.cur_folio_in_bio);
} else {
WARN_ON_ONCE(ctx.cur_folio_in_bio);
@@ -418,8 +425,12 @@ void iomap_readahead(struct readahead_control *rac, const struct iomap_ops *ops)
while (iomap_iter(&iter, ops) > 0)
iter.processed = iomap_readahead_iter(&iter, &ctx);
- if (ctx.bio)
- submit_bio(ctx.bio);
+ if (ctx.bio) {
+ if (iter.iomap.flags & IOMAP_F_NOSUBMIT)
+ bio_endio(ctx.bio);
+ else
+ submit_bio(ctx.bio);
+ }
if (ctx.cur_folio) {
if (!ctx.cur_folio_in_bio)
folio_unlock(ctx.cur_folio);
@@ -543,11 +554,17 @@ static int iomap_read_folio_sync(loff_t block_start, struct folio *folio,
{
struct bio_vec bvec;
struct bio bio;
+ int ret = 0;
bio_init(&bio, iomap->bdev, &bvec, 1, REQ_OP_READ);
bio.bi_iter.bi_sector = iomap_sector(iomap, block_start);
bio_add_folio(&bio, folio, plen, poff);
- return submit_bio_wait(&bio);
+
+ if (iomap->flags & IOMAP_F_NOSUBMIT)
+ bio_endio(&bio);
+ else
+ ret = submit_bio_wait(&bio);
+ return ret;
}
static int __iomap_write_begin(const struct iomap_iter *iter, loff_t pos,
@@ -1493,7 +1510,10 @@ iomap_submit_ioend(struct iomap_writepage_ctx *wpc, struct iomap_ioend *ioend,
return error;
}
- submit_bio(ioend->io_bio);
+ if (wpc->iomap.flags & IOMAP_F_NOSUBMIT)
+ bio_endio(ioend->io_bio);
+ else
+ submit_bio(ioend->io_bio);
return 0;
}
@@ -1531,8 +1551,9 @@ iomap_alloc_ioend(struct inode *inode, struct iomap_writepage_ctx *wpc,
* traversal in iomap_finish_ioend().
*/
static struct bio *
-iomap_chain_bio(struct bio *prev)
+iomap_chain_bio(struct iomap_writepage_ctx *wpc)
{
+ struct bio *prev = wpc->ioend->io_bio;
struct bio *new;
new = bio_alloc(prev->bi_bdev, BIO_MAX_VECS, prev->bi_opf, GFP_NOFS);
@@ -1541,7 +1562,11 @@ iomap_chain_bio(struct bio *prev)
bio_chain(prev, new);
bio_get(prev); /* for iomap_finish_ioend */
- submit_bio(prev);
+
+ if (wpc->iomap.flags & IOMAP_F_NOSUBMIT)
+ bio_endio(prev);
+ else
+ submit_bio(prev);
return new;
}
@@ -1588,7 +1613,7 @@ iomap_add_to_ioend(struct inode *inode, loff_t pos, struct folio *folio,
}
if (!bio_add_folio(wpc->ioend->io_bio, folio, len, poff)) {
- wpc->ioend->io_bio = iomap_chain_bio(wpc->ioend->io_bio);
+ wpc->ioend->io_bio = iomap_chain_bio(wpc);
bio_add_folio(wpc->ioend->io_bio, folio, len, poff);
}
diff --git a/include/linux/iomap.h b/include/linux/iomap.h
index 0f8123504e5e..bc3cdaa444df 100644
--- a/include/linux/iomap.h
+++ b/include/linux/iomap.h
@@ -60,6 +60,7 @@ struct vm_fault;
#define IOMAP_F_MERGED (1U << 3)
#define IOMAP_F_BUFFER_HEAD (1U << 4)
#define IOMAP_F_XATTR (1U << 5)
+#define IOMAP_F_NOSUBMIT (1U << 6)
/*
* Flags set by the core iomap code during operations: