From: Joanne Koong <joannelkoong@gmail.com>
To: brauner@kernel.org
Cc: djwong@kernel.org, hch@infradead.org, bfoster@redhat.com,
linux-fsdevel@vger.kernel.org, kernel-team@meta.com
Subject: [PATCH v1 6/9] iomap: optimize reads for non-block-aligned writes
Date: Thu, 9 Oct 2025 15:56:08 -0700 [thread overview]
Message-ID: <20251009225611.3744728-7-joannelkoong@gmail.com> (raw)
In-Reply-To: <20251009225611.3744728-1-joannelkoong@gmail.com>
If a write is block-aligned (i.e., write offset and length are both
block-aligned), no reads should be necessary.
If the write starts or ends at a non-block-aligned offset, the write
should only need to read in at most two blocks, the starting block and
the ending block. Any intermediary blocks should be skipped since they
will be completely overwritten.
Currently for non-block-aligned writes, the entire range gets read in
including intermediary blocks.
Optimize the logic to read in only the necessary blocks.
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
---
fs/iomap/buffered-io.c | 39 ++++++++++++++++++++++++++++++++-------
1 file changed, 32 insertions(+), 7 deletions(-)
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 0ad8c8a218f3..372e14f7ab57 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -686,6 +686,7 @@ static int __iomap_write_begin(const struct iomap_iter *iter,
loff_t block_size = i_blocksize(iter->inode);
loff_t block_start = round_down(pos, block_size);
loff_t block_end = round_up(pos + len, block_size);
+ unsigned int block_bits = iter->inode->i_blkbits;
unsigned int nr_blocks = i_blocks_per_folio(iter->inode, folio);
size_t from = offset_in_folio(folio, pos), to = from + len;
size_t poff, plen;
@@ -714,13 +715,37 @@ static int __iomap_write_begin(const struct iomap_iter *iter,
if (plen == 0)
break;
- /*
- * If the read range will be entirely overwritten by the write,
- * we can skip having to zero/read it in.
- */
- if (!(iter->flags & IOMAP_UNSHARE) &&
- (from <= poff && to >= poff + plen))
- continue;
+ if (!(iter->flags & IOMAP_UNSHARE)) {
+ /*
+ * If the read range will be entirely overwritten by the
+ * write, we can skip having to zero/read it in.
+ */
+ if (from <= poff && to >= poff + plen)
+ continue;
+
+ /*
+ * If the write starts at a non-block-aligned offset
+ * (from > poff), read only the first block. Any
+ * intermediate blocks will be skipped in the next
+ * iteration.
+ *
+ * Exception: skip this optimization if the write spans
+ * only two blocks and ends at a non-block-aligned
+ * offset.
+ */
+ if (from > poff) {
+ if ((plen >> block_bits) > 2 ||
+ to >= poff + plen)
+ plen = block_size;
+ } else if (to < poff + plen) {
+ /*
+ * Else if the write ends at an offset into the
+ * last block, read in just the last block.
+ */
+ poff = poff + plen - block_size;
+ plen = block_size;
+ }
+ }
if (iomap_block_needs_zeroing(iter, block_start)) {
if (WARN_ON_ONCE(iter->flags & IOMAP_UNSHARE))
--
2.47.3
next prev parent reply other threads:[~2025-10-09 22:57 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-09 22:56 [PATCH v1 0/9] iomap: buffered io changes Joanne Koong
2025-10-09 22:56 ` [PATCH v1 1/9] iomap: account for unaligned end offsets when truncating read range Joanne Koong
2025-10-13 3:00 ` Christoph Hellwig
2025-10-09 22:56 ` [PATCH v1 2/9] docs: document iomap writeback's iomap_finish_folio_write() requirement Joanne Koong
2025-10-13 3:01 ` Christoph Hellwig
2025-10-09 22:56 ` [PATCH v1 3/9] iomap: optimize pending async writeback accounting Joanne Koong
2025-10-13 3:04 ` Christoph Hellwig
2025-10-09 22:56 ` [PATCH v1 4/9] iomap: simplify ->read_folio_range() error handling for reads Joanne Koong
2025-10-13 3:06 ` Christoph Hellwig
2025-10-09 22:56 ` [PATCH v1 5/9] iomap: simplify when reads can be skipped for writes Joanne Koong
2025-10-13 3:06 ` Christoph Hellwig
2025-10-09 22:56 ` Joanne Koong [this message]
2025-10-13 3:08 ` [PATCH v1 6/9] iomap: optimize reads for non-block-aligned writes Christoph Hellwig
2025-10-14 0:04 ` Joanne Koong
2025-10-14 4:14 ` Christoph Hellwig
2025-10-09 22:56 ` [PATCH v1 7/9] iomap: use loff_t for file positions and offsets in writeback code Joanne Koong
2025-10-13 3:09 ` Christoph Hellwig
2025-10-09 22:56 ` [PATCH v1 8/9] iomap: use find_next_bit() for dirty bitmap scanning Joanne Koong
2025-10-13 3:13 ` Christoph Hellwig
2025-10-09 22:56 ` [PATCH v1 9/9] iomap: use find_next_bit() for uptodate " Joanne Koong
2025-10-13 3:13 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251009225611.3744728-7-joannelkoong@gmail.com \
--to=joannelkoong@gmail.com \
--cc=bfoster@redhat.com \
--cc=brauner@kernel.org \
--cc=djwong@kernel.org \
--cc=hch@infradead.org \
--cc=kernel-team@meta.com \
--cc=linux-fsdevel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).