]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
btrfs: subpage: simplify the PAGECACHE_TAG_TOWRITE handling
authorQu Wenruo <wqu@suse.com>
Tue, 21 Oct 2025 03:51:48 +0000 (14:21 +1030)
committerDavid Sterba <dsterba@suse.com>
Mon, 24 Nov 2025 21:03:38 +0000 (22:03 +0100)
In function btrfs_subpage_set_writeback() we need to keep the
PAGECACHE_TAG_TOWRITE tag if the folio is still dirty.

This is a needed quirk for support async extents, as a subpage range can
almost suddenly go writeback, without touching other subpage ranges in
the same folio.

However we can simplify the handling by replace the open-coded tag
clearing by passing the @keep_write flag depending on if the folio is
dirty.

Since we're holding the subpage lock already, no one is able to change
the dirty/writeback flag, thus it's safe to check the folio dirty before
calling __folio_start_writeback().

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Boris Burkov <boris@bur.io>
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/subpage.c

index 0a4a1ee81e6392c44fdd41be5e4e1fc3a4524ebf..80cd27d3267f57207c4ccfec5ae9ab03ce1200aa 100644 (file)
@@ -440,6 +440,7 @@ void btrfs_subpage_set_writeback(const struct btrfs_fs_info *fs_info,
        unsigned int start_bit = subpage_calc_start_bit(fs_info, folio,
                                                        writeback, start, len);
        unsigned long flags;
+       bool keep_write;
 
        spin_lock_irqsave(&bfs->lock, flags);
        bitmap_set(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits);
@@ -450,18 +451,9 @@ void btrfs_subpage_set_writeback(const struct btrfs_fs_info *fs_info,
         * assume writeback is complete, and exit too early — violating sync
         * ordering guarantees.
         */
+       keep_write = folio_test_dirty(folio);
        if (!folio_test_writeback(folio))
-               __folio_start_writeback(folio, true);
-       if (!folio_test_dirty(folio)) {
-               struct address_space *mapping = folio_mapping(folio);
-               XA_STATE(xas, &mapping->i_pages, folio->index);
-               unsigned long xa_flags;
-
-               xas_lock_irqsave(&xas, xa_flags);
-               xas_load(&xas);
-               xas_clear_mark(&xas, PAGECACHE_TAG_TOWRITE);
-               xas_unlock_irqrestore(&xas, xa_flags);
-       }
+               __folio_start_writeback(folio, keep_write);
        spin_unlock_irqrestore(&bfs->lock, flags);
 }