OSDN Git Service

btrfs: add more find_free_extent tracepoints
authorBoris Burkov <boris@bur.io>
Fri, 16 Dec 2022 00:06:32 +0000 (16:06 -0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 13 Feb 2023 16:50:34 +0000 (17:50 +0100)
find_free_extent is a complicated function. It consists (at least) of:

- a hint that jumps into the middle of a for loop macro
- a middle loop trying every raid level
- an outer loop ascending through ffe loop levels
- complicated logic for skipping some of those ffe loop levels
- multiple underlying in-bg allocators (zoned, cluster, no cluster)

Which is all to say that more tracing is helpful for debugging its
behavior. Add two new tracepoints: at the entrance to the block_groups
loop (hit for every raid level and every ffe_ctl loop) and at the point
we seriously consider a block_group for allocation. This way we can see
the whole path through the algorithm, including hints, multiple loops,
etc.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Boris Burkov <boris@bur.io>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/extent-tree.c
fs/btrfs/extent-tree.h
include/trace/events/btrfs.h

index b26cbf6..203c8cb 100644 (file)
@@ -4261,6 +4261,7 @@ static noinline int find_free_extent(struct btrfs_root *root,
                                                        block_group->flags);
                                btrfs_lock_block_group(block_group,
                                                       ffe_ctl->delalloc);
+                               ffe_ctl->hinted = true;
                                goto have_block_group;
                        }
                } else if (block_group) {
@@ -4268,6 +4269,7 @@ static noinline int find_free_extent(struct btrfs_root *root,
                }
        }
 search:
+       trace_find_free_extent_search_loop(root, ffe_ctl);
        ffe_ctl->have_caching_bg = false;
        if (ffe_ctl->index == btrfs_bg_flags_to_raid_index(ffe_ctl->flags) ||
            ffe_ctl->index == 0)
@@ -4277,6 +4279,7 @@ search:
                            &space_info->block_groups[ffe_ctl->index], list) {
                struct btrfs_block_group *bg_ret;
 
+               ffe_ctl->hinted = false;
                /* If the block group is read-only, we can skip it entirely. */
                if (unlikely(block_group->ro)) {
                        if (ffe_ctl->for_treelog)
@@ -4318,6 +4321,7 @@ search:
                }
 
 have_block_group:
+               trace_find_free_extent_have_block_group(root, ffe_ctl, block_group);
                ffe_ctl->cached = btrfs_block_group_done(block_group);
                if (unlikely(!ffe_ctl->cached)) {
                        ffe_ctl->have_caching_bg = true;
index 64fa8ad..daa5e35 100644 (file)
@@ -76,6 +76,9 @@ struct find_free_extent_ctl {
 
        /* Allocation policy */
        enum btrfs_extent_allocation_policy policy;
+
+       /* Whether or not the allocator is currently following a hint */
+       bool hinted;
 };
 
 enum btrfs_inline_ref_type {
index 8a422e2..cc2eaab 100644 (file)
@@ -1268,6 +1268,77 @@ TRACE_EVENT(find_free_extent,
                                 BTRFS_GROUP_FLAGS))
 );
 
+TRACE_EVENT(find_free_extent_search_loop,
+
+       TP_PROTO(const struct btrfs_root *root,
+                const struct find_free_extent_ctl *ffe_ctl),
+
+       TP_ARGS(root, ffe_ctl),
+
+       TP_STRUCT__entry_btrfs(
+               __field(        u64,    root_objectid           )
+               __field(        u64,    num_bytes               )
+               __field(        u64,    empty_size              )
+               __field(        u64,    flags                   )
+               __field(        u64,    loop                    )
+       ),
+
+       TP_fast_assign_btrfs(root->fs_info,
+               __entry->root_objectid  = root->root_key.objectid;
+               __entry->num_bytes      = ffe_ctl->num_bytes;
+               __entry->empty_size     = ffe_ctl->empty_size;
+               __entry->flags          = ffe_ctl->flags;
+               __entry->loop           = ffe_ctl->loop;
+       ),
+
+       TP_printk_btrfs("root=%llu(%s) len=%llu empty_size=%llu flags=%llu(%s) loop=%llu",
+                 show_root_type(__entry->root_objectid),
+                 __entry->num_bytes, __entry->empty_size, __entry->flags,
+                 __print_flags((unsigned long)__entry->flags, "|", BTRFS_GROUP_FLAGS),
+                 __entry->loop)
+);
+
+TRACE_EVENT(find_free_extent_have_block_group,
+
+       TP_PROTO(const struct btrfs_root *root,
+                const struct find_free_extent_ctl *ffe_ctl,
+                const struct btrfs_block_group *block_group),
+
+       TP_ARGS(root, ffe_ctl, block_group),
+
+       TP_STRUCT__entry_btrfs(
+               __field(        u64,    root_objectid           )
+               __field(        u64,    num_bytes               )
+               __field(        u64,    empty_size              )
+               __field(        u64,    flags                   )
+               __field(        u64,    loop                    )
+               __field(        bool,   hinted                  )
+               __field(        u64,    bg_start                )
+               __field(        u64,    bg_flags                )
+       ),
+
+       TP_fast_assign_btrfs(root->fs_info,
+               __entry->root_objectid  = root->root_key.objectid;
+               __entry->num_bytes      = ffe_ctl->num_bytes;
+               __entry->empty_size     = ffe_ctl->empty_size;
+               __entry->flags          = ffe_ctl->flags;
+               __entry->loop           = ffe_ctl->loop;
+               __entry->hinted         = ffe_ctl->hinted;
+               __entry->bg_start       = block_group->start;
+               __entry->bg_flags       = block_group->flags;
+       ),
+
+       TP_printk_btrfs(
+"root=%llu(%s) len=%llu empty_size=%llu flags=%llu(%s) loop=%llu hinted=%d block_group=%llu bg_flags=%llu(%s)",
+                 show_root_type(__entry->root_objectid),
+                 __entry->num_bytes, __entry->empty_size, __entry->flags,
+                 __print_flags((unsigned long)__entry->flags, "|", BTRFS_GROUP_FLAGS),
+                 __entry->loop, __entry->hinted,
+                 __entry->bg_start, __entry->bg_flags,
+                 __print_flags((unsigned long)__entry->bg_flags, "|",
+                                BTRFS_GROUP_FLAGS))
+);
+
 DECLARE_EVENT_CLASS(btrfs__reserve_extent,
 
        TP_PROTO(const struct btrfs_block_group *block_group,
@@ -1280,6 +1351,8 @@ DECLARE_EVENT_CLASS(btrfs__reserve_extent,
                __field(        u64,    flags                   )
                __field(        u64,    start                   )
                __field(        u64,    len                     )
+               __field(        u64,    loop                    )
+               __field(        bool,   hinted                  )
        ),
 
        TP_fast_assign_btrfs(block_group->fs_info,
@@ -1287,15 +1360,17 @@ DECLARE_EVENT_CLASS(btrfs__reserve_extent,
                __entry->flags          = block_group->flags;
                __entry->start          = ffe_ctl->search_start;
                __entry->len            = ffe_ctl->num_bytes;
+               __entry->loop           = ffe_ctl->loop;
+               __entry->hinted         = ffe_ctl->hinted;
        ),
 
-       TP_printk_btrfs("root=%llu(%s) block_group=%llu flags=%llu(%s) "
-                 "start=%llu len=%llu",
+       TP_printk_btrfs(
+"root=%llu(%s) block_group=%llu flags=%llu(%s) start=%llu len=%llu loop=%llu hinted=%d",
                  show_root_type(BTRFS_EXTENT_TREE_OBJECTID),
                  __entry->bg_objectid,
                  __entry->flags, __print_flags((unsigned long)__entry->flags,
                                                "|", BTRFS_GROUP_FLAGS),
-                 __entry->start, __entry->len)
+                 __entry->start, __entry->len, __entry->loop, __entry->hinted)
 );
 
 DEFINE_EVENT(btrfs__reserve_extent, btrfs_reserve_extent,