From: Brian Foster <bfoster@redhat.com>
To: Joanne Koong <joannelkoong@gmail.com>
Cc: linux-mm@kvack.org, brauner@kernel.org, willy@infradead.org,
jack@suse.cz, hch@infradead.org, djwong@kernel.org,
jlayton@kernel.org, linux-fsdevel@vger.kernel.org,
kernel-team@meta.com
Subject: Re: [PATCH v2 10/12] iomap: refactor dirty bitmap iteration
Date: Wed, 3 Sep 2025 14:53:33 -0400 [thread overview]
Message-ID: <aLiOrcetNAvjvjtk@bfoster> (raw)
In-Reply-To: <20250829233942.3607248-11-joannelkoong@gmail.com>
On Fri, Aug 29, 2025 at 04:39:40PM -0700, Joanne Koong wrote:
> Use find_next_bit()/find_next_zero_bit() for iomap dirty bitmap
> iteration. This uses __ffs() internally and is more efficient for
> finding the next dirty or clean bit than manually iterating through the
> bitmap range testing every bit.
>
> Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
> Suggested-by: Christoph Hellwig <hch@infradead.org>
> ---
> fs/iomap/buffered-io.c | 67 ++++++++++++++++++++++++++++++------------
> 1 file changed, 48 insertions(+), 19 deletions(-)
>
> diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
> index fd827398afd2..dc1a1f371412 100644
> --- a/fs/iomap/buffered-io.c
> +++ b/fs/iomap/buffered-io.c
> @@ -75,13 +75,42 @@ static void iomap_set_range_uptodate(struct folio *folio, size_t off,
> folio_mark_uptodate(folio);
> }
>
> -static inline bool ifs_block_is_dirty(struct folio *folio,
> - struct iomap_folio_state *ifs, int block)
> +/**
> + * ifs_next_dirty_block - find the next dirty block in the folio
> + * @folio: The folio
> + * @start_blk: Block number to begin searching at
> + * @end_blk: Last block number (inclusive) to search
> + *
> + * If no dirty block is found, this will return end_blk + 1.
> + */
> +static unsigned ifs_next_dirty_block(struct folio *folio,
> + unsigned start_blk, unsigned end_blk)
> {
> + struct iomap_folio_state *ifs = folio->private;
> struct inode *inode = folio->mapping->host;
> - unsigned int blks_per_folio = i_blocks_per_folio(inode, folio);
> + unsigned int blks = i_blocks_per_folio(inode, folio);
> +
> + return find_next_bit(ifs->state, blks + end_blk + 1,
> + blks + start_blk) - blks;
> +}
> +
> +/**
> + * ifs_next_clean_block - find the next clean block in the folio
> + * @folio: The folio
> + * @start_blk: Block number to begin searching at
> + * @end_blk: Last block number (inclusive) to search
> + *
> + * If no clean block is found, this will return end_blk + 1.
> + */
> +static unsigned ifs_next_clean_block(struct folio *folio,
> + unsigned start_blk, unsigned end_blk)
> +{
> + struct iomap_folio_state *ifs = folio->private;
> + struct inode *inode = folio->mapping->host;
> + unsigned int blks = i_blocks_per_folio(inode, folio);
>
> - return test_bit(block + blks_per_folio, ifs->state);
> + return find_next_zero_bit(ifs->state, blks + end_blk + 1,
> + blks + start_blk) - blks;
> }
>
> static unsigned ifs_find_dirty_range(struct folio *folio,
> @@ -92,18 +121,15 @@ static unsigned ifs_find_dirty_range(struct folio *folio,
> offset_in_folio(folio, *range_start) >> inode->i_blkbits;
> unsigned end_blk = min_not_zero(
> offset_in_folio(folio, range_end) >> inode->i_blkbits,
> - i_blocks_per_folio(inode, folio));
> - unsigned nblks = 1;
> + i_blocks_per_folio(inode, folio)) - 1;
> + unsigned nblks;
>
> - while (!ifs_block_is_dirty(folio, ifs, start_blk))
> - if (++start_blk == end_blk)
> - return 0;
> + start_blk = ifs_next_dirty_block(folio, start_blk, end_blk);
> + if (start_blk > end_blk)
> + return 0;
>
> - while (start_blk + nblks < end_blk) {
> - if (!ifs_block_is_dirty(folio, ifs, start_blk + nblks))
> - break;
> - nblks++;
> - }
> + nblks = ifs_next_clean_block(folio, start_blk + 1, end_blk)
> + - start_blk;
Not a critical problem since it looks like the helper bumps end_blk, but
something that stands out to me here as mildly annoying is that we check
for (start > end) just above, clearly implying that start == end is
possible, then go and pass start + 1 and end to the next call. It's not
clear to me if that's worth changing to make end exclusive, but may be
worth thinking about if you haven't already..
Brian
>
> *range_start = folio_pos(folio) + (start_blk << inode->i_blkbits);
> return nblks << inode->i_blkbits;
> @@ -1077,7 +1103,7 @@ static void iomap_write_delalloc_ifs_punch(struct inode *inode,
> struct folio *folio, loff_t start_byte, loff_t end_byte,
> struct iomap *iomap, iomap_punch_t punch)
> {
> - unsigned int first_blk, last_blk, i;
> + unsigned int first_blk, last_blk;
> loff_t last_byte;
> u8 blkbits = inode->i_blkbits;
> struct iomap_folio_state *ifs;
> @@ -1096,10 +1122,13 @@ static void iomap_write_delalloc_ifs_punch(struct inode *inode,
> folio_pos(folio) + folio_size(folio) - 1);
> first_blk = offset_in_folio(folio, start_byte) >> blkbits;
> last_blk = offset_in_folio(folio, last_byte) >> blkbits;
> - for (i = first_blk; i <= last_blk; i++) {
> - if (!ifs_block_is_dirty(folio, ifs, i))
> - punch(inode, folio_pos(folio) + (i << blkbits),
> - 1 << blkbits, iomap);
> + while (first_blk <= last_blk) {
> + first_blk = ifs_next_clean_block(folio, first_blk, last_blk);
> + if (first_blk > last_blk)
> + break;
> + punch(inode, folio_pos(folio) + (first_blk << blkbits),
> + 1 << blkbits, iomap);
> + first_blk++;
> }
> }
>
> --
> 2.47.3
>
>
next prev parent reply other threads:[~2025-09-03 18:49 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-29 23:39 [PATCH v2 00/12] mm/iomap: add granular dirty and writeback accounting Joanne Koong
2025-08-29 23:39 ` [PATCH v2 01/12] mm: pass number of pages to __folio_start_writeback() Joanne Koong
2025-09-03 11:48 ` David Hildenbrand
2025-09-03 20:02 ` Darrick J. Wong
2025-09-03 20:05 ` David Hildenbrand
2025-09-03 23:12 ` Joanne Koong
2025-08-29 23:39 ` [PATCH v2 02/12] mm: pass number of pages to __folio_end_writeback() Joanne Koong
2025-08-29 23:39 ` [PATCH v2 03/12] mm: add folio_end_writeback_pages() helper Joanne Koong
2025-08-29 23:39 ` [PATCH v2 04/12] mm: pass number of pages dirtied to __folio_mark_dirty() Joanne Koong
2025-08-29 23:39 ` [PATCH v2 05/12] mm: add filemap_dirty_folio_pages() helper Joanne Koong
2025-08-29 23:39 ` [PATCH v2 06/12] mm: add __folio_clear_dirty_for_io() helper Joanne Koong
2025-08-29 23:39 ` [PATCH v2 07/12] mm: add no_stats_accounting bitfield to wbc Joanne Koong
2025-08-29 23:39 ` [PATCH v2 08/12] mm: refactor clearing dirty stats into helper function Joanne Koong
2025-08-29 23:39 ` [PATCH v2 09/12] mm: add clear_dirty_for_io_stats() helper Joanne Koong
2025-08-29 23:39 ` [PATCH v2 10/12] iomap: refactor dirty bitmap iteration Joanne Koong
2025-09-03 18:53 ` Brian Foster [this message]
2025-09-03 19:59 ` Darrick J. Wong
2025-10-03 22:27 ` Joanne Koong
2025-10-04 1:11 ` Joanne Koong
2025-08-29 23:39 ` [PATCH v2 11/12] iomap: refactor uptodate " Joanne Koong
2025-08-29 23:39 ` [PATCH v2 12/12] iomap: add granular dirty and writeback accounting Joanne Koong
2025-09-02 23:46 ` Darrick J. Wong
2025-09-03 18:48 ` Brian Foster
2025-09-04 0:35 ` Joanne Koong
2025-09-04 2:52 ` Darrick J. Wong
2025-09-04 11:47 ` Brian Foster
2025-09-04 20:07 ` Darrick J. Wong
2025-09-05 0:14 ` Joanne Koong
2025-09-05 11:19 ` Brian Foster
2025-09-05 12:43 ` Jan Kara
2025-09-05 23:30 ` Joanne Koong
2025-09-04 8:53 ` [PATCH v2 00/12] mm/iomap: " Jan Kara
2025-09-04 23:59 ` Joanne Koong
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=aLiOrcetNAvjvjtk@bfoster \
--to=bfoster@redhat.com \
--cc=brauner@kernel.org \
--cc=djwong@kernel.org \
--cc=hch@infradead.org \
--cc=jack@suse.cz \
--cc=jlayton@kernel.org \
--cc=joannelkoong@gmail.com \
--cc=kernel-team@meta.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=willy@infradead.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 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.