diff options
| author | Qu Wenruo <wqu@suse.com> | 2026-05-09 18:36:31 +0930 |
|---|---|---|
| committer | David Sterba <dsterba@suse.com> | 2026-06-08 15:53:32 +0200 |
| commit | 0e7fff6ecaea56b410d77cf7a738ef588d12251a (patch) | |
| tree | 27ee5ec51ca28a7e7be9b3b454dc22b915d34567 | |
| parent | 0af37c217edf15fa21dac1c40822086df356c6bb (diff) | |
| download | linux-stable-0e7fff6ecaea56b410d77cf7a738ef588d12251a.tar.gz linux-stable-0e7fff6ecaea56b410d77cf7a738ef588d12251a.zip | |
btrfs: remove locked subpage bitmap
Currently there are two members inside btrfs_folio_state that are related
to locked bitmap:
- locked sub-bitmap inside btrfs_folio_state::bitmaps[]
The enum btrfs_bitmap_nr_locked determines the sub-bitmap.
- btrfs_folio_state::nr_locked
Which records how many blocks are locked inside the folio.
The locked sub-bitmap is a btrfs specific per-block tracking mechanism,
which is mostly for async-submission, utilized by compressed writes.
The sub-bitmap itself is a super set of nr_locked, as it can provide a
more reliable tracking.
But the sub-bitmap itself can be pretty large for the incoming huge
folio, 2M sized folio for 4K page size, meaning 512 bits for one
sub-bitmap.
Furthermore, in the long run compression will be reworked to get rid of
async-submission completely, there is not much need for a full
sub-bitmap to track the locked status.
This patch removes the locked sub-bitmap and only relies on @nr_locked
atomic to do the tracking.
This can also save 64 bytes from btrfs_folio_state::bitmaps[] for a huge
folio.
This will reduce some safety checks, as previously if a block is not
locked, btrfs_folio_end_lock()/btrfs_folio_end_lock_bitmap() will find
out that, and skip reducing @nr_locked for that block, and avoid
under-flow.
But this safety net itself shouldn't be necessary in the first place.
If we're unlocking a block that is not locked, it's a bug in the logic,
and we should catch it, not silently ignoring it.
Thus I believe the removal of the extra safety net should not be a
problem.
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
| -rw-r--r-- | fs/btrfs/subpage.c | 45 | ||||
| -rw-r--r-- | fs/btrfs/subpage.h | 10 |
2 files changed, 10 insertions, 45 deletions
diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c index 8a09f34ea31e..ff68e79fe72d 100644 --- a/fs/btrfs/subpage.c +++ b/fs/btrfs/subpage.c @@ -224,11 +224,8 @@ static bool btrfs_subpage_end_and_test_lock(const struct btrfs_fs_info *fs_info, struct folio *folio, u64 start, u32 len) { struct btrfs_folio_state *bfs = folio_get_private(folio); - const int start_bit = subpage_calc_start_bit(fs_info, folio, locked, start, len); const int nbits = (len >> fs_info->sectorsize_bits); unsigned long flags; - unsigned int cleared = 0; - int bit = start_bit; bool last; btrfs_subpage_assert(fs_info, folio, start, len); @@ -245,15 +242,10 @@ static bool btrfs_subpage_end_and_test_lock(const struct btrfs_fs_info *fs_info, spin_unlock_irqrestore(&bfs->lock, flags); return true; } - - for_each_set_bit_from(bit, bfs->bitmaps, start_bit + nbits) { - clear_bit(bit, bfs->bitmaps); - cleared++; - } - ASSERT(atomic_read(&bfs->nr_locked) >= cleared, - "atomic_read(&bfs->nr_locked)=%d cleared=%d", - atomic_read(&bfs->nr_locked), cleared); - last = atomic_sub_and_test(cleared, &bfs->nr_locked); + ASSERT(atomic_read(&bfs->nr_locked) >= nbits, + "atomic_read(&bfs->nr_locked)=%d nbits=%d", + atomic_read(&bfs->nr_locked), nbits); + last = atomic_sub_and_test(nbits, &bfs->nr_locked); spin_unlock_irqrestore(&bfs->lock, flags); return last; } @@ -309,11 +301,9 @@ void btrfs_folio_end_lock_bitmap(const struct btrfs_fs_info *fs_info, { struct btrfs_folio_state *bfs = folio_get_private(folio); const unsigned int blocks_per_folio = btrfs_blocks_per_folio(fs_info, folio); - const int start_bit = blocks_per_folio * btrfs_bitmap_nr_locked; + const unsigned int nbits = bitmap_weight(&bitmap, blocks_per_folio); unsigned long flags; bool last = false; - int cleared = 0; - int bit; if (!btrfs_is_subpage(fs_info, folio)) { folio_unlock(folio); @@ -327,14 +317,10 @@ void btrfs_folio_end_lock_bitmap(const struct btrfs_fs_info *fs_info, } spin_lock_irqsave(&bfs->lock, flags); - for_each_set_bit(bit, &bitmap, blocks_per_folio) { - if (test_and_clear_bit(bit + start_bit, bfs->bitmaps)) - cleared++; - } - ASSERT(atomic_read(&bfs->nr_locked) >= cleared, - "atomic_read(&bfs->nr_locked)=%d cleared=%d", - atomic_read(&bfs->nr_locked), cleared); - last = atomic_sub_and_test(cleared, &bfs->nr_locked); + ASSERT(atomic_read(&bfs->nr_locked) >= nbits, + "atomic_read(&bfs->nr_locked)=%d nbits=%d", + atomic_read(&bfs->nr_locked), nbits); + last = atomic_sub_and_test(nbits, &bfs->nr_locked); spin_unlock_irqrestore(&bfs->lock, flags); if (last) folio_unlock(folio); @@ -696,7 +682,6 @@ void btrfs_folio_set_lock(const struct btrfs_fs_info *fs_info, { struct btrfs_folio_state *bfs; unsigned long flags; - unsigned int start_bit; unsigned int nbits; int ret; @@ -705,15 +690,8 @@ void btrfs_folio_set_lock(const struct btrfs_fs_info *fs_info, return; bfs = folio_get_private(folio); - start_bit = subpage_calc_start_bit(fs_info, folio, locked, start, len); nbits = len >> fs_info->sectorsize_bits; spin_lock_irqsave(&bfs->lock, flags); - /* Target range should not yet be locked. */ - if (unlikely(!bitmap_test_range_all_zero(bfs->bitmaps, start_bit, nbits))) { - SUBPAGE_DUMP_BITMAP(fs_info, folio, locked, start, len); - ASSERT(bitmap_test_range_all_zero(bfs->bitmaps, start_bit, nbits)); - } - bitmap_set(bfs->bitmaps, start_bit, nbits); ret = atomic_add_return(nbits, &bfs->nr_locked); ASSERT(ret <= btrfs_blocks_per_folio(fs_info, folio)); spin_unlock_irqrestore(&bfs->lock, flags); @@ -750,7 +728,6 @@ void __cold btrfs_subpage_dump_bitmap(const struct btrfs_fs_info *fs_info, unsigned long dirty_bitmap; unsigned long writeback_bitmap; unsigned long ordered_bitmap; - unsigned long locked_bitmap; unsigned long flags; ASSERT(folio_test_private(folio) && folio_get_private(folio)); @@ -762,16 +739,14 @@ void __cold btrfs_subpage_dump_bitmap(const struct btrfs_fs_info *fs_info, GET_SUBPAGE_BITMAP(fs_info, folio, dirty, &dirty_bitmap); GET_SUBPAGE_BITMAP(fs_info, folio, writeback, &writeback_bitmap); GET_SUBPAGE_BITMAP(fs_info, folio, ordered, &ordered_bitmap); - GET_SUBPAGE_BITMAP(fs_info, folio, locked, &locked_bitmap); spin_unlock_irqrestore(&bfs->lock, flags); dump_page(folio_page(folio, 0), "btrfs folio state dump"); btrfs_warn(fs_info, -"start=%llu len=%u page=%llu, bitmaps uptodate=%*pbl dirty=%*pbl locked=%*pbl writeback=%*pbl ordered=%*pbl", +"start=%llu len=%u page=%llu, bitmaps uptodate=%*pbl dirty=%*pbl writeback=%*pbl ordered=%*pbl", start, len, folio_pos(folio), blocks_per_folio, &uptodate_bitmap, blocks_per_folio, &dirty_bitmap, - blocks_per_folio, &locked_bitmap, blocks_per_folio, &writeback_bitmap, blocks_per_folio, &ordered_bitmap); } diff --git a/fs/btrfs/subpage.h b/fs/btrfs/subpage.h index fdea0b605bfc..ccdb817381dd 100644 --- a/fs/btrfs/subpage.h +++ b/fs/btrfs/subpage.h @@ -45,16 +45,6 @@ enum { */ btrfs_bitmap_nr_ordered, - /* - * The locked bit is for async delalloc range (compression), currently - * async extent is queued with the range locked, until the compression - * is done. - * So an async extent can unlock the range at any random timing. - * - * This will need a rework on the async extent lifespan (mark writeback - * and do compression) before deprecating this flag. - */ - btrfs_bitmap_nr_locked, btrfs_bitmap_nr_max }; |
