Commit 480b9b4d authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba

btrfs: extent-tree: Add trace events for space info numbers update

Add trace event for update_bytes_pinned() and update_bytes_may_use() to
detect underflow better.

The output would be something like (only showing data part):

  ## Buffered write start, 16K total ##
  2255.954 xfs_io/860 btrfs:update_bytes_may_use:(nil)U: type=DATA old=0 diff=4096
  2257.169 sudo/860 btrfs:update_bytes_may_use:(nil)U: type=DATA old=4096 diff=4096
  2257.346 sudo/860 btrfs:update_bytes_may_use:(nil)U: type=DATA old=8192 diff=4096
  2257.542 sudo/860 btrfs:update_bytes_may_use:(nil)U: type=DATA old=12288 diff=4096

  ## Delalloc start ##
  3727.853 kworker/u8:3-e/700 btrfs:update_bytes_may_use:(nil)U: type=DATA old=16384 diff=-16384

  ## Space cache update ##
  3733.132 sudo/862 btrfs:update_bytes_may_use:(nil)U: type=DATA old=0 diff=65536
  3733.169 sudo/862 btrfs:update_bytes_may_use:(nil)U: type=DATA old=65536 diff=-65536
  3739.868 sudo/862 btrfs:update_bytes_may_use:(nil)U: type=DATA old=0 diff=65536
  3739.891 sudo/862 btrfs:update_bytes_may_use:(nil)U: type=DATA old=65536 diff=-65536

These two trace events will allow bcc tool to probe btrfs_space_info
changes and detect underflow with more details (e.g. backtrace for each
update).
Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 0185f364
...@@ -55,10 +55,12 @@ enum { ...@@ -55,10 +55,12 @@ enum {
* Declare a helper function to detect underflow of various space info members * Declare a helper function to detect underflow of various space info members
*/ */
#define DECLARE_SPACE_INFO_UPDATE(name) \ #define DECLARE_SPACE_INFO_UPDATE(name) \
static inline void update_##name(struct btrfs_space_info *sinfo, \ static inline void update_##name(struct btrfs_fs_info *fs_info, \
struct btrfs_space_info *sinfo, \
s64 bytes) \ s64 bytes) \
{ \ { \
lockdep_assert_held(&sinfo->lock); \ lockdep_assert_held(&sinfo->lock); \
trace_update_##name(fs_info, sinfo, sinfo->name, bytes); \
if (bytes < 0 && sinfo->name < -bytes) { \ if (bytes < 0 && sinfo->name < -bytes) { \
WARN_ON(1); \ WARN_ON(1); \
sinfo->name = 0; \ sinfo->name = 0; \
...@@ -4209,7 +4211,7 @@ int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes) ...@@ -4209,7 +4211,7 @@ int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes)
data_sinfo->flags, bytes, 1); data_sinfo->flags, bytes, 1);
return -ENOSPC; return -ENOSPC;
} }
update_bytes_may_use(data_sinfo, bytes); update_bytes_may_use(fs_info, data_sinfo, bytes);
trace_btrfs_space_reservation(fs_info, "space_info", trace_btrfs_space_reservation(fs_info, "space_info",
data_sinfo->flags, bytes, 1); data_sinfo->flags, bytes, 1);
spin_unlock(&data_sinfo->lock); spin_unlock(&data_sinfo->lock);
...@@ -4262,7 +4264,7 @@ void btrfs_free_reserved_data_space_noquota(struct inode *inode, u64 start, ...@@ -4262,7 +4264,7 @@ void btrfs_free_reserved_data_space_noquota(struct inode *inode, u64 start,
data_sinfo = fs_info->data_sinfo; data_sinfo = fs_info->data_sinfo;
spin_lock(&data_sinfo->lock); spin_lock(&data_sinfo->lock);
update_bytes_may_use(data_sinfo, -len); update_bytes_may_use(fs_info, data_sinfo, -len);
trace_btrfs_space_reservation(fs_info, "space_info", trace_btrfs_space_reservation(fs_info, "space_info",
data_sinfo->flags, len, 0); data_sinfo->flags, len, 0);
spin_unlock(&data_sinfo->lock); spin_unlock(&data_sinfo->lock);
...@@ -5169,13 +5171,13 @@ static int __reserve_metadata_bytes(struct btrfs_fs_info *fs_info, ...@@ -5169,13 +5171,13 @@ static int __reserve_metadata_bytes(struct btrfs_fs_info *fs_info,
* If not things get more complicated. * If not things get more complicated.
*/ */
if (used + orig_bytes <= space_info->total_bytes) { if (used + orig_bytes <= space_info->total_bytes) {
update_bytes_may_use(space_info, orig_bytes); update_bytes_may_use(fs_info, space_info, orig_bytes);
trace_btrfs_space_reservation(fs_info, "space_info", trace_btrfs_space_reservation(fs_info, "space_info",
space_info->flags, orig_bytes, 1); space_info->flags, orig_bytes, 1);
ret = 0; ret = 0;
} else if (can_overcommit(fs_info, space_info, orig_bytes, flush, } else if (can_overcommit(fs_info, space_info, orig_bytes, flush,
system_chunk)) { system_chunk)) {
update_bytes_may_use(space_info, orig_bytes); update_bytes_may_use(fs_info, space_info, orig_bytes);
trace_btrfs_space_reservation(fs_info, "space_info", trace_btrfs_space_reservation(fs_info, "space_info",
space_info->flags, orig_bytes, 1); space_info->flags, orig_bytes, 1);
ret = 0; ret = 0;
...@@ -5503,7 +5505,7 @@ static void space_info_add_old_bytes(struct btrfs_fs_info *fs_info, ...@@ -5503,7 +5505,7 @@ static void space_info_add_old_bytes(struct btrfs_fs_info *fs_info,
flush = BTRFS_RESERVE_FLUSH_ALL; flush = BTRFS_RESERVE_FLUSH_ALL;
goto again; goto again;
} }
update_bytes_may_use(space_info, -num_bytes); update_bytes_may_use(fs_info, space_info, -num_bytes);
trace_btrfs_space_reservation(fs_info, "space_info", trace_btrfs_space_reservation(fs_info, "space_info",
space_info->flags, num_bytes, 0); space_info->flags, num_bytes, 0);
spin_unlock(&space_info->lock); spin_unlock(&space_info->lock);
...@@ -5531,7 +5533,8 @@ static void space_info_add_new_bytes(struct btrfs_fs_info *fs_info, ...@@ -5531,7 +5533,8 @@ static void space_info_add_new_bytes(struct btrfs_fs_info *fs_info,
ticket->bytes, 1); ticket->bytes, 1);
list_del_init(&ticket->list); list_del_init(&ticket->list);
num_bytes -= ticket->bytes; num_bytes -= ticket->bytes;
update_bytes_may_use(space_info, ticket->bytes); update_bytes_may_use(fs_info, space_info,
ticket->bytes);
ticket->bytes = 0; ticket->bytes = 0;
space_info->tickets_id++; space_info->tickets_id++;
wake_up(&ticket->wait); wake_up(&ticket->wait);
...@@ -5539,7 +5542,7 @@ static void space_info_add_new_bytes(struct btrfs_fs_info *fs_info, ...@@ -5539,7 +5542,7 @@ static void space_info_add_new_bytes(struct btrfs_fs_info *fs_info,
trace_btrfs_space_reservation(fs_info, "space_info", trace_btrfs_space_reservation(fs_info, "space_info",
space_info->flags, space_info->flags,
num_bytes, 1); num_bytes, 1);
update_bytes_may_use(space_info, num_bytes); update_bytes_may_use(fs_info, space_info, num_bytes);
ticket->bytes -= num_bytes; ticket->bytes -= num_bytes;
num_bytes = 0; num_bytes = 0;
} }
...@@ -5832,14 +5835,14 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info) ...@@ -5832,14 +5835,14 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
num_bytes = min(num_bytes, num_bytes = min(num_bytes,
block_rsv->size - block_rsv->reserved); block_rsv->size - block_rsv->reserved);
block_rsv->reserved += num_bytes; block_rsv->reserved += num_bytes;
update_bytes_may_use(sinfo, num_bytes); update_bytes_may_use(fs_info, sinfo, num_bytes);
trace_btrfs_space_reservation(fs_info, "space_info", trace_btrfs_space_reservation(fs_info, "space_info",
sinfo->flags, num_bytes, sinfo->flags, num_bytes,
1); 1);
} }
} else if (block_rsv->reserved > block_rsv->size) { } else if (block_rsv->reserved > block_rsv->size) {
num_bytes = block_rsv->reserved - block_rsv->size; num_bytes = block_rsv->reserved - block_rsv->size;
update_bytes_may_use(sinfo, -num_bytes); update_bytes_may_use(fs_info, sinfo, -num_bytes);
trace_btrfs_space_reservation(fs_info, "space_info", trace_btrfs_space_reservation(fs_info, "space_info",
sinfo->flags, num_bytes, 0); sinfo->flags, num_bytes, 0);
block_rsv->reserved = block_rsv->size; block_rsv->reserved = block_rsv->size;
...@@ -6302,7 +6305,7 @@ static int update_block_group(struct btrfs_trans_handle *trans, ...@@ -6302,7 +6305,7 @@ static int update_block_group(struct btrfs_trans_handle *trans,
old_val -= num_bytes; old_val -= num_bytes;
btrfs_set_block_group_used(&cache->item, old_val); btrfs_set_block_group_used(&cache->item, old_val);
cache->pinned += num_bytes; cache->pinned += num_bytes;
update_bytes_pinned(cache->space_info, num_bytes); update_bytes_pinned(info, cache->space_info, num_bytes);
cache->space_info->bytes_used -= num_bytes; cache->space_info->bytes_used -= num_bytes;
cache->space_info->disk_used -= num_bytes * factor; cache->space_info->disk_used -= num_bytes * factor;
spin_unlock(&cache->lock); spin_unlock(&cache->lock);
...@@ -6377,7 +6380,7 @@ static int pin_down_extent(struct btrfs_block_group_cache *cache, ...@@ -6377,7 +6380,7 @@ static int pin_down_extent(struct btrfs_block_group_cache *cache,
spin_lock(&cache->space_info->lock); spin_lock(&cache->space_info->lock);
spin_lock(&cache->lock); spin_lock(&cache->lock);
cache->pinned += num_bytes; cache->pinned += num_bytes;
update_bytes_pinned(cache->space_info, num_bytes); update_bytes_pinned(fs_info, cache->space_info, num_bytes);
if (reserved) { if (reserved) {
cache->reserved -= num_bytes; cache->reserved -= num_bytes;
cache->space_info->bytes_reserved -= num_bytes; cache->space_info->bytes_reserved -= num_bytes;
...@@ -6586,7 +6589,7 @@ static int btrfs_add_reserved_bytes(struct btrfs_block_group_cache *cache, ...@@ -6586,7 +6589,7 @@ static int btrfs_add_reserved_bytes(struct btrfs_block_group_cache *cache,
} else { } else {
cache->reserved += num_bytes; cache->reserved += num_bytes;
space_info->bytes_reserved += num_bytes; space_info->bytes_reserved += num_bytes;
update_bytes_may_use(space_info, -ram_bytes); update_bytes_may_use(cache->fs_info, space_info, -ram_bytes);
if (delalloc) if (delalloc)
cache->delalloc_bytes += num_bytes; cache->delalloc_bytes += num_bytes;
} }
...@@ -6742,7 +6745,7 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info, ...@@ -6742,7 +6745,7 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info,
spin_lock(&space_info->lock); spin_lock(&space_info->lock);
spin_lock(&cache->lock); spin_lock(&cache->lock);
cache->pinned -= len; cache->pinned -= len;
update_bytes_pinned(space_info, -len); update_bytes_pinned(fs_info, space_info, -len);
trace_btrfs_space_reservation(fs_info, "pinned", trace_btrfs_space_reservation(fs_info, "pinned",
space_info->flags, len, 0); space_info->flags, len, 0);
...@@ -6763,7 +6766,8 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info, ...@@ -6763,7 +6766,8 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info,
to_add = min(len, global_rsv->size - to_add = min(len, global_rsv->size -
global_rsv->reserved); global_rsv->reserved);
global_rsv->reserved += to_add; global_rsv->reserved += to_add;
update_bytes_may_use(space_info, to_add); update_bytes_may_use(fs_info, space_info,
to_add);
if (global_rsv->reserved >= global_rsv->size) if (global_rsv->reserved >= global_rsv->size)
global_rsv->full = 1; global_rsv->full = 1;
trace_btrfs_space_reservation(fs_info, trace_btrfs_space_reservation(fs_info,
...@@ -11024,7 +11028,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) ...@@ -11024,7 +11028,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
spin_lock(&space_info->lock); spin_lock(&space_info->lock);
spin_lock(&block_group->lock); spin_lock(&block_group->lock);
update_bytes_pinned(space_info, -block_group->pinned); update_bytes_pinned(fs_info, space_info, -block_group->pinned);
space_info->bytes_readonly += block_group->pinned; space_info->bytes_readonly += block_group->pinned;
percpu_counter_add_batch(&space_info->total_bytes_pinned, percpu_counter_add_batch(&space_info->total_bytes_pinned,
-block_group->pinned, -block_group->pinned,
......
...@@ -29,6 +29,7 @@ struct btrfs_qgroup_extent_record; ...@@ -29,6 +29,7 @@ struct btrfs_qgroup_extent_record;
struct btrfs_qgroup; struct btrfs_qgroup;
struct extent_io_tree; struct extent_io_tree;
struct prelim_ref; struct prelim_ref;
struct btrfs_space_info;
TRACE_DEFINE_ENUM(FLUSH_DELAYED_ITEMS_NR); TRACE_DEFINE_ENUM(FLUSH_DELAYED_ITEMS_NR);
TRACE_DEFINE_ENUM(FLUSH_DELAYED_ITEMS); TRACE_DEFINE_ENUM(FLUSH_DELAYED_ITEMS);
...@@ -2091,6 +2092,45 @@ DEFINE_BTRFS_LOCK_EVENT(btrfs_try_tree_read_lock); ...@@ -2091,6 +2092,45 @@ DEFINE_BTRFS_LOCK_EVENT(btrfs_try_tree_read_lock);
DEFINE_BTRFS_LOCK_EVENT(btrfs_try_tree_write_lock); DEFINE_BTRFS_LOCK_EVENT(btrfs_try_tree_write_lock);
DEFINE_BTRFS_LOCK_EVENT(btrfs_tree_read_lock_atomic); DEFINE_BTRFS_LOCK_EVENT(btrfs_tree_read_lock_atomic);
DECLARE_EVENT_CLASS(btrfs__space_info_update,
TP_PROTO(struct btrfs_fs_info *fs_info,
struct btrfs_space_info *sinfo, u64 old, s64 diff),
TP_ARGS(fs_info, sinfo, old, diff),
TP_STRUCT__entry_btrfs(
__field( u64, type )
__field( u64, old )
__field( s64, diff )
),
TP_fast_assign_btrfs(fs_info,
__entry->type = sinfo->flags;
__entry->old = old;
__entry->diff = diff;
),
TP_printk_btrfs("type=%s old=%llu diff=%lld",
__print_flags(__entry->type, "|", BTRFS_GROUP_FLAGS),
__entry->old, __entry->diff)
);
DEFINE_EVENT(btrfs__space_info_update, update_bytes_may_use,
TP_PROTO(struct btrfs_fs_info *fs_info,
struct btrfs_space_info *sinfo, u64 old, s64 diff),
TP_ARGS(fs_info, sinfo, old, diff)
);
DEFINE_EVENT(btrfs__space_info_update, update_bytes_pinned,
TP_PROTO(struct btrfs_fs_info *fs_info,
struct btrfs_space_info *sinfo, u64 old, s64 diff),
TP_ARGS(fs_info, sinfo, old, diff)
);
#endif /* _TRACE_BTRFS_H */ #endif /* _TRACE_BTRFS_H */
/* This part must be outside protection */ /* This part must be outside protection */
......
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