* [PATCH 0/3] btrfs: tree mod log optimizations and cleanup
@ 2025-07-02 15:38 fdmanana
2025-07-02 15:38 ` [PATCH 1/3] btrfs: avoid logging tree mod log elements for irrelevant extent buffers fdmanana
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: fdmanana @ 2025-07-02 15:38 UTC (permalink / raw)
To: linux-btrfs
From: Filipe Manana <fdmanana@suse.com>
A couple optimizations for the tree mod log and a cleanup (related, for
one of the users of tree mog log).
Filipe Manana (3):
btrfs: avoid logging tree mod log elements for irrelevant extent buffers
btrfs: reduce size of struct tree_mod_elem
btrfs: set search_commit_root to false in iterate_inodes_from_logical()
fs/btrfs/backref.c | 12 +++---
fs/btrfs/backref.h | 3 +-
fs/btrfs/ioctl.c | 10 +----
fs/btrfs/tree-mod-log.c | 81 ++++++++++++++++++++++++++++++-----------
4 files changed, 68 insertions(+), 38 deletions(-)
--
2.47.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/3] btrfs: avoid logging tree mod log elements for irrelevant extent buffers
2025-07-02 15:38 [PATCH 0/3] btrfs: tree mod log optimizations and cleanup fdmanana
@ 2025-07-02 15:38 ` fdmanana
2025-07-02 15:38 ` [PATCH 2/3] btrfs: reduce size of struct tree_mod_elem fdmanana
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: fdmanana @ 2025-07-02 15:38 UTC (permalink / raw)
To: linux-btrfs
From: Filipe Manana <fdmanana@suse.com>
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 crelocation 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 either to the extent or to
subvolume trees. This avoids unncessary memory allocations and having a
larger tree mod log rbtree with nodes that are never needed.
Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
fs/btrfs/tree-mod-log.c | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/fs/btrfs/tree-mod-log.c b/fs/btrfs/tree-mod-log.c
index 1ac2678fc4ca..41dcd296b003 100644
--- a/fs/btrfs/tree-mod-log.c
+++ b/fs/btrfs/tree-mod-log.c
@@ -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 subvolumes 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;
--
2.47.2
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/3] btrfs: reduce size of struct tree_mod_elem
2025-07-02 15:38 [PATCH 0/3] btrfs: tree mod log optimizations and cleanup fdmanana
2025-07-02 15:38 ` [PATCH 1/3] btrfs: avoid logging tree mod log elements for irrelevant extent buffers fdmanana
@ 2025-07-02 15:38 ` fdmanana
2025-07-02 15:38 ` [PATCH 3/3] btrfs: set search_commit_root to false in iterate_inodes_from_logical() fdmanana
2025-07-02 21:39 ` [PATCH 0/3] btrfs: tree mod log optimizations and cleanup Boris Burkov
3 siblings, 0 replies; 5+ messages in thread
From: fdmanana @ 2025-07-02 15:38 UTC (permalink / raw)
To: linux-btrfs
From: Filipe Manana <fdmanana@suse.com>
Several members are used for specific types of tree mod log operations so
they can be placed in a union in order to reduce the structure's size.
This reduces the structure size from 112 bytes to 88 bytes on x86_64,
so we can now use the kmalloc-96 slab instead of the kmalloc-128 slab.
Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
fs/btrfs/tree-mod-log.c | 53 +++++++++++++++++++++++++----------------
1 file changed, 33 insertions(+), 20 deletions(-)
diff --git a/fs/btrfs/tree-mod-log.c b/fs/btrfs/tree-mod-log.c
index 41dcd296b003..d15a84f695e4 100644
--- a/fs/btrfs/tree-mod-log.c
+++ b/fs/btrfs/tree-mod-log.c
@@ -27,18 +27,29 @@ struct tree_mod_elem {
/* This is used for BTRFS_MOD_LOG_KEY* and BTRFS_MOD_LOG_ROOT_REPLACE. */
u64 generation;
- /* Those are used for op == BTRFS_MOD_LOG_KEY_{REPLACE,REMOVE}. */
- struct btrfs_disk_key key;
- u64 blockptr;
-
- /* This is used for op == BTRFS_MOD_LOG_MOVE_KEYS. */
- struct {
- int dst_slot;
- int nr_items;
- } move;
-
- /* This is used for op == BTRFS_MOD_LOG_ROOT_REPLACE. */
- struct tree_mod_root old_root;
+ union {
+ /*
+ * This is used for the following op types:
+ *
+ * BTRFS_MOD_LOG_KEY_REMOVE_WHILE_FREEING
+ * BTRFS_MOD_LOG_KEY_REMOVE_WHILE_MOVING
+ * BTRFS_MOD_LOG_KEY_REMOVE
+ * BTRFS_MOD_LOG_KEY_REPLACE
+ */
+ struct {
+ struct btrfs_disk_key key;
+ u64 blockptr;
+ } slot_change;
+
+ /* This is used for op == BTRFS_MOD_LOG_MOVE_KEYS. */
+ struct {
+ int dst_slot;
+ int nr_items;
+ } move;
+
+ /* This is used for op == BTRFS_MOD_LOG_ROOT_REPLACE. */
+ struct tree_mod_root old_root;
+ };
};
/*
@@ -228,15 +239,17 @@ static struct tree_mod_elem *alloc_tree_mod_elem(const struct extent_buffer *eb,
{
struct tree_mod_elem *tm;
+ /* Can't be one of these types, due to union on struct tree_mod_elem. */
+ ASSERT(op != BTRFS_MOD_LOG_MOVE_KEYS);
+ ASSERT(op != BTRFS_MOD_LOG_ROOT_REPLACE);
+
tm = kzalloc(sizeof(*tm), GFP_NOFS);
if (!tm)
return NULL;
tm->logical = eb->start;
- if (op != BTRFS_MOD_LOG_KEY_ADD) {
- btrfs_node_key(eb, &tm->key, slot);
- tm->blockptr = btrfs_node_blockptr(eb, slot);
- }
+ btrfs_node_key(eb, &tm->slot_change.key, slot);
+ tm->slot_change.blockptr = btrfs_node_blockptr(eb, slot);
tm->op = op;
tm->slot = slot;
tm->generation = btrfs_node_ptr_generation(eb, slot);
@@ -854,8 +867,8 @@ static void tree_mod_log_rewind(struct btrfs_fs_info *fs_info,
fallthrough;
case BTRFS_MOD_LOG_KEY_REMOVE_WHILE_MOVING:
case BTRFS_MOD_LOG_KEY_REMOVE:
- btrfs_set_node_key(eb, &tm->key, tm->slot);
- btrfs_set_node_blockptr(eb, tm->slot, tm->blockptr);
+ btrfs_set_node_key(eb, &tm->slot_change.key, tm->slot);
+ btrfs_set_node_blockptr(eb, tm->slot, tm->slot_change.blockptr);
btrfs_set_node_ptr_generation(eb, tm->slot,
tm->generation);
n++;
@@ -864,8 +877,8 @@ static void tree_mod_log_rewind(struct btrfs_fs_info *fs_info,
break;
case BTRFS_MOD_LOG_KEY_REPLACE:
BUG_ON(tm->slot >= n);
- btrfs_set_node_key(eb, &tm->key, tm->slot);
- btrfs_set_node_blockptr(eb, tm->slot, tm->blockptr);
+ btrfs_set_node_key(eb, &tm->slot_change.key, tm->slot);
+ btrfs_set_node_blockptr(eb, tm->slot, tm->slot_change.blockptr);
btrfs_set_node_ptr_generation(eb, tm->slot,
tm->generation);
break;
--
2.47.2
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/3] btrfs: set search_commit_root to false in iterate_inodes_from_logical()
2025-07-02 15:38 [PATCH 0/3] btrfs: tree mod log optimizations and cleanup fdmanana
2025-07-02 15:38 ` [PATCH 1/3] btrfs: avoid logging tree mod log elements for irrelevant extent buffers fdmanana
2025-07-02 15:38 ` [PATCH 2/3] btrfs: reduce size of struct tree_mod_elem fdmanana
@ 2025-07-02 15:38 ` fdmanana
2025-07-02 21:39 ` [PATCH 0/3] btrfs: tree mod log optimizations and cleanup Boris Burkov
3 siblings, 0 replies; 5+ messages in thread
From: fdmanana @ 2025-07-02 15:38 UTC (permalink / raw)
To: linux-btrfs
From: Filipe Manana <fdmanana@suse.com>
There's no point in checking at iterate_inodes_from_logical() if the path
has search_commit_root set, the only caller never sets search_commit_root
to true and it doesn't make sense for it ever to be true for the current
use case (logical_to_ino ioctl). So stop checking for that and since the
only caller allocates the path just for it to be used by
iterate_inodes_from_logical(), move the path allocation into that function.
Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
fs/btrfs/backref.c | 12 +++++++-----
fs/btrfs/backref.h | 3 +--
fs/btrfs/ioctl.c | 10 +---------
3 files changed, 9 insertions(+), 16 deletions(-)
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 2e0d959092f5..6a450be293b1 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -2546,17 +2546,20 @@ static int build_ino_list(u64 inum, u64 offset, u64 num_bytes, u64 root, void *c
}
int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
- struct btrfs_path *path,
void *ctx, bool ignore_offset)
{
struct btrfs_backref_walk_ctx walk_ctx = { 0 };
int ret;
u64 flags = 0;
struct btrfs_key found_key;
- int search_commit_root = path->search_commit_root;
+ struct btrfs_path *path;
+
+ path = btrfs_alloc_path();
+ if (!path)
+ return -ENOMEM;
ret = extent_from_logical(fs_info, logical, path, &found_key, &flags);
- btrfs_release_path(path);
+ btrfs_free_path(path);
if (ret < 0)
return ret;
if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)
@@ -2569,8 +2572,7 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
walk_ctx.extent_item_pos = logical - found_key.objectid;
walk_ctx.fs_info = fs_info;
- return iterate_extent_inodes(&walk_ctx, search_commit_root,
- build_ino_list, ctx);
+ return iterate_extent_inodes(&walk_ctx, false, build_ino_list, ctx);
}
static int inode_to_path(u64 inum, u32 name_len, unsigned long name_off,
diff --git a/fs/btrfs/backref.h b/fs/btrfs/backref.h
index 61f53825226d..34b0193a181c 100644
--- a/fs/btrfs/backref.h
+++ b/fs/btrfs/backref.h
@@ -226,8 +226,7 @@ int iterate_extent_inodes(struct btrfs_backref_walk_ctx *ctx,
iterate_extent_inodes_t *iterate, void *user_ctx);
int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
- struct btrfs_path *path, void *ctx,
- bool ignore_offset);
+ void *ctx, bool ignore_offset);
int paths_from_inode(u64 inum, struct inode_fs_paths *ipath);
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 503c469249e5..680c4e794e67 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -3353,7 +3353,6 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_fs_info *fs_info,
int size;
struct btrfs_ioctl_logical_ino_args *loi;
struct btrfs_data_container *inodes = NULL;
- struct btrfs_path *path = NULL;
bool ignore_offset;
if (!capable(CAP_SYS_ADMIN))
@@ -3387,14 +3386,7 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_fs_info *fs_info,
goto out_loi;
}
- path = btrfs_alloc_path();
- if (!path) {
- ret = -ENOMEM;
- goto out;
- }
- ret = iterate_inodes_from_logical(loi->logical, fs_info, path,
- inodes, ignore_offset);
- btrfs_free_path(path);
+ ret = iterate_inodes_from_logical(loi->logical, fs_info, inodes, ignore_offset);
if (ret == -EINVAL)
ret = -ENOENT;
if (ret < 0)
--
2.47.2
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 0/3] btrfs: tree mod log optimizations and cleanup
2025-07-02 15:38 [PATCH 0/3] btrfs: tree mod log optimizations and cleanup fdmanana
` (2 preceding siblings ...)
2025-07-02 15:38 ` [PATCH 3/3] btrfs: set search_commit_root to false in iterate_inodes_from_logical() fdmanana
@ 2025-07-02 21:39 ` Boris Burkov
3 siblings, 0 replies; 5+ messages in thread
From: Boris Burkov @ 2025-07-02 21:39 UTC (permalink / raw)
To: fdmanana; +Cc: linux-btrfs
On Wed, Jul 02, 2025 at 04:38:29PM +0100, fdmanana@kernel.org wrote:
> From: Filipe Manana <fdmanana@suse.com>
>
> A couple optimizations for the tree mod log and a cleanup (related, for
> one of the users of tree mog log).
Looks good, thanks.
Reviewed-by: Boris Burkov <boris@bur.io>
>
> Filipe Manana (3):
> btrfs: avoid logging tree mod log elements for irrelevant extent buffers
> btrfs: reduce size of struct tree_mod_elem
> btrfs: set search_commit_root to false in iterate_inodes_from_logical()
>
> fs/btrfs/backref.c | 12 +++---
> fs/btrfs/backref.h | 3 +-
> fs/btrfs/ioctl.c | 10 +----
> fs/btrfs/tree-mod-log.c | 81 ++++++++++++++++++++++++++++++-----------
> 4 files changed, 68 insertions(+), 38 deletions(-)
>
> --
> 2.47.2
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-07-02 21:38 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-02 15:38 [PATCH 0/3] btrfs: tree mod log optimizations and cleanup fdmanana
2025-07-02 15:38 ` [PATCH 1/3] btrfs: avoid logging tree mod log elements for irrelevant extent buffers fdmanana
2025-07-02 15:38 ` [PATCH 2/3] btrfs: reduce size of struct tree_mod_elem fdmanana
2025-07-02 15:38 ` [PATCH 3/3] btrfs: set search_commit_root to false in iterate_inodes_from_logical() fdmanana
2025-07-02 21:39 ` [PATCH 0/3] btrfs: tree mod log optimizations and cleanup Boris Burkov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.