]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
btrfs: simplify the btree folio wait during invalidation
authorQu Wenruo <wqu@suse.com>
Sun, 3 May 2026 09:47:51 +0000 (19:17 +0930)
committerDavid Sterba <dsterba@suse.com>
Mon, 8 Jun 2026 13:53:32 +0000 (15:53 +0200)
The btree inode is very different from regular data inodes, as the btree
inode is never exposed to user space operations.

All operations are either initiated by btrfs metadata operations, or MM
layer like memory pressure to release folios.

This means we never need to handle partial folio invalidation inside
btree_invalidate_folio().

With that said, we can slightly simplify the btree folio invalidation
by:

- Add ASSERT()s to make sure the range covers the whole folio

- Remove "if (start > end)" check
  As the range always covers the full folio, that check is always
  false and can be removed.

- Open code extent_invalidate_folio()

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/disk-io.c

index c13a05a7e39a41f4026287f8a7a66bb8c4a54dcc..982df3e3131199daa2137a6b9ebf16ddb846e12b 100644 (file)
@@ -488,25 +488,27 @@ static bool btree_release_folio(struct folio *folio, gfp_t gfp_flags)
        return try_release_extent_buffer(folio);
 }
 
-/*
- * Basic invalidate_folio code, this waits on any locked or writeback
- * ranges corresponding to the folio.
- */
-static int extent_invalidate_folio(struct extent_io_tree *tree,
-                                  struct folio *folio, size_t offset)
+static void btree_invalidate_folio(struct folio *folio, size_t offset,
+                                size_t length)
 {
+       struct extent_io_tree *tree = &folio_to_inode(folio)->io_tree;
        struct extent_state *cached_state = NULL;
-       u64 start = folio_pos(folio);
-       u64 end = start + folio_size(folio) - 1;
-       size_t blocksize = folio_to_fs_info(folio)->sectorsize;
+       const u64 start = folio_pos(folio);
+       const u64 end = folio_next_pos(folio) - 1;
+
+       /*
+        * The range must cover the full @folio.
+        * Btree inode is never exposed to regular file operations, thus there
+        * is no partial truncation.
+        * The folio is only invalidated when the btree inode is evicted.
+        */
+       ASSERT(offset == 0, "folio=%llu offset=%zu", folio_pos(folio), offset);
+       ASSERT(length == folio_size(folio), "folio=%llu folio_size=%zu length=%zu",
+              folio_pos(folio), folio_size(folio), length);
 
        /* This function is only called for the btree inode */
        ASSERT(tree->owner == IO_TREE_BTREE_INODE_IO);
 
-       start += ALIGN(offset, blocksize);
-       if (start > end)
-               return 0;
-
        btrfs_lock_extent(tree, start, end, &cached_state);
        folio_wait_writeback(folio);
 
@@ -516,16 +518,7 @@ static int extent_invalidate_folio(struct extent_io_tree *tree,
         * existing extent state.
         */
        btrfs_unlock_extent(tree, start, end, &cached_state);
-       return 0;
-}
-
-static void btree_invalidate_folio(struct folio *folio, size_t offset,
-                                size_t length)
-{
-       struct extent_io_tree *tree;
 
-       tree = &folio_to_inode(folio)->io_tree;
-       extent_invalidate_folio(tree, folio, offset);
        btree_release_folio(folio, GFP_NOFS);
        if (folio_get_private(folio)) {
                btrfs_warn(folio_to_fs_info(folio),