* [PATCH 0/2] btrfs: minor cleanup related to bitmap operations
@ 2025-12-10 8:32 Qu Wenruo
2025-12-10 8:32 ` [PATCH 1/2] btrfs: integrate the error handling of submit_one_sector() Qu Wenruo
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Qu Wenruo @ 2025-12-10 8:32 UTC (permalink / raw)
To: linux-btrfs
This is the safer cleanup part extracted from the previous attempt:
https://lore.kernel.org/linux-btrfs/cover.1763629982.git.wqu@suse.com/
The first patch is to concentrate the error handling of
submit_one_sector() so we do not have two separate error handling.
The second patch is the convert for_each_set_bit() to a more efficient
for_each_set_bitmap() so that we can benefit from functions which
accept a range other than a single block.
Qu Wenruo (2):
btrfs: integrate the error handling of submit_one_sector()
btrfs: replace for_each_set_bit() with for_each_set_bitmap()
fs/btrfs/extent_io.c | 55 +++++++++++++++++++++++++-------------------
1 file changed, 31 insertions(+), 24 deletions(-)
--
2.52.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/2] btrfs: integrate the error handling of submit_one_sector()
2025-12-10 8:32 [PATCH 0/2] btrfs: minor cleanup related to bitmap operations Qu Wenruo
@ 2025-12-10 8:32 ` Qu Wenruo
2025-12-10 8:32 ` [PATCH 2/2] btrfs: replace for_each_set_bit() with for_each_set_bitmap() Qu Wenruo
2025-12-11 18:40 ` [PATCH 0/2] btrfs: minor cleanup related to bitmap operations David Sterba
2 siblings, 0 replies; 4+ messages in thread
From: Qu Wenruo @ 2025-12-10 8:32 UTC (permalink / raw)
To: linux-btrfs; +Cc: Boris Burkov
Currently submit_one_sector() has only one failure pattern from
btrfs_get_extent().
However the error handling is split into two parts, one inside
submit_one_sector(), which clears the dirty flag and finishes the
writeback for the fs block.
The other part is to submit any remaining bio inside bio_ctrl and mark
the ordered extent finished for the fs block.
There is no special reason that we must split the error handling, let's
just concentrate all the error handling into submit_one_sector().
Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
fs/btrfs/extent_io.c | 29 +++++++++++++++--------------
1 file changed, 15 insertions(+), 14 deletions(-)
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 629fd5af4286..49606a01039e 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -1598,7 +1598,7 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode,
/*
* Return 0 if we have submitted or queued the sector for submission.
- * Return <0 for critical errors, and the sector will have its dirty flag cleared.
+ * Return <0 for critical errors, and the involved sector will be cleaned up.
*
* Caller should make sure filepos < i_size and handle filepos >= i_size case.
*/
@@ -1622,6 +1622,13 @@ static int submit_one_sector(struct btrfs_inode *inode,
em = btrfs_get_extent(inode, NULL, filepos, sectorsize);
if (IS_ERR(em)) {
+ /*
+ * bio_ctrl may contain a bio crossing several folios.
+ * Submit it immediately so that the bio has a chance
+ * to finish normally, other than marked as error.
+ */
+ submit_one_bio(bio_ctrl);
+
/*
* When submission failed, we should still clear the folio dirty.
* Or the folio will be written back again but without any
@@ -1630,6 +1637,13 @@ static int submit_one_sector(struct btrfs_inode *inode,
btrfs_folio_clear_dirty(fs_info, folio, filepos, sectorsize);
btrfs_folio_set_writeback(fs_info, folio, filepos, sectorsize);
btrfs_folio_clear_writeback(fs_info, folio, filepos, sectorsize);
+
+ /*
+ * Since there is no bio submitted to finish the ordered
+ * extent, we have to manually finish this sector.
+ */
+ btrfs_mark_ordered_io_finished(inode, folio, filepos,
+ fs_info->sectorsize, false);
return PTR_ERR(em);
}
@@ -1756,19 +1770,6 @@ static noinline_for_stack int extent_writepage_io(struct btrfs_inode *inode,
}
ret = submit_one_sector(inode, folio, cur, bio_ctrl, i_size);
if (unlikely(ret < 0)) {
- /*
- * bio_ctrl may contain a bio crossing several folios.
- * Submit it immediately so that the bio has a chance
- * to finish normally, other than marked as error.
- */
- submit_one_bio(bio_ctrl);
- /*
- * Failed to grab the extent map which should be very rare.
- * Since there is no bio submitted to finish the ordered
- * extent, we have to manually finish this sector.
- */
- btrfs_mark_ordered_io_finished(inode, folio, cur,
- fs_info->sectorsize, false);
if (!found_error)
found_error = ret;
continue;
--
2.52.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] btrfs: replace for_each_set_bit() with for_each_set_bitmap()
2025-12-10 8:32 [PATCH 0/2] btrfs: minor cleanup related to bitmap operations Qu Wenruo
2025-12-10 8:32 ` [PATCH 1/2] btrfs: integrate the error handling of submit_one_sector() Qu Wenruo
@ 2025-12-10 8:32 ` Qu Wenruo
2025-12-11 18:40 ` [PATCH 0/2] btrfs: minor cleanup related to bitmap operations David Sterba
2 siblings, 0 replies; 4+ messages in thread
From: Qu Wenruo @ 2025-12-10 8:32 UTC (permalink / raw)
To: linux-btrfs; +Cc: Boris Burkov
Inside extent_io.c, there are several simple call sites doing things
like:
for_each_set_bit(bit, bitmap, bitmap_size) {
/* handle one fs block */
}
The workload includes:
- set_bit()
Inside extent_writepage_io().
This can be replaced with a bitmap_set().
- btrfs_folio_set_lock()
- btrfs_mark_ordered_io_finished()
Inside writepage_delalloc().
Instead of calling it multiple times, we can pass a range into the
function with one call.
Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
fs/btrfs/extent_io.c | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 49606a01039e..11c2dee7d363 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -1426,8 +1426,9 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode,
u64 delalloc_start = page_start;
u64 delalloc_end = page_end;
u64 delalloc_to_write = 0;
+ unsigned int start_bit;
+ unsigned int end_bit;
int ret = 0;
- int bit;
/* Save the dirty bitmap as our submission bitmap will be a subset of it. */
if (btrfs_is_subpage(fs_info, folio)) {
@@ -1437,10 +1438,12 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode,
bio_ctrl->submit_bitmap = 1;
}
- for_each_set_bit(bit, &bio_ctrl->submit_bitmap, blocks_per_folio) {
- u64 start = page_start + (bit << fs_info->sectorsize_bits);
+ for_each_set_bitrange(start_bit, end_bit, &bio_ctrl->submit_bitmap,
+ blocks_per_folio) {
+ u64 start = page_start + (start_bit << fs_info->sectorsize_bits);
+ u32 len = (end_bit - start_bit) << fs_info->sectorsize_bits;
- btrfs_folio_set_lock(fs_info, folio, start, fs_info->sectorsize);
+ btrfs_folio_set_lock(fs_info, folio, start, len);
}
/* Lock all (subpage) delalloc ranges inside the folio first. */
@@ -1557,10 +1560,13 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode,
fs_info->sectorsize_bits,
blocks_per_folio);
- for_each_set_bit(bit, &bio_ctrl->submit_bitmap, bitmap_size)
- btrfs_mark_ordered_io_finished(inode, folio,
- page_start + (bit << fs_info->sectorsize_bits),
- fs_info->sectorsize, false);
+ for_each_set_bitrange(start_bit, end_bit, &bio_ctrl->submit_bitmap,
+ bitmap_size) {
+ u64 start = page_start + (start_bit << fs_info->sectorsize_bits);
+ u32 len = (end_bit - start_bit) << fs_info->sectorsize_bits;
+
+ btrfs_mark_ordered_io_finished(inode, folio, start, len, false);
+ }
return ret;
}
out:
@@ -1728,8 +1734,8 @@ static noinline_for_stack int extent_writepage_io(struct btrfs_inode *inode,
return ret;
}
- for (cur = start; cur < end; cur += fs_info->sectorsize)
- set_bit((cur - folio_start) >> fs_info->sectorsize_bits, &range_bitmap);
+ bitmap_set(&range_bitmap, (start - folio_pos(folio)) >> fs_info->sectorsize_bits,
+ len >> fs_info->sectorsize_bits);
bitmap_and(&bio_ctrl->submit_bitmap, &bio_ctrl->submit_bitmap, &range_bitmap,
blocks_per_folio);
--
2.52.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 0/2] btrfs: minor cleanup related to bitmap operations
2025-12-10 8:32 [PATCH 0/2] btrfs: minor cleanup related to bitmap operations Qu Wenruo
2025-12-10 8:32 ` [PATCH 1/2] btrfs: integrate the error handling of submit_one_sector() Qu Wenruo
2025-12-10 8:32 ` [PATCH 2/2] btrfs: replace for_each_set_bit() with for_each_set_bitmap() Qu Wenruo
@ 2025-12-11 18:40 ` David Sterba
2 siblings, 0 replies; 4+ messages in thread
From: David Sterba @ 2025-12-11 18:40 UTC (permalink / raw)
To: Qu Wenruo; +Cc: linux-btrfs
On Wed, Dec 10, 2025 at 07:02:32PM +1030, Qu Wenruo wrote:
> This is the safer cleanup part extracted from the previous attempt:
> https://lore.kernel.org/linux-btrfs/cover.1763629982.git.wqu@suse.com/
>
> The first patch is to concentrate the error handling of
> submit_one_sector() so we do not have two separate error handling.
>
> The second patch is the convert for_each_set_bit() to a more efficient
> for_each_set_bitmap() so that we can benefit from functions which
> accept a range other than a single block.
>
> Qu Wenruo (2):
> btrfs: integrate the error handling of submit_one_sector()
> btrfs: replace for_each_set_bit() with for_each_set_bitmap()
Reviewed-by: David Sterba <dsterba@suse.com>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-12-11 18:40 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-10 8:32 [PATCH 0/2] btrfs: minor cleanup related to bitmap operations Qu Wenruo
2025-12-10 8:32 ` [PATCH 1/2] btrfs: integrate the error handling of submit_one_sector() Qu Wenruo
2025-12-10 8:32 ` [PATCH 2/2] btrfs: replace for_each_set_bit() with for_each_set_bitmap() Qu Wenruo
2025-12-11 18:40 ` [PATCH 0/2] btrfs: minor cleanup related to bitmap operations David Sterba
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox