]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
btrfs: simplify subpage handling of btrfs_clear_buffer_dirty()
authorQu Wenruo <wqu@suse.com>
Wed, 29 Jan 2025 03:23:17 +0000 (13:53 +1030)
committerDavid Sterba <dsterba@suse.com>
Tue, 18 Mar 2025 19:35:42 +0000 (20:35 +0100)
The function btrfs_clear_buffer_dirty() is called on dirty extent buffer
that will not be written back.

The function will call btree_clear_folio_dirty() to clear the folio
dirty flag and also clear PAGECACHE_TAG_DIRTY flag.

And we split the subpage and regular handling, as for subpage cases we
should only clear PAGECACHE_TAG_DIRTY if the last dirty extent buffer in
the page is cleared.

So here we can simplify the function by:

- Use the newly introduced btrfs_meta_folio_clear_and_test_dirty() helper
  The helper will return true if we cleared the folio dirty flag.
  With that we can use the same helper for both subpage and regular
  cases.

- Rename btree_clear_folio_dirty() to btree_clear_folio_dirty_tag()
  As we move the folio dirty clearing in the btrfs_clear_buffer_dirty().

- Call btrfs_meta_folio_clear_and_test_dirty() to clear the dirty flags
  for both regular and subpage metadata cases

- Only call btree_clear_folio_dirty_tag() when the folio is no longer
  dirty

- Update the comment inside set_extent_buffer_dirty()
  As there is no separate clear_subpage_extent_buffer_dirty() anymore.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/extent_io.c
fs/btrfs/subpage.c
fs/btrfs/subpage.h

index dbf4fb1fc2d194ff4f2a2a88c93c4773dd3b632f..354dd25225311d7f34270ef7fc1c9ea4783f2e36 100644 (file)
@@ -3337,11 +3337,10 @@ void free_extent_buffer_stale(struct extent_buffer *eb)
        release_extent_buffer(eb);
 }
 
-static void btree_clear_folio_dirty(struct folio *folio)
+static void btree_clear_folio_dirty_tag(struct folio *folio)
 {
-       ASSERT(folio_test_dirty(folio));
+       ASSERT(!folio_test_dirty(folio));
        ASSERT(folio_test_locked(folio));
-       folio_clear_dirty_for_io(folio);
        xa_lock_irq(&folio->mapping->i_pages);
        if (!folio_test_dirty(folio))
                __xa_clear_mark(&folio->mapping->i_pages,
@@ -3349,26 +3348,11 @@ static void btree_clear_folio_dirty(struct folio *folio)
        xa_unlock_irq(&folio->mapping->i_pages);
 }
 
-static void clear_subpage_extent_buffer_dirty(const struct extent_buffer *eb)
-{
-       struct btrfs_fs_info *fs_info = eb->fs_info;
-       struct folio *folio = eb->folios[0];
-       bool last;
-
-       /* btree_clear_folio_dirty() needs page locked. */
-       folio_lock(folio);
-       last = btrfs_subpage_clear_and_test_dirty(fs_info, folio, eb->start, eb->len);
-       if (last)
-               btree_clear_folio_dirty(folio);
-       folio_unlock(folio);
-       WARN_ON(atomic_read(&eb->refs) == 0);
-}
-
 void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans,
                              struct extent_buffer *eb)
 {
        struct btrfs_fs_info *fs_info = eb->fs_info;
-       int num_folios;
+       const int num_folios = num_extent_folios(eb);
 
        btrfs_assert_tree_write_locked(eb);
 
@@ -3395,17 +3379,17 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans,
        percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -eb->len,
                                 fs_info->dirty_metadata_batch);
 
-       if (btrfs_meta_is_subpage(fs_info))
-               return clear_subpage_extent_buffer_dirty(eb);
-
-       num_folios = num_extent_folios(eb);
        for (int i = 0; i < num_folios; i++) {
                struct folio *folio = eb->folios[i];
+               bool last;
 
                if (!folio_test_dirty(folio))
                        continue;
                folio_lock(folio);
-               btree_clear_folio_dirty(folio);
+               last = btrfs_meta_folio_clear_and_test_dirty(fs_info, folio,
+                                                            eb->start, eb->len);
+               if (last)
+                       btree_clear_folio_dirty_tag(folio);
                folio_unlock(folio);
        }
        WARN_ON(atomic_read(&eb->refs) == 0);
@@ -3430,12 +3414,12 @@ void set_extent_buffer_dirty(struct extent_buffer *eb)
 
                /*
                 * For subpage case, we can have other extent buffers in the
-                * same page, and in clear_subpage_extent_buffer_dirty() we
+                * same page, and in clear_extent_buffer_dirty() we
                 * have to clear page dirty without subpage lock held.
                 * This can cause race where our page gets dirty cleared after
                 * we just set it.
                 *
-                * Thankfully, clear_subpage_extent_buffer_dirty() has locked
+                * Thankfully, clear_extent_buffer_dirty() has locked
                 * its page for other reasons, we can use page lock to prevent
                 * the above race.
                 */
index 3b5cde51ba549e3322a55ab798e0b83580a8d473..f02346aff827f655cc9acbc6452701f0d2710bc7 100644 (file)
@@ -781,6 +781,29 @@ void btrfs_folio_set_lock(const struct btrfs_fs_info *fs_info,
        spin_unlock_irqrestore(&subpage->lock, flags);
 }
 
+/*
+ * Clear the dirty flag for the folio.
+ *
+ * If the affected folio is no longer dirty, return true. Otherwise return false.
+ */
+bool btrfs_meta_folio_clear_and_test_dirty(const struct btrfs_fs_info *fs_info,
+                                          struct folio *folio, u64 start, u32 len)
+{
+       bool last;
+
+       if (!btrfs_meta_is_subpage(fs_info)) {
+               folio_clear_dirty_for_io(folio);
+               return true;
+       }
+
+       last = btrfs_subpage_clear_and_test_dirty(fs_info, folio, start, len);
+       if (last) {
+               folio_clear_dirty_for_io(folio);
+               return true;
+       }
+       return false;
+}
+
 void __cold btrfs_subpage_dump_bitmap(const struct btrfs_fs_info *fs_info,
                                      struct folio *folio, u64 start, u32 len)
 {
index ee118bb2c22f10b1980aa84898ef9e09f803bf54..6a2dd208eeae8c325b247afe5772145754fa589b 100644 (file)
@@ -186,6 +186,8 @@ bool btrfs_subpage_clear_and_test_dirty(const struct btrfs_fs_info *fs_info,
 
 void btrfs_folio_assert_not_dirty(const struct btrfs_fs_info *fs_info,
                                  struct folio *folio, u64 start, u32 len);
+bool btrfs_meta_folio_clear_and_test_dirty(const struct btrfs_fs_info *fs_info,
+                                          struct folio *folio, u64 start, u32 len);
 void btrfs_get_subpage_dirty_bitmap(struct btrfs_fs_info *fs_info,
                                    struct folio *folio,
                                    unsigned long *ret_bitmap);