diff mbox series

btrfs: add tracepoints for ordered extents

Message ID 6bd882fd0562b8b18600629f7d0504f98c560dcf.1654792073.git.johannes.thumshirn@wdc.com (mailing list archive)
State New, archived
Headers show
Series btrfs: add tracepoints for ordered extents | expand

Commit Message

Johannes Thumshirn June 9, 2022, 4:28 p.m. UTC
When debugging a reference counting issue with ordered extents, I've found
we're lacking a lot of tracepoint coverage in the ordered-extent code.

Close these gaps by adding tracepoints after every refcount_inc() in the
ordered-extent code.

Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
---
 fs/btrfs/ordered-data.c      | 19 +++++++++--
 include/trace/events/btrfs.h | 64 ++++++++++++++++++++++++++++++++++++
 2 files changed, 80 insertions(+), 3 deletions(-)

Comments

Boris Burkov June 9, 2022, 5:17 p.m. UTC | #1
On Thu, Jun 09, 2022 at 09:28:04AM -0700, Johannes Thumshirn wrote:
> When debugging a reference counting issue with ordered extents, I've found
> we're lacking a lot of tracepoint coverage in the ordered-extent code.
> 
> Close these gaps by adding tracepoints after every refcount_inc() in the
> ordered-extent code.
> 
> Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

Looks good, I see the new tracepoints. I think it would be helpful for
posterity to motivate why refcount_inc is what we want to trace.

Reviewed-by: Boris Burkov <boris@bur.io>

> ---
>  fs/btrfs/ordered-data.c      | 19 +++++++++--
>  include/trace/events/btrfs.h | 64 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 80 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
> index dc88d2b3721f..41b3bc44c92b 100644
> --- a/fs/btrfs/ordered-data.c
> +++ b/fs/btrfs/ordered-data.c
> @@ -401,6 +401,7 @@ void btrfs_mark_ordered_io_finished(struct btrfs_inode *inode,
>  			set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags);
>  			cond_wake_up(&entry->wait);
>  			refcount_inc(&entry->refs);
> +			trace_btrfs_ordered_extent_mark_finished(inode, entry);
>  			spin_unlock_irqrestore(&tree->lock, flags);
>  			btrfs_init_work(&entry->work, finish_func, NULL, NULL);
>  			btrfs_queue_work(wq, &entry->work);
> @@ -473,6 +474,7 @@ bool btrfs_dec_test_ordered_pending(struct btrfs_inode *inode,
>  	if (finished && cached && entry) {
>  		*cached = entry;
>  		refcount_inc(&entry->refs);
> +		trace_btrfs_ordered_extent_dec_test_pending(inode, entry);
>  	}
>  	spin_unlock_irqrestore(&tree->lock, flags);
>  	return finished;
> @@ -807,8 +809,10 @@ struct btrfs_ordered_extent *btrfs_lookup_ordered_extent(struct btrfs_inode *ino
>  	entry = rb_entry(node, struct btrfs_ordered_extent, rb_node);
>  	if (!in_range(file_offset, entry->file_offset, entry->num_bytes))
>  		entry = NULL;
> -	if (entry)
> +	if (entry) {
>  		refcount_inc(&entry->refs);
> +		trace_btrfs_ordered_extent_lookup(inode, entry);
> +	}
>  out:
>  	spin_unlock_irqrestore(&tree->lock, flags);
>  	return entry;
> @@ -848,8 +852,10 @@ struct btrfs_ordered_extent *btrfs_lookup_ordered_range(
>  			break;
>  	}
>  out:
> -	if (entry)
> +	if (entry) {
>  		refcount_inc(&entry->refs);
> +		trace_btrfs_ordered_extent_lookup_range(inode, entry);
> +	}
>  	spin_unlock_irq(&tree->lock);
>  	return entry;
>  }
> @@ -878,6 +884,7 @@ void btrfs_get_ordered_extents_for_logging(struct btrfs_inode *inode,
>  		ASSERT(list_empty(&ordered->log_list));
>  		list_add_tail(&ordered->log_list, list);
>  		refcount_inc(&ordered->refs);
> +		trace_btrfs_ordered_extent_lookup_for_logging(inode, ordered);
>  	}
>  	spin_unlock_irq(&tree->lock);
>  }
> @@ -901,6 +908,7 @@ btrfs_lookup_first_ordered_extent(struct btrfs_inode *inode, u64 file_offset)
>  
>  	entry = rb_entry(node, struct btrfs_ordered_extent, rb_node);
>  	refcount_inc(&entry->refs);
> +	trace_btrfs_ordered_extent_lookup_first(inode, entry);
>  out:
>  	spin_unlock_irq(&tree->lock);
>  	return entry;
> @@ -975,8 +983,11 @@ struct btrfs_ordered_extent *btrfs_lookup_first_ordered_range(
>  	/* No ordered extent in the range */
>  	entry = NULL;
>  out:
> -	if (entry)
> +	if (entry) {
>  		refcount_inc(&entry->refs);
> +		trace_btrfs_ordered_extent_lookup_first_range(inode, entry);
> +	}
> +
>  	spin_unlock_irq(&tree->lock);
>  	return entry;
>  }
> @@ -1055,6 +1066,8 @@ int btrfs_split_ordered_extent(struct btrfs_ordered_extent *ordered, u64 pre,
>  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
>  	int ret = 0;
>  
> +	trace_btrfs_ordered_extent_split(BTRFS_I(inode), ordered);
> +
>  	spin_lock_irq(&tree->lock);
>  	/* Remove from tree once */
>  	node = &ordered->rb_node;
> diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h
> index 29fa8ea2cc0f..73df80d462dc 100644
> --- a/include/trace/events/btrfs.h
> +++ b/include/trace/events/btrfs.h
> @@ -598,6 +598,70 @@ DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_put,
>  	TP_ARGS(inode, ordered)
>  );
>  
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup_range,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup_first_range,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup_for_logging,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup_first,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_split,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_dec_test_pending,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_mark_finished,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
>  DECLARE_EVENT_CLASS(btrfs__writepage,
>  
>  	TP_PROTO(const struct page *page, const struct inode *inode,
> -- 
> 2.35.3
>
Qu Wenruo June 10, 2022, 9:17 a.m. UTC | #2
On 2022/6/10 00:28, Johannes Thumshirn wrote:
> When debugging a reference counting issue with ordered extents, I've found
> we're lacking a lot of tracepoint coverage in the ordered-extent code.
>
> Close these gaps by adding tracepoints after every refcount_inc() in the
> ordered-extent code.
>
> Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
> ---
>   fs/btrfs/ordered-data.c      | 19 +++++++++--
>   include/trace/events/btrfs.h | 64 ++++++++++++++++++++++++++++++++++++
>   2 files changed, 80 insertions(+), 3 deletions(-)
>
> diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
> index dc88d2b3721f..41b3bc44c92b 100644
> --- a/fs/btrfs/ordered-data.c
> +++ b/fs/btrfs/ordered-data.c
> @@ -401,6 +401,7 @@ void btrfs_mark_ordered_io_finished(struct btrfs_inode *inode,
>   			set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags);
>   			cond_wake_up(&entry->wait);
>   			refcount_inc(&entry->refs);
> +			trace_btrfs_ordered_extent_mark_finished(inode, entry);
>   			spin_unlock_irqrestore(&tree->lock, flags);
>   			btrfs_init_work(&entry->work, finish_func, NULL, NULL);
>   			btrfs_queue_work(wq, &entry->work);
> @@ -473,6 +474,7 @@ bool btrfs_dec_test_ordered_pending(struct btrfs_inode *inode,
>   	if (finished && cached && entry) {
>   		*cached = entry;
>   		refcount_inc(&entry->refs);
> +		trace_btrfs_ordered_extent_dec_test_pending(inode, entry);
>   	}
>   	spin_unlock_irqrestore(&tree->lock, flags);
>   	return finished;
> @@ -807,8 +809,10 @@ struct btrfs_ordered_extent *btrfs_lookup_ordered_extent(struct btrfs_inode *ino
>   	entry = rb_entry(node, struct btrfs_ordered_extent, rb_node);
>   	if (!in_range(file_offset, entry->file_offset, entry->num_bytes))
>   		entry = NULL;
> -	if (entry)
> +	if (entry) {
>   		refcount_inc(&entry->refs);
> +		trace_btrfs_ordered_extent_lookup(inode, entry);
> +	}
>   out:
>   	spin_unlock_irqrestore(&tree->lock, flags);
>   	return entry;
> @@ -848,8 +852,10 @@ struct btrfs_ordered_extent *btrfs_lookup_ordered_range(
>   			break;
>   	}
>   out:
> -	if (entry)
> +	if (entry) {
>   		refcount_inc(&entry->refs);
> +		trace_btrfs_ordered_extent_lookup_range(inode, entry);
> +	}
>   	spin_unlock_irq(&tree->lock);
>   	return entry;
>   }
> @@ -878,6 +884,7 @@ void btrfs_get_ordered_extents_for_logging(struct btrfs_inode *inode,
>   		ASSERT(list_empty(&ordered->log_list));
>   		list_add_tail(&ordered->log_list, list);
>   		refcount_inc(&ordered->refs);
> +		trace_btrfs_ordered_extent_lookup_for_logging(inode, ordered);
>   	}
>   	spin_unlock_irq(&tree->lock);
>   }
> @@ -901,6 +908,7 @@ btrfs_lookup_first_ordered_extent(struct btrfs_inode *inode, u64 file_offset)
>
>   	entry = rb_entry(node, struct btrfs_ordered_extent, rb_node);
>   	refcount_inc(&entry->refs);
> +	trace_btrfs_ordered_extent_lookup_first(inode, entry);
>   out:
>   	spin_unlock_irq(&tree->lock);
>   	return entry;
> @@ -975,8 +983,11 @@ struct btrfs_ordered_extent *btrfs_lookup_first_ordered_range(
>   	/* No ordered extent in the range */
>   	entry = NULL;
>   out:
> -	if (entry)
> +	if (entry) {
>   		refcount_inc(&entry->refs);
> +		trace_btrfs_ordered_extent_lookup_first_range(inode, entry);
> +	}
> +
>   	spin_unlock_irq(&tree->lock);
>   	return entry;
>   }
> @@ -1055,6 +1066,8 @@ int btrfs_split_ordered_extent(struct btrfs_ordered_extent *ordered, u64 pre,
>   	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
>   	int ret = 0;
>
> +	trace_btrfs_ordered_extent_split(BTRFS_I(inode), ordered);

I guess this doesn't have all the info for this split event?
Like pre/post values?

Although we will call clone_ordered_extent() which will call
btrfs_add_ordered_extent() and trigger the event for add.

It still doesn't really show the pre/post values directly.

Is there better way to just add extra members for the existing trace
event class?
If not, I guess that's all what we can do right now...

Thanks,
Qu


> +
>   	spin_lock_irq(&tree->lock);
>   	/* Remove from tree once */
>   	node = &ordered->rb_node;
> diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h
> index 29fa8ea2cc0f..73df80d462dc 100644
> --- a/include/trace/events/btrfs.h
> +++ b/include/trace/events/btrfs.h
> @@ -598,6 +598,70 @@ DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_put,
>   	TP_ARGS(inode, ordered)
>   );
>
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup_range,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup_first_range,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup_for_logging,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup_first,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_split,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_dec_test_pending,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_mark_finished,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
>   DECLARE_EVENT_CLASS(btrfs__writepage,
>
>   	TP_PROTO(const struct page *page, const struct inode *inode,
Johannes Thumshirn June 10, 2022, 10:07 a.m. UTC | #3
On 10.06.22 11:17, Qu Wenruo wrote:
>> +	trace_btrfs_ordered_extent_split(BTRFS_I(inode), ordered);
> 
> I guess this doesn't have all the info for this split event?
> Like pre/post values?
> 
> Although we will call clone_ordered_extent() which will call
> btrfs_add_ordered_extent() and trigger the event for add.
> 
> It still doesn't really show the pre/post values directly.
> 

Yup, unfortunately you need to do the math on your own.

> Is there better way to just add extra members for the existing trace
> event class?
> If not, I guess that's all what we can do right now...
> 

Not that I know of, hence why I had to do it this way.
Qu Wenruo June 10, 2022, 10:18 a.m. UTC | #4
On 2022/6/10 18:07, Johannes Thumshirn wrote:
> On 10.06.22 11:17, Qu Wenruo wrote:
>>> +	trace_btrfs_ordered_extent_split(BTRFS_I(inode), ordered);
>>
>> I guess this doesn't have all the info for this split event?
>> Like pre/post values?
>>
>> Although we will call clone_ordered_extent() which will call
>> btrfs_add_ordered_extent() and trigger the event for add.
>>
>> It still doesn't really show the pre/post values directly.
>>
>
> Yup, unfortunately you need to do the math on your own.
>
>> Is there better way to just add extra members for the existing trace
>> event class?
>> If not, I guess that's all what we can do right now...
>>
>
> Not that I know of, hence why I had to do it this way.

OK, then it looks fine to me.

Reviewed-by: Qu Wenruo <wqu@suse.com>

Thanks,
Qu
Anand Jain June 11, 2022, 1:36 p.m. UTC | #5
On 6/9/22 21:58, Johannes Thumshirn wrote:
> When debugging a reference counting issue with ordered extents, I've found
> we're lacking a lot of tracepoint coverage in the ordered-extent code.
> 
> Close these gaps by adding tracepoints after every refcount_inc() in the
> ordered-extent code.
> 
> Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

LGTM

Reviewed-by: Anand Jain <anand.jain@oracle.com>



> ---
>   fs/btrfs/ordered-data.c      | 19 +++++++++--
>   include/trace/events/btrfs.h | 64 ++++++++++++++++++++++++++++++++++++
>   2 files changed, 80 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
> index dc88d2b3721f..41b3bc44c92b 100644
> --- a/fs/btrfs/ordered-data.c
> +++ b/fs/btrfs/ordered-data.c
> @@ -401,6 +401,7 @@ void btrfs_mark_ordered_io_finished(struct btrfs_inode *inode,
>   			set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags);
>   			cond_wake_up(&entry->wait);
>   			refcount_inc(&entry->refs);
> +			trace_btrfs_ordered_extent_mark_finished(inode, entry);
>   			spin_unlock_irqrestore(&tree->lock, flags);
>   			btrfs_init_work(&entry->work, finish_func, NULL, NULL);
>   			btrfs_queue_work(wq, &entry->work);
> @@ -473,6 +474,7 @@ bool btrfs_dec_test_ordered_pending(struct btrfs_inode *inode,
>   	if (finished && cached && entry) {
>   		*cached = entry;
>   		refcount_inc(&entry->refs);
> +		trace_btrfs_ordered_extent_dec_test_pending(inode, entry);
>   	}
>   	spin_unlock_irqrestore(&tree->lock, flags);
>   	return finished;
> @@ -807,8 +809,10 @@ struct btrfs_ordered_extent *btrfs_lookup_ordered_extent(struct btrfs_inode *ino
>   	entry = rb_entry(node, struct btrfs_ordered_extent, rb_node);
>   	if (!in_range(file_offset, entry->file_offset, entry->num_bytes))
>   		entry = NULL;
> -	if (entry)
> +	if (entry) {
>   		refcount_inc(&entry->refs);
> +		trace_btrfs_ordered_extent_lookup(inode, entry);
> +	}
>   out:
>   	spin_unlock_irqrestore(&tree->lock, flags);
>   	return entry;
> @@ -848,8 +852,10 @@ struct btrfs_ordered_extent *btrfs_lookup_ordered_range(
>   			break;
>   	}
>   out:
> -	if (entry)
> +	if (entry) {
>   		refcount_inc(&entry->refs);
> +		trace_btrfs_ordered_extent_lookup_range(inode, entry);
> +	}
>   	spin_unlock_irq(&tree->lock);
>   	return entry;
>   }
> @@ -878,6 +884,7 @@ void btrfs_get_ordered_extents_for_logging(struct btrfs_inode *inode,
>   		ASSERT(list_empty(&ordered->log_list));
>   		list_add_tail(&ordered->log_list, list);
>   		refcount_inc(&ordered->refs);
> +		trace_btrfs_ordered_extent_lookup_for_logging(inode, ordered);
>   	}
>   	spin_unlock_irq(&tree->lock);
>   }
> @@ -901,6 +908,7 @@ btrfs_lookup_first_ordered_extent(struct btrfs_inode *inode, u64 file_offset)
>   
>   	entry = rb_entry(node, struct btrfs_ordered_extent, rb_node);
>   	refcount_inc(&entry->refs);
> +	trace_btrfs_ordered_extent_lookup_first(inode, entry);
>   out:
>   	spin_unlock_irq(&tree->lock);
>   	return entry;
> @@ -975,8 +983,11 @@ struct btrfs_ordered_extent *btrfs_lookup_first_ordered_range(
>   	/* No ordered extent in the range */
>   	entry = NULL;
>   out:
> -	if (entry)
> +	if (entry) {
>   		refcount_inc(&entry->refs);
> +		trace_btrfs_ordered_extent_lookup_first_range(inode, entry);
> +	}
> +
>   	spin_unlock_irq(&tree->lock);
>   	return entry;
>   }
> @@ -1055,6 +1066,8 @@ int btrfs_split_ordered_extent(struct btrfs_ordered_extent *ordered, u64 pre,
>   	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
>   	int ret = 0;
>   
> +	trace_btrfs_ordered_extent_split(BTRFS_I(inode), ordered);
> +
>   	spin_lock_irq(&tree->lock);
>   	/* Remove from tree once */
>   	node = &ordered->rb_node;
> diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h
> index 29fa8ea2cc0f..73df80d462dc 100644
> --- a/include/trace/events/btrfs.h
> +++ b/include/trace/events/btrfs.h
> @@ -598,6 +598,70 @@ DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_put,
>   	TP_ARGS(inode, ordered)
>   );
>   
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup_range,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup_first_range,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup_for_logging,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup_first,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_split,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_dec_test_pending,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
> +DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_mark_finished,
> +
> +	     TP_PROTO(const struct btrfs_inode *inode,
> +		      const struct btrfs_ordered_extent *ordered),
> +
> +	     TP_ARGS(inode, ordered)
> +);
> +
>   DECLARE_EVENT_CLASS(btrfs__writepage,
>   
>   	TP_PROTO(const struct page *page, const struct inode *inode,
David Sterba June 13, 2022, 6:45 p.m. UTC | #6
On Thu, Jun 09, 2022 at 09:28:04AM -0700, Johannes Thumshirn wrote:
> When debugging a reference counting issue with ordered extents, I've found
> we're lacking a lot of tracepoint coverage in the ordered-extent code.
> 
> Close these gaps by adding tracepoints after every refcount_inc() in the
> ordered-extent code.
> 
> Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

Added to misc-next, thanks.
diff mbox series

Patch

diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
index dc88d2b3721f..41b3bc44c92b 100644
--- a/fs/btrfs/ordered-data.c
+++ b/fs/btrfs/ordered-data.c
@@ -401,6 +401,7 @@  void btrfs_mark_ordered_io_finished(struct btrfs_inode *inode,
 			set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags);
 			cond_wake_up(&entry->wait);
 			refcount_inc(&entry->refs);
+			trace_btrfs_ordered_extent_mark_finished(inode, entry);
 			spin_unlock_irqrestore(&tree->lock, flags);
 			btrfs_init_work(&entry->work, finish_func, NULL, NULL);
 			btrfs_queue_work(wq, &entry->work);
@@ -473,6 +474,7 @@  bool btrfs_dec_test_ordered_pending(struct btrfs_inode *inode,
 	if (finished && cached && entry) {
 		*cached = entry;
 		refcount_inc(&entry->refs);
+		trace_btrfs_ordered_extent_dec_test_pending(inode, entry);
 	}
 	spin_unlock_irqrestore(&tree->lock, flags);
 	return finished;
@@ -807,8 +809,10 @@  struct btrfs_ordered_extent *btrfs_lookup_ordered_extent(struct btrfs_inode *ino
 	entry = rb_entry(node, struct btrfs_ordered_extent, rb_node);
 	if (!in_range(file_offset, entry->file_offset, entry->num_bytes))
 		entry = NULL;
-	if (entry)
+	if (entry) {
 		refcount_inc(&entry->refs);
+		trace_btrfs_ordered_extent_lookup(inode, entry);
+	}
 out:
 	spin_unlock_irqrestore(&tree->lock, flags);
 	return entry;
@@ -848,8 +852,10 @@  struct btrfs_ordered_extent *btrfs_lookup_ordered_range(
 			break;
 	}
 out:
-	if (entry)
+	if (entry) {
 		refcount_inc(&entry->refs);
+		trace_btrfs_ordered_extent_lookup_range(inode, entry);
+	}
 	spin_unlock_irq(&tree->lock);
 	return entry;
 }
@@ -878,6 +884,7 @@  void btrfs_get_ordered_extents_for_logging(struct btrfs_inode *inode,
 		ASSERT(list_empty(&ordered->log_list));
 		list_add_tail(&ordered->log_list, list);
 		refcount_inc(&ordered->refs);
+		trace_btrfs_ordered_extent_lookup_for_logging(inode, ordered);
 	}
 	spin_unlock_irq(&tree->lock);
 }
@@ -901,6 +908,7 @@  btrfs_lookup_first_ordered_extent(struct btrfs_inode *inode, u64 file_offset)
 
 	entry = rb_entry(node, struct btrfs_ordered_extent, rb_node);
 	refcount_inc(&entry->refs);
+	trace_btrfs_ordered_extent_lookup_first(inode, entry);
 out:
 	spin_unlock_irq(&tree->lock);
 	return entry;
@@ -975,8 +983,11 @@  struct btrfs_ordered_extent *btrfs_lookup_first_ordered_range(
 	/* No ordered extent in the range */
 	entry = NULL;
 out:
-	if (entry)
+	if (entry) {
 		refcount_inc(&entry->refs);
+		trace_btrfs_ordered_extent_lookup_first_range(inode, entry);
+	}
+
 	spin_unlock_irq(&tree->lock);
 	return entry;
 }
@@ -1055,6 +1066,8 @@  int btrfs_split_ordered_extent(struct btrfs_ordered_extent *ordered, u64 pre,
 	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
 	int ret = 0;
 
+	trace_btrfs_ordered_extent_split(BTRFS_I(inode), ordered);
+
 	spin_lock_irq(&tree->lock);
 	/* Remove from tree once */
 	node = &ordered->rb_node;
diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h
index 29fa8ea2cc0f..73df80d462dc 100644
--- a/include/trace/events/btrfs.h
+++ b/include/trace/events/btrfs.h
@@ -598,6 +598,70 @@  DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_put,
 	TP_ARGS(inode, ordered)
 );
 
+DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup,
+
+	     TP_PROTO(const struct btrfs_inode *inode,
+		      const struct btrfs_ordered_extent *ordered),
+
+	     TP_ARGS(inode, ordered)
+);
+
+DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup_range,
+
+	     TP_PROTO(const struct btrfs_inode *inode,
+		      const struct btrfs_ordered_extent *ordered),
+
+	     TP_ARGS(inode, ordered)
+);
+
+DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup_first_range,
+
+	     TP_PROTO(const struct btrfs_inode *inode,
+		      const struct btrfs_ordered_extent *ordered),
+
+	     TP_ARGS(inode, ordered)
+);
+
+DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup_for_logging,
+
+	     TP_PROTO(const struct btrfs_inode *inode,
+		      const struct btrfs_ordered_extent *ordered),
+
+	     TP_ARGS(inode, ordered)
+);
+
+DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_lookup_first,
+
+	     TP_PROTO(const struct btrfs_inode *inode,
+		      const struct btrfs_ordered_extent *ordered),
+
+	     TP_ARGS(inode, ordered)
+);
+
+DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_split,
+
+	     TP_PROTO(const struct btrfs_inode *inode,
+		      const struct btrfs_ordered_extent *ordered),
+
+	     TP_ARGS(inode, ordered)
+);
+
+DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_dec_test_pending,
+
+	     TP_PROTO(const struct btrfs_inode *inode,
+		      const struct btrfs_ordered_extent *ordered),
+
+	     TP_ARGS(inode, ordered)
+);
+
+DEFINE_EVENT(btrfs__ordered_extent, btrfs_ordered_extent_mark_finished,
+
+	     TP_PROTO(const struct btrfs_inode *inode,
+		      const struct btrfs_ordered_extent *ordered),
+
+	     TP_ARGS(inode, ordered)
+);
+
 DECLARE_EVENT_CLASS(btrfs__writepage,
 
 	TP_PROTO(const struct page *page, const struct inode *inode,