* [PATCH v2] iomap: avoid memset iomap when iter is done
@ 2026-04-20 6:16 Fengnan Chang
[not found] ` <20260420073254.996FAC19425@smtp.kernel.org>
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Fengnan Chang @ 2026-04-20 6:16 UTC (permalink / raw)
To: brauner, djwong, hch, linux-xfs, linux-fsdevel, linux-ext4
Cc: lidiangang, Fengnan Chang
When iomap_iter() finishes its iteration (returns <= 0), it is no longer
necessary to memset the entire iomap and srcmap structures.
In high-IOPS scenarios (like 4k randread NVMe polling with io_uring),
where the majority of I/Os complete in a single extent map, this wasted
memory write bandwidth, as the caller will just discard the iterator.
Use this command to test:
taskset -c 30 ./t/io_uring -p1 -d512 -b4096 -s32 -c32 -F1 -B1 -R1 -X1
-n1 -P1 /mnt/testfile
IOPS improve about 5% on ext4 and XFS.
However, we MUST still call iomap_iter_reset_iomap() to release the
folio_batch if IOMAP_F_FOLIO_BATCH is set, otherwise we leak page
references. Therefore, split the cleanup logic: always release the
folio_batch, but skip the memset() when ret <= 0.
Signed-off-by: Fengnan Chang <changfengnan@bytedance.com>
---
fs/iomap/iter.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/fs/iomap/iter.c b/fs/iomap/iter.c
index c04796f6e57f..e4a29829591a 100644
--- a/fs/iomap/iter.c
+++ b/fs/iomap/iter.c
@@ -6,17 +6,13 @@
#include <linux/iomap.h>
#include "trace.h"
-static inline void iomap_iter_reset_iomap(struct iomap_iter *iter)
+static inline void iomap_iter_clean_fbatch(struct iomap_iter *iter)
{
if (iter->iomap.flags & IOMAP_F_FOLIO_BATCH) {
folio_batch_release(iter->fbatch);
folio_batch_reinit(iter->fbatch);
iter->iomap.flags &= ~IOMAP_F_FOLIO_BATCH;
}
-
- iter->status = 0;
- memset(&iter->iomap, 0, sizeof(iter->iomap));
- memset(&iter->srcmap, 0, sizeof(iter->srcmap));
}
/* Advance the current iterator position and decrement the remaining length */
@@ -102,10 +98,14 @@ int iomap_iter(struct iomap_iter *iter, const struct iomap_ops *ops)
ret = 0;
else
ret = 1;
- iomap_iter_reset_iomap(iter);
+ iomap_iter_clean_fbatch(iter);
+ iter->status = 0;
if (ret <= 0)
return ret;
+ memset(&iter->iomap, 0, sizeof(iter->iomap));
+ memset(&iter->srcmap, 0, sizeof(iter->srcmap));
+
begin:
ret = ops->iomap_begin(iter->inode, iter->pos, iter->len, iter->flags,
&iter->iomap, &iter->srcmap);
--
2.39.5 (Apple Git-154)
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2] iomap: avoid memset iomap when iter is done
[not found] ` <20260420073254.996FAC19425@smtp.kernel.org>
@ 2026-04-20 7:56 ` Fengnan Chang
0 siblings, 0 replies; 5+ messages in thread
From: Fengnan Chang @ 2026-04-20 7:56 UTC (permalink / raw)
To: sashiko; +Cc: tytso
在 2026/4/20 15:32, sashiko-bot@kernel.org 写道:
> Sashiko AI review found 1 potential issue(s):
> - [High] Early return paths in `iomap_iter()` bypass `folio_batch` cleanup, leaking page references.
> --
>
> commit 20686db0394fe5c92c4d207b4ec3987147d0e1ab
> Author: Fengnan Chang <fengnanchang@gmail.com>
>
> iomap: avoid memset iomap when iter is done
>
> This commit splits the cleanup logic in iomap_iter() to avoid wasted memory
> writes by skipping the memset of iomap and srcmap when iteration finishes,
> while extracting the folio_batch release into iomap_iter_clean_fbatch().
>
>> However, we MUST still call iomap_iter_reset_iomap() to release the
>> folio_batch if IOMAP_F_FOLIO_BATCH is set, otherwise we leak page
>> references. Therefore, split the cleanup logic: always release the
>> folio_batch, but skip the memset() when ret <= 0.
> Does this actually always release the folio_batch?
Just skip memset, always release the folio_batch.
>
>> diff --git a/fs/iomap/iter.c b/fs/iomap/iter.c
>> index c04796f6e57fa..e4a29829591a7 100644
>> --- a/fs/iomap/iter.c
>> +++ b/fs/iomap/iter.c
> [ ... ]
>> @@ -102,10 +98,14 @@ int iomap_iter(struct iomap_iter *iter, const struct iomap_ops *ops)
>> ret = 0;
>> else
>> ret = 1;
>> - iomap_iter_reset_iomap(iter);
>> + iomap_iter_clean_fbatch(iter);
>> + iter->status = 0;
>> if (ret <= 0)
>> return ret;
>>
>> + memset(&iter->iomap, 0, sizeof(iter->iomap));
>> + memset(&iter->srcmap, 0, sizeof(iter->srcmap));
>> +
>> begin:
>> ret = ops->iomap_begin(iter->inode, iter->pos, iter->len, iter->flags,
>> &iter->iomap, &iter->srcmap);
> If ops->iomap_begin() populates iter->fbatch and sets IOMAP_F_FOLIO_BATCH
> (for example, via iomap_fill_dirty_folios() in
> xfs_buffered_write_iomap_begin()) but subsequently fails, the next lines
> in the function are:
>
> if (ret < 0)
> return ret;
>
> This returns directly and bypasses the iomap_iter_clean_fbatch() call.
>
> There is also a similar early return at the start of iomap_iter() before
> the new cleanup logic:
>
> if (ops->iomap_end) {
> ret = ops->iomap_end(iter->inode, iter->iter_start_pos,
> iomap_length_trim(iter, iter->iter_start_pos,
> olen),
> advanced, iter->flags, &iter->iomap);
> if (ret < 0 && !advanced)
> return ret;
>
> If ops->iomap_end() fails without advancing, this early return also skips
> the cleanup.
>
> Since callers like iomap_zero_range() allocate the batch on the stack and
> rely on iomap_iter() for cleanup, could these error paths leak folio
> references when transient I/O errors occur?
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] iomap: avoid memset iomap when iter is done
2026-04-20 6:16 [PATCH v2] iomap: avoid memset iomap when iter is done Fengnan Chang
[not found] ` <20260420073254.996FAC19425@smtp.kernel.org>
@ 2026-04-22 6:34 ` Christoph Hellwig
2026-04-22 10:59 ` Brian Foster
2026-04-22 12:56 ` Christian Brauner
3 siblings, 0 replies; 5+ messages in thread
From: Christoph Hellwig @ 2026-04-22 6:34 UTC (permalink / raw)
To: Fengnan Chang
Cc: brauner, djwong, hch, linux-xfs, linux-fsdevel, linux-ext4,
lidiangang, Fengnan Chang
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] iomap: avoid memset iomap when iter is done
2026-04-20 6:16 [PATCH v2] iomap: avoid memset iomap when iter is done Fengnan Chang
[not found] ` <20260420073254.996FAC19425@smtp.kernel.org>
2026-04-22 6:34 ` Christoph Hellwig
@ 2026-04-22 10:59 ` Brian Foster
2026-04-22 12:56 ` Christian Brauner
3 siblings, 0 replies; 5+ messages in thread
From: Brian Foster @ 2026-04-22 10:59 UTC (permalink / raw)
To: Fengnan Chang
Cc: brauner, djwong, hch, linux-xfs, linux-fsdevel, linux-ext4,
lidiangang, Fengnan Chang
On Mon, Apr 20, 2026 at 02:16:30PM +0800, Fengnan Chang wrote:
> When iomap_iter() finishes its iteration (returns <= 0), it is no longer
> necessary to memset the entire iomap and srcmap structures.
>
> In high-IOPS scenarios (like 4k randread NVMe polling with io_uring),
> where the majority of I/Os complete in a single extent map, this wasted
> memory write bandwidth, as the caller will just discard the iterator.
> Use this command to test:
> taskset -c 30 ./t/io_uring -p1 -d512 -b4096 -s32 -c32 -F1 -B1 -R1 -X1
> -n1 -P1 /mnt/testfile
> IOPS improve about 5% on ext4 and XFS.
>
> However, we MUST still call iomap_iter_reset_iomap() to release the
> folio_batch if IOMAP_F_FOLIO_BATCH is set, otherwise we leak page
> references. Therefore, split the cleanup logic: always release the
> folio_batch, but skip the memset() when ret <= 0.
>
> Signed-off-by: Fengnan Chang <changfengnan@bytedance.com>
> ---
Reviewed-by: Brian Foster <bfoster@redhat.com>
> fs/iomap/iter.c | 12 ++++++------
> 1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/fs/iomap/iter.c b/fs/iomap/iter.c
> index c04796f6e57f..e4a29829591a 100644
> --- a/fs/iomap/iter.c
> +++ b/fs/iomap/iter.c
> @@ -6,17 +6,13 @@
> #include <linux/iomap.h>
> #include "trace.h"
>
> -static inline void iomap_iter_reset_iomap(struct iomap_iter *iter)
> +static inline void iomap_iter_clean_fbatch(struct iomap_iter *iter)
> {
> if (iter->iomap.flags & IOMAP_F_FOLIO_BATCH) {
> folio_batch_release(iter->fbatch);
> folio_batch_reinit(iter->fbatch);
> iter->iomap.flags &= ~IOMAP_F_FOLIO_BATCH;
> }
> -
> - iter->status = 0;
> - memset(&iter->iomap, 0, sizeof(iter->iomap));
> - memset(&iter->srcmap, 0, sizeof(iter->srcmap));
> }
>
> /* Advance the current iterator position and decrement the remaining length */
> @@ -102,10 +98,14 @@ int iomap_iter(struct iomap_iter *iter, const struct iomap_ops *ops)
> ret = 0;
> else
> ret = 1;
> - iomap_iter_reset_iomap(iter);
> + iomap_iter_clean_fbatch(iter);
> + iter->status = 0;
> if (ret <= 0)
> return ret;
>
> + memset(&iter->iomap, 0, sizeof(iter->iomap));
> + memset(&iter->srcmap, 0, sizeof(iter->srcmap));
> +
> begin:
> ret = ops->iomap_begin(iter->inode, iter->pos, iter->len, iter->flags,
> &iter->iomap, &iter->srcmap);
> --
> 2.39.5 (Apple Git-154)
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] iomap: avoid memset iomap when iter is done
2026-04-20 6:16 [PATCH v2] iomap: avoid memset iomap when iter is done Fengnan Chang
` (2 preceding siblings ...)
2026-04-22 10:59 ` Brian Foster
@ 2026-04-22 12:56 ` Christian Brauner
3 siblings, 0 replies; 5+ messages in thread
From: Christian Brauner @ 2026-04-22 12:56 UTC (permalink / raw)
To: djwong, hch, linux-xfs, linux-fsdevel, linux-ext4, Fengnan Chang
Cc: Christian Brauner, lidiangang, Fengnan Chang
On Mon, 20 Apr 2026 14:16:30 +0800, Fengnan Chang wrote:
> When iomap_iter() finishes its iteration (returns <= 0), it is no longer
> necessary to memset the entire iomap and srcmap structures.
>
> In high-IOPS scenarios (like 4k randread NVMe polling with io_uring),
> where the majority of I/Os complete in a single extent map, this wasted
> memory write bandwidth, as the caller will just discard the iterator.
> Use this command to test:
> taskset -c 30 ./t/io_uring -p1 -d512 -b4096 -s32 -c32 -F1 -B1 -R1 -X1
> -n1 -P1 /mnt/testfile
> IOPS improve about 5% on ext4 and XFS.
>
> [...]
Applied to the vfs-7.2.iomap branch of the vfs/vfs.git tree.
Patches in the vfs-7.2.iomap branch should appear in linux-next soon.
Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.
It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.
Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. If in doubt, please check the listed branch.
tree: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: master
[1/1] iomap: avoid memset iomap when iter is done
https://git.kernel.org/vfs/vfs/c/72fa5c7e5c81
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-04-22 12:56 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-20 6:16 [PATCH v2] iomap: avoid memset iomap when iter is done Fengnan Chang
[not found] ` <20260420073254.996FAC19425@smtp.kernel.org>
2026-04-20 7:56 ` Fengnan Chang
2026-04-22 6:34 ` Christoph Hellwig
2026-04-22 10:59 ` Brian Foster
2026-04-22 12:56 ` Christian Brauner
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.