]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
btrfs: avoid logging tree mod log elements for irrelevant extent buffers
authorFilipe Manana <fdmanana@suse.com>
Tue, 1 Jul 2025 21:20:19 +0000 (22:20 +0100)
committerDavid Sterba <dsterba@suse.com>
Mon, 21 Jul 2025 22:09:20 +0000 (00:09 +0200)
We are logging tree mod log operations for extent buffers from any tree
but we only need to log for the extent tree and subvolume tree, since
the tree mod log is used to get a consistent view, within a transaction,
of extents and their backrefs. So it's pointless to log operations for
trees such as the csum tree, free space tree, root tree, chunk tree,
log trees, data relocation tree, etc, as these trees are not used for
backref walking and all tree mod log users are about backref walking.

So skip extent buffers that don't belong neither to the extent nor to
subvolume trees. This avoids unnecessary memory allocations and having a
larger tree mod log rbtree with nodes that are never needed.

Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/tree-mod-log.c

index 1ac2678fc4caa8d1d2ee8f9ee2e26a8ffe877ee9..dcb8aef6e9007335076e137c2c7e856df697ce8e 100644 (file)
@@ -164,6 +164,30 @@ static noinline int tree_mod_log_insert(struct btrfs_fs_info *fs_info,
        return 0;
 }
 
+static inline bool skip_eb_logging(const struct extent_buffer *eb)
+{
+       const u64 owner = btrfs_header_owner(eb);
+
+       if (btrfs_header_level(eb) == 0)
+               return true;
+
+       /*
+        * Tree mod logging exists so that there's a consistent view of the
+        * extents and backrefs of inodes even if while a task is iterating over
+        * them other tasks are modifying subvolume trees and the extent tree
+        * (including running delayed refs). So we only need to log extent
+        * buffers from the extent tree and subvolume trees.
+        */
+
+       if (owner == BTRFS_EXTENT_TREE_OBJECTID)
+               return false;
+
+       if (btrfs_is_fstree(owner))
+               return false;
+
+       return true;
+}
+
 /*
  * Determines if logging can be omitted. Returns true if it can. Otherwise, it
  * returns false with the tree_mod_log_lock acquired. The caller must hold
@@ -174,7 +198,7 @@ static bool tree_mod_dont_log(struct btrfs_fs_info *fs_info, const struct extent
 {
        if (!test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags))
                return true;
-       if (eb && btrfs_header_level(eb) == 0)
+       if (eb && skip_eb_logging(eb))
                return true;
 
        write_lock(&fs_info->tree_mod_log_lock);
@@ -192,7 +216,7 @@ static bool tree_mod_need_log(const struct btrfs_fs_info *fs_info,
 {
        if (!test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags))
                return false;
-       if (eb && btrfs_header_level(eb) == 0)
+       if (eb && skip_eb_logging(eb))
                return false;
 
        return true;