linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] btrfs: de-couple subpage locked and delalloc range
@ 2024-09-15 23:11 Qu Wenruo
  2024-09-15 23:11 ` [PATCH 1/2] btrfs: move the delalloc range bitmap search into extent_io.c Qu Wenruo
  2024-09-15 23:11 ` [PATCH 2/2] btrfs: mark all dirty sectors as locked inside writepage_delalloc() Qu Wenruo
  0 siblings, 2 replies; 3+ messages in thread
From: Qu Wenruo @ 2024-09-15 23:11 UTC (permalink / raw)
  To: linux-btrfs

Since commit d034cdb4cc8a ("btrfs: lock subpage ranges in one go for
writepage_delalloc()") btrfs uses subpage locked bitmap to trace all the
locked delalloc ranges, and that commits provides the basis for mixing
async and non-async submission inside the same page.

But that locked bitmap is not a perfect match to trace delalloc ranges,
as we can have the following case: (64K page size)

        0       32K      64K      96K       128K
        |       |////////||///////|    |////|
                                       120K

In above case, writepage_delalloc() for page 0 will find
and lock the delalloc range [32K, 96K), which is beyond the page
boundary.

Then when writepage_delalloc() is called for the page 64K, since [64K,
96K) is already locked, only [120K, 128K) will be locked.

This means, although range [64K, 96K) is dirty and will be submitted
later by extent_writepage_io(), it will not be marked as locked.

This is fine for now, as we call btrfs_folio_end_writer_lock_bitmap() to
free every non-compressed sector, and compression is only allowed for
full page range.

But this is not safe for future sector perfect compression support, as
this can lead to double folio unlock, if [32K, 96K) is submitted without
compression but [120K, 128K) is.

              Thread A                 |           Thread B
---------------------------------------+--------------------------------
                                       | submit_one_async_extent()
				       | |- extent_clear_unlock_delalloc()
extent_writepage()                     |    |- btrfs_folio_end_writer_lock()
|- btrfs_folio_edn_writer_lock_bitmap()|       |- btrfs_subpage_end_and_test_writer()
   |                                   |       |  |- atomic_sub_and_test()
   |                                   |       |     /* Now the atomic value is 0 */
   |- if (atomic_read() == 0)          |       |
   |- folio_unlock()                   |       |- folio_unlock()

The root cause is the above range [64K, 96K) is dirtied and should also
be locked but it isn't.

So to make everything more consistent and prepare for the incoming
sector perfect compression, mark all dirty sectors as locked.

The first patch is to introduce a new bitmap locally inside
writepage_delalloc().
The second patch is to fully de-couple locked bitmap from delalloc
range, and lock all dirty sectors.

Qu Wenruo (2):
  btrfs: move the delalloc range bitmap search into extent_io.c
  btrfs: mark all dirty sectors as locked inside writepage_delalloc()

 fs/btrfs/extent_io.c | 54 ++++++++++++++++++++++++++++++++++++++++----
 fs/btrfs/subpage.c   | 47 --------------------------------------
 fs/btrfs/subpage.h   |  4 ----
 3 files changed, 50 insertions(+), 55 deletions(-)

-- 
2.46.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2024-09-15 23:12 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-15 23:11 [PATCH 0/2] btrfs: de-couple subpage locked and delalloc range Qu Wenruo
2024-09-15 23:11 ` [PATCH 1/2] btrfs: move the delalloc range bitmap search into extent_io.c Qu Wenruo
2024-09-15 23:11 ` [PATCH 2/2] btrfs: mark all dirty sectors as locked inside writepage_delalloc() Qu Wenruo

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).