btrfs: print-tree: Add eb locking status output for debug build
authorQu Wenruo <wqu@suse.com>
Tue, 24 Apr 2018 05:03:13 +0000 (13:03 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 28 May 2018 16:07:26 +0000 (18:07 +0200)
It's pretty handy if we can get the debug output for locking status of
an extent buffer, specially for race condition related debugging.

So add the following output for btrfs_print_tree() and
btrfs_print_leaf():
- refs
- write_locks (as w:%d)
- read_locks (as r:%d)
- blocking_writers (as bw:%d)
- blocking_readers (as br:%d)
- spinning_writers (as sw:%d)
- spinning_readers (as sr:%d)
- lock_owner
- current->pid

Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
[ update comment ]
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/print-tree.c

index 21a831d3d087418bc2e4db884f4fd6a25e9df4e5..a4e11cf04671e6777802922d460dec16007b8380 100644 (file)
@@ -166,6 +166,25 @@ static void print_uuid_item(struct extent_buffer *l, unsigned long offset,
        }
 }
 
+/*
+ * Helper to output refs and locking status of extent buffer.  Useful to debug
+ * race condition related problems.
+ */
+static void print_eb_refs_lock(struct extent_buffer *eb)
+{
+#ifdef CONFIG_BTRFS_DEBUG
+       btrfs_info(eb->fs_info,
+"refs %u lock (w:%d r:%d bw:%d br:%d sw:%d sr:%d) lock_owner %u current %u",
+                  atomic_read(&eb->refs), atomic_read(&eb->write_locks),
+                  atomic_read(&eb->read_locks),
+                  atomic_read(&eb->blocking_writers),
+                  atomic_read(&eb->blocking_readers),
+                  atomic_read(&eb->spinning_writers),
+                  atomic_read(&eb->spinning_readers),
+                  eb->lock_owner, current->pid);
+#endif
+}
+
 void btrfs_print_leaf(struct extent_buffer *l)
 {
        struct btrfs_fs_info *fs_info;
@@ -193,6 +212,7 @@ void btrfs_print_leaf(struct extent_buffer *l)
                   "leaf %llu gen %llu total ptrs %d free space %d owner %llu",
                   btrfs_header_bytenr(l), btrfs_header_generation(l), nr,
                   btrfs_leaf_free_space(fs_info, l), btrfs_header_owner(l));
+       print_eb_refs_lock(l);
        for (i = 0 ; i < nr ; i++) {
                item = btrfs_item_nr(i);
                btrfs_item_key_to_cpu(l, &key, i);
@@ -347,6 +367,7 @@ void btrfs_print_tree(struct extent_buffer *c, bool follow)
                   btrfs_header_bytenr(c), level, btrfs_header_generation(c),
                   nr, (u32)BTRFS_NODEPTRS_PER_BLOCK(fs_info) - nr,
                   btrfs_header_owner(c));
+       print_eb_refs_lock(c);
        for (i = 0; i < nr; i++) {
                btrfs_node_key_to_cpu(c, &key, i);
                pr_info("\tkey %d (%llu %u %llu) block %llu gen %llu\n",