Commit 1abe9b8a authored by liubo's avatar liubo Committed by root

Btrfs: add initial tracepoint support for btrfs

Tracepoints can provide insight into why btrfs hits bugs and be greatly
helpful for debugging, e.g
              dd-7822  [000]  2121.641088: btrfs_inode_request: root = 5(FS_TREE), gen = 4, ino = 256, blocks = 8, disk_i_size = 0, last_trans = 8, logged_trans = 0
              dd-7822  [000]  2121.641100: btrfs_inode_new: root = 5(FS_TREE), gen = 8, ino = 257, blocks = 0, disk_i_size = 0, last_trans = 0, logged_trans = 0
 btrfs-transacti-7804  [001]  2146.935420: btrfs_cow_block: root = 2(EXTENT_TREE), refs = 2, orig_buf = 29368320 (orig_level = 0), cow_buf = 29388800 (cow_level = 0)
 btrfs-transacti-7804  [001]  2146.935473: btrfs_cow_block: root = 1(ROOT_TREE), refs = 2, orig_buf = 29364224 (orig_level = 0), cow_buf = 29392896 (cow_level = 0)
 btrfs-transacti-7804  [001]  2146.972221: btrfs_transaction_commit: root = 1(ROOT_TREE), gen = 8
   flush-btrfs-2-7821  [001]  2155.824210: btrfs_chunk_alloc: root = 3(CHUNK_TREE), offset = 1103101952, size = 1073741824, num_stripes = 1, sub_stripes = 0, type = DATA
   flush-btrfs-2-7821  [001]  2155.824241: btrfs_cow_block: root = 2(EXTENT_TREE), refs = 2, orig_buf = 29388800 (orig_level = 0), cow_buf = 29396992 (cow_level = 0)
   flush-btrfs-2-7821  [001]  2155.824255: btrfs_cow_block: root = 4(DEV_TREE), refs = 2, orig_buf = 29372416 (orig_level = 0), cow_buf = 29401088 (cow_level = 0)
   flush-btrfs-2-7821  [000]  2155.824329: btrfs_cow_block: root = 3(CHUNK_TREE), refs = 2, orig_buf = 20971520 (orig_level = 0), cow_buf = 20975616 (cow_level = 0)
 btrfs-endio-wri-7800  [001]  2155.898019: btrfs_cow_block: root = 5(FS_TREE), refs = 2, orig_buf = 29384704 (orig_level = 0), cow_buf = 29405184 (cow_level = 0)
 btrfs-endio-wri-7800  [001]  2155.898043: btrfs_cow_block: root = 7(CSUM_TREE), refs = 2, orig_buf = 29376512 (orig_level = 0), cow_buf = 29409280 (cow_level = 0)

Here is what I have added:

1) ordere_extent:
        btrfs_ordered_extent_add
        btrfs_ordered_extent_remove
        btrfs_ordered_extent_start
        btrfs_ordered_extent_put

These provide critical information to understand how ordered_extents are
updated.

2) extent_map:
        btrfs_get_extent

extent_map is used in both read and write cases, and it is useful for tracking
how btrfs specific IO is running.

3) writepage:
        __extent_writepage
        btrfs_writepage_end_io_hook

Pages are cirtical resourses and produce a lot of corner cases during writeback,
so it is valuable to know how page is written to disk.

4) inode:
        btrfs_inode_new
        btrfs_inode_request
        btrfs_inode_evict

These can show where and when a inode is created, when a inode is evicted.

5) sync:
        btrfs_sync_file
        btrfs_sync_fs

These show sync arguments.

6) transaction:
        btrfs_transaction_commit

In transaction based filesystem, it will be useful to know the generation and
who does commit.

7) back reference and cow:
	btrfs_delayed_tree_ref
	btrfs_delayed_data_ref
	btrfs_delayed_ref_head
	btrfs_cow_block

Btrfs natively supports back references, these tracepoints are helpful on
understanding btrfs's COW mechanism.

8) chunk:
	btrfs_chunk_alloc
	btrfs_chunk_free

Chunk is a link between physical offset and logical offset, and stands for space
infomation in btrfs, and these are helpful on tracing space things.

9) reserved_extent:
	btrfs_reserved_extent_alloc
	btrfs_reserved_extent_free

These can show how btrfs uses its space.
Signed-off-by: default avatarLiu Bo <liubo2009@cn.fujitsu.com>
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 240f62c8
...@@ -535,6 +535,9 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans, ...@@ -535,6 +535,9 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans,
ret = __btrfs_cow_block(trans, root, buf, parent, ret = __btrfs_cow_block(trans, root, buf, parent,
parent_slot, cow_ret, search_start, 0); parent_slot, cow_ret, search_start, 0);
trace_btrfs_cow_block(root, buf, *cow_ret);
return ret; return ret;
} }
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kobject.h> #include <linux/kobject.h>
#include <trace/events/btrfs.h>
#include <asm/kmap_types.h> #include <asm/kmap_types.h>
#include "extent_io.h" #include "extent_io.h"
#include "extent_map.h" #include "extent_map.h"
......
...@@ -483,6 +483,8 @@ static noinline int add_delayed_ref_head(struct btrfs_trans_handle *trans, ...@@ -483,6 +483,8 @@ static noinline int add_delayed_ref_head(struct btrfs_trans_handle *trans,
INIT_LIST_HEAD(&head_ref->cluster); INIT_LIST_HEAD(&head_ref->cluster);
mutex_init(&head_ref->mutex); mutex_init(&head_ref->mutex);
trace_btrfs_delayed_ref_head(ref, head_ref, action);
existing = tree_insert(&delayed_refs->root, &ref->rb_node); existing = tree_insert(&delayed_refs->root, &ref->rb_node);
if (existing) { if (existing) {
...@@ -537,6 +539,8 @@ static noinline int add_delayed_tree_ref(struct btrfs_trans_handle *trans, ...@@ -537,6 +539,8 @@ static noinline int add_delayed_tree_ref(struct btrfs_trans_handle *trans,
} }
full_ref->level = level; full_ref->level = level;
trace_btrfs_delayed_tree_ref(ref, full_ref, action);
existing = tree_insert(&delayed_refs->root, &ref->rb_node); existing = tree_insert(&delayed_refs->root, &ref->rb_node);
if (existing) { if (existing) {
...@@ -591,6 +595,8 @@ static noinline int add_delayed_data_ref(struct btrfs_trans_handle *trans, ...@@ -591,6 +595,8 @@ static noinline int add_delayed_data_ref(struct btrfs_trans_handle *trans,
full_ref->objectid = owner; full_ref->objectid = owner;
full_ref->offset = offset; full_ref->offset = offset;
trace_btrfs_delayed_data_ref(ref, full_ref, action);
existing = tree_insert(&delayed_refs->root, &ref->rb_node); existing = tree_insert(&delayed_refs->root, &ref->rb_node);
if (existing) { if (existing) {
......
...@@ -5412,6 +5412,8 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans, ...@@ -5412,6 +5412,8 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
dump_space_info(sinfo, num_bytes, 1); dump_space_info(sinfo, num_bytes, 1);
} }
trace_btrfs_reserved_extent_alloc(root, ins->objectid, ins->offset);
return ret; return ret;
} }
...@@ -5433,6 +5435,8 @@ int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len) ...@@ -5433,6 +5435,8 @@ int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len)
update_reserved_bytes(cache, len, 0, 1); update_reserved_bytes(cache, len, 0, 1);
btrfs_put_block_group(cache); btrfs_put_block_group(cache);
trace_btrfs_reserved_extent_free(root, start, len);
return ret; return ret;
} }
......
...@@ -2192,6 +2192,8 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, ...@@ -2192,6 +2192,8 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
else else
write_flags = WRITE; write_flags = WRITE;
trace___extent_writepage(page, inode, wbc);
WARN_ON(!PageLocked(page)); WARN_ON(!PageLocked(page));
pg_offset = i_size & (PAGE_CACHE_SIZE - 1); pg_offset = i_size & (PAGE_CACHE_SIZE - 1);
if (page->index > end_index || if (page->index > end_index ||
......
...@@ -1205,6 +1205,7 @@ int btrfs_sync_file(struct file *file, int datasync) ...@@ -1205,6 +1205,7 @@ int btrfs_sync_file(struct file *file, int datasync)
int ret = 0; int ret = 0;
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
trace_btrfs_sync_file(file, datasync);
/* we wait first, since the writeback may change the inode */ /* we wait first, since the writeback may change the inode */
root->log_batch++; root->log_batch++;
......
...@@ -1787,6 +1787,8 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) ...@@ -1787,6 +1787,8 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end, static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end,
struct extent_state *state, int uptodate) struct extent_state *state, int uptodate)
{ {
trace_btrfs_writepage_end_io_hook(page, start, end, uptodate);
ClearPagePrivate2(page); ClearPagePrivate2(page);
return btrfs_finish_ordered_io(page->mapping->host, start, end); return btrfs_finish_ordered_io(page->mapping->host, start, end);
} }
...@@ -3718,6 +3720,8 @@ void btrfs_evict_inode(struct inode *inode) ...@@ -3718,6 +3720,8 @@ void btrfs_evict_inode(struct inode *inode)
unsigned long nr; unsigned long nr;
int ret; int ret;
trace_btrfs_inode_evict(inode);
truncate_inode_pages(&inode->i_data, 0); truncate_inode_pages(&inode->i_data, 0);
if (inode->i_nlink && (btrfs_root_refs(&root->root_item) != 0 || if (inode->i_nlink && (btrfs_root_refs(&root->root_item) != 0 ||
root == root->fs_info->tree_root)) root == root->fs_info->tree_root))
...@@ -4510,6 +4514,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, ...@@ -4510,6 +4514,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
if (dir) { if (dir) {
trace_btrfs_inode_request(dir);
ret = btrfs_set_inode_index(dir, index); ret = btrfs_set_inode_index(dir, index);
if (ret) { if (ret) {
iput(inode); iput(inode);
...@@ -4584,6 +4590,9 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, ...@@ -4584,6 +4590,9 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
insert_inode_hash(inode); insert_inode_hash(inode);
inode_tree_add(inode); inode_tree_add(inode);
trace_btrfs_inode_new(inode);
return inode; return inode;
fail: fail:
if (dir) if (dir)
...@@ -5261,6 +5270,9 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, ...@@ -5261,6 +5270,9 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
} }
write_unlock(&em_tree->lock); write_unlock(&em_tree->lock);
out: out:
trace_btrfs_get_extent(root, em);
if (path) if (path)
btrfs_free_path(path); btrfs_free_path(path);
if (trans) { if (trans) {
......
...@@ -202,6 +202,8 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, ...@@ -202,6 +202,8 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
INIT_LIST_HEAD(&entry->list); INIT_LIST_HEAD(&entry->list);
INIT_LIST_HEAD(&entry->root_extent_list); INIT_LIST_HEAD(&entry->root_extent_list);
trace_btrfs_ordered_extent_add(inode, entry);
spin_lock(&tree->lock); spin_lock(&tree->lock);
node = tree_insert(&tree->tree, file_offset, node = tree_insert(&tree->tree, file_offset,
&entry->rb_node); &entry->rb_node);
...@@ -387,6 +389,8 @@ int btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry) ...@@ -387,6 +389,8 @@ int btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry)
struct list_head *cur; struct list_head *cur;
struct btrfs_ordered_sum *sum; struct btrfs_ordered_sum *sum;
trace_btrfs_ordered_extent_put(entry->inode, entry);
if (atomic_dec_and_test(&entry->refs)) { if (atomic_dec_and_test(&entry->refs)) {
while (!list_empty(&entry->list)) { while (!list_empty(&entry->list)) {
cur = entry->list.next; cur = entry->list.next;
...@@ -420,6 +424,8 @@ static int __btrfs_remove_ordered_extent(struct inode *inode, ...@@ -420,6 +424,8 @@ static int __btrfs_remove_ordered_extent(struct inode *inode,
spin_lock(&root->fs_info->ordered_extent_lock); spin_lock(&root->fs_info->ordered_extent_lock);
list_del_init(&entry->root_extent_list); list_del_init(&entry->root_extent_list);
trace_btrfs_ordered_extent_remove(inode, entry);
/* /*
* we have no more ordered extents for this inode and * we have no more ordered extents for this inode and
* no dirty pages. We can safely remove it from the * no dirty pages. We can safely remove it from the
...@@ -585,6 +591,8 @@ void btrfs_start_ordered_extent(struct inode *inode, ...@@ -585,6 +591,8 @@ void btrfs_start_ordered_extent(struct inode *inode,
u64 start = entry->file_offset; u64 start = entry->file_offset;
u64 end = start + entry->len - 1; u64 end = start + entry->len - 1;
trace_btrfs_ordered_extent_start(inode, entry);
/* /*
* pages in the range can be dirty, clean or writeback. We * pages in the range can be dirty, clean or writeback. We
* start IO on any dirty ones so the wait doesn't stall waiting * start IO on any dirty ones so the wait doesn't stall waiting
......
...@@ -52,6 +52,9 @@ ...@@ -52,6 +52,9 @@
#include "export.h" #include "export.h"
#include "compression.h" #include "compression.h"
#define CREATE_TRACE_POINTS
#include <trace/events/btrfs.h>
static const struct super_operations btrfs_super_ops; static const struct super_operations btrfs_super_ops;
static const char *btrfs_decode_error(struct btrfs_fs_info *fs_info, int errno, static const char *btrfs_decode_error(struct btrfs_fs_info *fs_info, int errno,
...@@ -620,6 +623,8 @@ int btrfs_sync_fs(struct super_block *sb, int wait) ...@@ -620,6 +623,8 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
struct btrfs_root *root = btrfs_sb(sb); struct btrfs_root *root = btrfs_sb(sb);
int ret; int ret;
trace_btrfs_sync_fs(wait);
if (!wait) { if (!wait) {
filemap_flush(root->fs_info->btree_inode->i_mapping); filemap_flush(root->fs_info->btree_inode->i_mapping);
return 0; return 0;
......
...@@ -1389,6 +1389,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, ...@@ -1389,6 +1389,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
put_transaction(cur_trans); put_transaction(cur_trans);
put_transaction(cur_trans); put_transaction(cur_trans);
trace_btrfs_transaction_commit(root);
mutex_unlock(&root->fs_info->trans_mutex); mutex_unlock(&root->fs_info->trans_mutex);
if (current->journal_info == trans) if (current->journal_info == trans)
......
...@@ -33,17 +33,6 @@ ...@@ -33,17 +33,6 @@
#include "volumes.h" #include "volumes.h"
#include "async-thread.h" #include "async-thread.h"
struct map_lookup {
u64 type;
int io_align;
int io_width;
int stripe_len;
int sector_size;
int num_stripes;
int sub_stripes;
struct btrfs_bio_stripe stripes[];
};
static int init_first_rw_device(struct btrfs_trans_handle *trans, static int init_first_rw_device(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
struct btrfs_device *device); struct btrfs_device *device);
...@@ -1923,6 +1912,8 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, ...@@ -1923,6 +1912,8 @@ static int btrfs_relocate_chunk(struct btrfs_root *root,
BUG_ON(ret); BUG_ON(ret);
trace_btrfs_chunk_free(root, map, chunk_offset, em->len);
if (map->type & BTRFS_BLOCK_GROUP_SYSTEM) { if (map->type & BTRFS_BLOCK_GROUP_SYSTEM) {
ret = btrfs_del_sys_chunk(root, chunk_objectid, chunk_offset); ret = btrfs_del_sys_chunk(root, chunk_objectid, chunk_offset);
BUG_ON(ret); BUG_ON(ret);
...@@ -2650,6 +2641,8 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, ...@@ -2650,6 +2641,8 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
*num_bytes = chunk_bytes_by_type(type, calc_size, *num_bytes = chunk_bytes_by_type(type, calc_size,
map->num_stripes, sub_stripes); map->num_stripes, sub_stripes);
trace_btrfs_chunk_alloc(info->chunk_root, map, start, *num_bytes);
em = alloc_extent_map(GFP_NOFS); em = alloc_extent_map(GFP_NOFS);
if (!em) { if (!em) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -2758,6 +2751,7 @@ static int __finish_chunk_alloc(struct btrfs_trans_handle *trans, ...@@ -2758,6 +2751,7 @@ static int __finish_chunk_alloc(struct btrfs_trans_handle *trans,
item_size); item_size);
BUG_ON(ret); BUG_ON(ret);
} }
kfree(chunk); kfree(chunk);
return 0; return 0;
} }
......
...@@ -145,6 +145,17 @@ struct btrfs_device_info { ...@@ -145,6 +145,17 @@ struct btrfs_device_info {
u64 max_avail; u64 max_avail;
}; };
struct map_lookup {
u64 type;
int io_align;
int io_width;
int stripe_len;
int sector_size;
int num_stripes;
int sub_stripes;
struct btrfs_bio_stripe stripes[];
};
/* Used to sort the devices by max_avail(descending sort) */ /* Used to sort the devices by max_avail(descending sort) */
int btrfs_cmp_device_free_bytes(const void *dev_info1, const void *dev_info2); int btrfs_cmp_device_free_bytes(const void *dev_info1, const void *dev_info2);
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment