From a1d198478e92cc8f05c26be746edd1c58f756c0f Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Fri, 1 Mar 2019 10:48:00 +0800 Subject: [PATCH] btrfs: tracepoints: Add trace events for extent_io_tree Although btrfs heavily relies on extent_io_tree, we don't really have any good trace events for them. This patch will add the folowing trace events: - trace_btrfs_set_extent_bit() - trace_btrfs_clear_extent_bit() - trace_btrfs_convert_extent_bit() Since selftests could create temporary extent_io_tree without fs_info, modify TP_fast_assign_fsid() to accept NULL as fs_info. NULL fs_info will lead to all zero fsid. The output would be: btrfs_set_extent_bit: : io_tree=INODE_IO ino=1 root=1 start=22036480 len=4096 set_bits=LOCKED btrfs_set_extent_bit: : io_tree=INODE_IO ino=1 root=1 start=22040576 len=4096 set_bits=LOCKED btrfs_set_extent_bit: : io_tree=INODE_IO ino=1 root=1 start=22044672 len=4096 set_bits=LOCKED btrfs_set_extent_bit: : io_tree=INODE_IO ino=1 root=1 start=22048768 len=4096 set_bits=LOCKED btrfs_clear_extent_bit: : io_tree=INODE_IO ino=1 root=1 start=22036480 len=16384 clear_bits=LOCKED ^^^ Extent buffer 22036480 read from disk, the locking progress btrfs_set_extent_bit: : io_tree=TRANS_DIRTY_PAGES ino=1 root=1 start=30425088 len=16384 set_bits=DIRTY btrfs_set_extent_bit: : io_tree=TRANS_DIRTY_PAGES ino=1 root=1 start=30441472 len=16384 set_bits=DIRTY ^^^ 2 new tree blocks allocated in one transaction btrfs_set_extent_bit: : io_tree=FREED_EXTENTS0 ino=0 root=0 start=30523392 len=16384 set_bits=DIRTY btrfs_set_extent_bit: : io_tree=FREED_EXTENTS0 ino=0 root=0 start=30556160 len=16384 set_bits=DIRTY ^^^ 2 old tree blocks get pinned down There is one point which need attention: 1) Those trace events can be pretty heavy: The following workload would generate over 400 trace events. mkfs.btrfs -f $dev start_trace mount $dev $mnt -o enospc_debug sync touch $mnt/file1 touch $mnt/file2 touch $mnt/file3 xfs_io -f -c "pwrite 0 16k" $mnt/file4 umount $mnt end_trace It's not recommended to use them in real world environment. Signed-off-by: Qu Wenruo Reviewed-by: David Sterba [ rename enums ] Signed-off-by: David Sterba --- fs/btrfs/extent_io.c | 4 ++ include/trace/events/btrfs.h | 158 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 161 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index cfd2b237fd66..ee246a7e14c5 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -614,6 +614,7 @@ int __clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, int clear = 0; btrfs_debug_check_extent_io_range(tree, start, end); + trace_btrfs_clear_extent_bit(tree, start, end - start + 1, bits); if (bits & EXTENT_DELALLOC) bits |= EXTENT_NORESERVE; @@ -883,6 +884,7 @@ __set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, u64 last_end; btrfs_debug_check_extent_io_range(tree, start, end); + trace_btrfs_set_extent_bit(tree, start, end - start + 1, bits); again: if (!prealloc && gfpflags_allow_blocking(mask)) { @@ -1115,6 +1117,8 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, bool first_iteration = true; btrfs_debug_check_extent_io_range(tree, start, end); + trace_btrfs_convert_extent_bit(tree, start, end - start + 1, bits, + clear_bits); again: if (!prealloc) { diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h index ab1cc33adbac..74a11b23b7d4 100644 --- a/include/trace/events/btrfs.h +++ b/include/trace/events/btrfs.h @@ -27,6 +27,7 @@ struct btrfs_work; struct __btrfs_workqueue; struct btrfs_qgroup_extent_record; struct btrfs_qgroup; +struct extent_io_tree; struct prelim_ref; TRACE_DEFINE_ENUM(FLUSH_DELAYED_ITEMS_NR); @@ -77,6 +78,17 @@ TRACE_DEFINE_ENUM(COMMIT_TRANS); { BTRFS_QGROUP_RSV_META_PERTRANS, "META_PERTRANS" }, \ { BTRFS_QGROUP_RSV_META_PREALLOC, "META_PREALLOC" }) +#define show_extent_io_tree_owner(owner) \ + __print_symbolic(owner, \ + { IO_TREE_FS_INFO_FREED_EXTENTS0, "FREED_EXTENTS0" }, \ + { IO_TREE_FS_INFO_FREED_EXTENTS1, "FREED_EXTENTS1" }, \ + { IO_TREE_INODE_IO, "INODE_IO" }, \ + { IO_TREE_INODE_IO_FAILURE, "INODE_IO_FAILURE" }, \ + { IO_TREE_RELOC_BLOCKS, "RELOC_BLOCKS" }, \ + { IO_TREE_TRANS_DIRTY_PAGES, "TRANS_DIRTY_PAGES" }, \ + { IO_TREE_ROOT_DIRTY_LOG_PAGES, "ROOT_DIRTY_LOG_PAGES" }, \ + { IO_TREE_SELFTEST, "SELFTEST" }) + #define BTRFS_GROUP_FLAGS \ { BTRFS_BLOCK_GROUP_DATA, "DATA"}, \ { BTRFS_BLOCK_GROUP_SYSTEM, "SYSTEM"}, \ @@ -88,11 +100,35 @@ TRACE_DEFINE_ENUM(COMMIT_TRANS); { BTRFS_BLOCK_GROUP_RAID5, "RAID5"}, \ { BTRFS_BLOCK_GROUP_RAID6, "RAID6"} +#define EXTENT_FLAGS \ + { EXTENT_DIRTY, "DIRTY"}, \ + { EXTENT_WRITEBACK, "WRITEBACK"}, \ + { EXTENT_UPTODATE, "UPTODATE"}, \ + { EXTENT_LOCKED, "LOCKED"}, \ + { EXTENT_NEW, "NEW"}, \ + { EXTENT_DELALLOC, "DELALLOC"}, \ + { EXTENT_DEFRAG, "DEFRAG"}, \ + { EXTENT_BOUNDARY, "BOUNDARY"}, \ + { EXTENT_NODATASUM, "NODATASUM"}, \ + { EXTENT_CLEAR_META_RESV, "CLEAR_META_RESV"}, \ + { EXTENT_NEED_WAIT, "NEED_WAIT"}, \ + { EXTENT_DAMAGED, "DAMAGED"}, \ + { EXTENT_NORESERVE, "NORESERVE"}, \ + { EXTENT_QGROUP_RESERVED, "QGROUP_RESERVED"}, \ + { EXTENT_CLEAR_DATA_RESV, "CLEAR_DATA_RESV"}, \ + { EXTENT_DELALLOC_NEW, "DELALLOC_NEW"} + #define BTRFS_FSID_SIZE 16 #define TP_STRUCT__entry_fsid __array(u8, fsid, BTRFS_FSID_SIZE) #define TP_fast_assign_fsid(fs_info) \ - memcpy(__entry->fsid, fs_info->fs_devices->fsid, BTRFS_FSID_SIZE) +({ \ + if (fs_info) \ + memcpy(__entry->fsid, fs_info->fs_devices->fsid, \ + BTRFS_FSID_SIZE); \ + else \ + memset(__entry->fsid, 0, BTRFS_FSID_SIZE); \ +}) #define TP_STRUCT__entry_btrfs(args...) \ TP_STRUCT__entry( \ @@ -1850,6 +1886,126 @@ DEFINE_EVENT(btrfs__block_group, btrfs_skip_unused_block_group, TP_ARGS(bg_cache) ); +TRACE_EVENT(btrfs_set_extent_bit, + TP_PROTO(const struct extent_io_tree *tree, + u64 start, u64 len, unsigned set_bits), + + TP_ARGS(tree, start, len, set_bits), + + TP_STRUCT__entry_btrfs( + __field( unsigned, owner ) + __field( u64, ino ) + __field( u64, rootid ) + __field( u64, start ) + __field( u64, len ) + __field( unsigned, set_bits) + ), + + TP_fast_assign_btrfs(tree->fs_info, + __entry->owner = tree->owner; + if (tree->private_data) { + struct inode *inode = tree->private_data; + + __entry->ino = btrfs_ino(BTRFS_I(inode)); + __entry->rootid = + BTRFS_I(inode)->root->root_key.objectid; + } else { + __entry->ino = 0; + __entry->rootid = 0; + } + __entry->start = start; + __entry->len = len; + __entry->set_bits = set_bits; + ), + + TP_printk_btrfs( + "io_tree=%s ino=%llu root=%llu start=%llu len=%llu set_bits=%s", + show_extent_io_tree_owner(__entry->owner), __entry->ino, + __entry->rootid, __entry->start, __entry->len, + __print_flags(__entry->set_bits, "|", EXTENT_FLAGS)) +); + +TRACE_EVENT(btrfs_clear_extent_bit, + TP_PROTO(const struct extent_io_tree *tree, + u64 start, u64 len, unsigned clear_bits), + + TP_ARGS(tree, start, len, clear_bits), + + TP_STRUCT__entry_btrfs( + __field( unsigned, owner ) + __field( u64, ino ) + __field( u64, rootid ) + __field( u64, start ) + __field( u64, len ) + __field( unsigned, clear_bits) + ), + + TP_fast_assign_btrfs(tree->fs_info, + __entry->owner = tree->owner; + if (tree->private_data) { + struct inode *inode = tree->private_data; + + __entry->ino = btrfs_ino(BTRFS_I(inode)); + __entry->rootid = + BTRFS_I(inode)->root->root_key.objectid; + } else { + __entry->ino = 0; + __entry->rootid = 0; + } + __entry->start = start; + __entry->len = len; + __entry->clear_bits = clear_bits; + ), + + TP_printk_btrfs( + "io_tree=%s ino=%llu root=%llu start=%llu len=%llu clear_bits=%s", + show_extent_io_tree_owner(__entry->owner), __entry->ino, + __entry->rootid, __entry->start, __entry->len, + __print_flags(__entry->clear_bits, "|", EXTENT_FLAGS)) +); + +TRACE_EVENT(btrfs_convert_extent_bit, + TP_PROTO(const struct extent_io_tree *tree, + u64 start, u64 len, unsigned set_bits, unsigned clear_bits), + + TP_ARGS(tree, start, len, set_bits, clear_bits), + + TP_STRUCT__entry_btrfs( + __field( unsigned, owner ) + __field( u64, ino ) + __field( u64, rootid ) + __field( u64, start ) + __field( u64, len ) + __field( unsigned, set_bits) + __field( unsigned, clear_bits) + ), + + TP_fast_assign_btrfs(tree->fs_info, + __entry->owner = tree->owner; + if (tree->private_data) { + struct inode *inode = tree->private_data; + + __entry->ino = btrfs_ino(BTRFS_I(inode)); + __entry->rootid = + BTRFS_I(inode)->root->root_key.objectid; + } else { + __entry->ino = 0; + __entry->rootid = 0; + } + __entry->start = start; + __entry->len = len; + __entry->set_bits = set_bits; + __entry->clear_bits = clear_bits; + ), + + TP_printk_btrfs( +"io_tree=%s ino=%llu root=%llu start=%llu len=%llu set_bits=%s clear_bits=%s", + show_extent_io_tree_owner(__entry->owner), __entry->ino, + __entry->rootid, __entry->start, __entry->len, + __print_flags(__entry->set_bits , "|", EXTENT_FLAGS), + __print_flags(__entry->clear_bits, "|", EXTENT_FLAGS)) +); + #endif /* _TRACE_BTRFS_H */ /* This part must be outside protection */ -- 2.11.0