Re: [PATCH v2] dma-buf: add some tracepoints to debug.
From: Steven Rostedt <rostedt@goodmis.org>
Date: 2025-11-26 01:38:51
Also in:
dri-devel, linux-media, lkml
On Wed, 26 Nov 2025 00:29:49 +0800 Xiang Gao [off-list ref] wrote:
quoted hunk ↗ jump to hunk
+++ b/include/trace/events/dma_buf.h@@ -0,0 +1,281 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM dma_buf + +#if !defined(_TRACE_DMA_BUF_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_DMA_BUF_H + +#include <linux/dma-buf.h> +#include <linux/tracepoint.h> + +TRACE_EVENT(dma_buf_export, + + TP_PROTO(struct dma_buf *dmabuf), + + TP_ARGS(dmabuf), + + TP_STRUCT__entry( + __string(exp_name, dmabuf->exp_name) + __string(name, dmabuf->name) + __field(size_t, size) + __field(ino_t, ino) + __field(long, f_refcnt) + ), + + TP_fast_assign( + __assign_str(exp_name); + spin_lock(&dmabuf->name_lock); + __assign_str(name); + spin_unlock(&dmabuf->name_lock);
The above isn't doing what you think it's doing. The name is assigned before this by the above __string(name, dmabuf->name). You really shouldn't be taking any locks in a tracepoint. A tracepoint is a callback, that isn't called most of the time. You could be hiding very hard to find deadlocks by taking a lock in a tracepoint callback. You need to take the lock around the tracepoint call itself where it is called in the code. Not in the TRACE_EVENT. You may need to have something like:
@@ -220,6 +223,8 @@ static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct *vma) dmabuf->size >> PAGE_SHIFT) return -EINVAL; + if (trace_dma_buf_mmap_internal_enabled()) { + guard(spinlock)(&dmabuf->namelock); + trace_dma_buf_mmap_internal(dmabuf); + } + return dmabuf->ops->mmap(dmabuf, vma); }
The "trace_dma_buf_mmap_internal_enabled()" is a static branch, where it is either a nop or a jump to the tracing code. It's not a normal conditional branch. It acts the same as tracepoints themselves do.
+ __entry->size = dmabuf->size;
+ __entry->ino = dmabuf->file->f_inode->i_ino;
+ __entry->f_refcnt = file_count(dmabuf->file);
+ ),
+
+ TP_printk("exp_name=%s name=%s size=%zu ino=%lu f_refcnt=%ld",
+ __get_str(exp_name),
+ __get_str(name),
+ __entry->size,
+ __entry->ino,
+ __entry->f_refcnt)
+);Below seems to be a lot of very similar TRACE_EVENT()s. A TRACE_EVENT() is literally defined as: #define TRACE_EVENT(name, proto, args, tstruct, assign, print) \ DECLARE_EVENT_CLASS(name, \ PARAMS(proto), \ PARAMS(args), \ PARAMS(tstruct), \ PARAMS(assign), \ PARAMS(print)); \ DEFINE_EVENT(name, name, PARAMS(proto), PARAMS(args)); That is, it is both a DECLARE_EVENT_CLASS() and a DEFINE_EVENT(). You can make one DECLARE_EVENT_CLASS() and use many DEFINE_EVENT()s with it. Each DECLARE_EVENT_CLASS() takes up around 4 to 5 kilobytes of memory. Each DEFINE_EVENT() takes around 300 bytes to 1K of memory. The more DEFINE_EVENT()s you use with a single DECLARE_EVENT_CLASS(), the more memory you save. Please try to do that. -- Steve
+
+TRACE_EVENT(dma_buf_fd,
+
+ TP_PROTO(struct dma_buf *dmabuf, int fd),
+
+ TP_ARGS(dmabuf, fd),
+
+ TP_STRUCT__entry(
+ __string(exp_name, dmabuf->exp_name)
+ __string(name, dmabuf->name)
+ __field(size_t, size)
+ __field(ino_t, ino)
+ __field(int, fd)
+ __field(long, f_refcnt)
+ ),
+
+ TP_fast_assign(
+ __assign_str(exp_name);
+ spin_lock(&dmabuf->name_lock);
+ __assign_str(name);
+ spin_unlock(&dmabuf->name_lock);
+ __entry->size = dmabuf->size;
+ __entry->ino = dmabuf->file->f_inode->i_ino;
+ __entry->fd = fd;
+ __entry->f_refcnt = file_count(dmabuf->file);
+ ),
+
+ TP_printk("exp_name=%s name=%s size=%zu ino=%lu fd=%d f_refcnt=%ld",
+ __get_str(exp_name),
+ __get_str(name),
+ __entry->size,
+ __entry->ino,
+ __entry->fd,
+ __entry->f_refcnt)
+);
+
+TRACE_EVENT(dma_buf_mmap_internal,
+
+ TP_PROTO(struct dma_buf *dmabuf),
+
+ TP_ARGS(dmabuf),
+
+ TP_STRUCT__entry(
+ __string(exp_name, dmabuf->exp_name)
+ __string(name, dmabuf->name)
+ __field(size_t, size)
+ __field(ino_t, ino)
+ __field(long, f_refcnt)
+ ),
+
+ TP_fast_assign(
+ __assign_str(exp_name);
+ spin_lock(&dmabuf->name_lock);
+ __assign_str(name);
+ spin_unlock(&dmabuf->name_lock);
+ __entry->size = dmabuf->size;
+ __entry->ino = dmabuf->file->f_inode->i_ino;
+ __entry->f_refcnt = file_count(dmabuf->file);
+ ),
+
+ TP_printk("exp_name=%s name=%s size=%zu ino=%lu f_refcnt=%ld",
+ __get_str(exp_name),
+ __get_str(name),
+ __entry->size,
+ __entry->ino,
+ __entry->f_refcnt)
+);
+
+TRACE_EVENT(dma_buf_mmap,
+
+ TP_PROTO(struct dma_buf *dmabuf),
+
+ TP_ARGS(dmabuf),
+
+ TP_STRUCT__entry(
+ __string(exp_name, dmabuf->exp_name)
+ __string(name, dmabuf->name)
+ __field(size_t, size)
+ __field(ino_t, ino)
+ __field(long, f_refcnt)
+ ),
+
+ TP_fast_assign(
+ __assign_str(exp_name);
+ spin_lock(&dmabuf->name_lock);
+ __assign_str(name);
+ spin_unlock(&dmabuf->name_lock);
+ __entry->size = dmabuf->size;
+ __entry->ino = dmabuf->file->f_inode->i_ino;
+ __entry->f_refcnt = file_count(dmabuf->file);
+ ),
+
+ TP_printk("exp_name=%s name=%s size=%zu ino=%lu f_refcnt=%ld",
+ __get_str(exp_name),
+ __get_str(name),
+ __entry->size,
+ __entry->ino,
+ __entry->f_refcnt)
+);
+
+TRACE_EVENT(dma_buf_attach,
+
+ TP_PROTO(struct dma_buf *dmabuf, struct device *dev),
+
+ TP_ARGS(dmabuf, dev),
+
+ TP_STRUCT__entry(
+ __string(dname, dev_name(dev))
+ __string(exp_name, dmabuf->exp_name)
+ __string(name, dmabuf->name)
+ __field(size_t, size)
+ __field(ino_t, ino)
+ __field(long, f_refcnt)
+ ),
+
+ TP_fast_assign(
+ __assign_str(dname);
+ __assign_str(exp_name);
+ spin_lock(&dmabuf->name_lock);
+ __assign_str(name);
+ spin_unlock(&dmabuf->name_lock);
+ __entry->size = dmabuf->size;
+ __entry->ino = dmabuf->file->f_inode->i_ino;
+ __entry->f_refcnt = file_count(dmabuf->file);
+ ),
+
+ TP_printk("dev_name=%s exp_name=%s name=%s size=%zu ino=%lu f_refcnt=%ld",
+ __get_str(dname),
+ __get_str(exp_name),
+ __get_str(name),
+ __entry->size,
+ __entry->ino,
+ __entry->f_refcnt)
+);
+
+TRACE_EVENT(dma_buf_detach,
+
+ TP_PROTO(struct dma_buf *dmabuf),
+
+ TP_ARGS(dmabuf),
+
+ TP_STRUCT__entry(
+ __string(exp_name, dmabuf->exp_name)
+ __string(name, dmabuf->name)
+ __field(size_t, size)
+ __field(ino_t, ino)
+ __field(long, f_refcnt)
+ ),
+
+ TP_fast_assign(
+ __assign_str(exp_name);
+ spin_lock(&dmabuf->name_lock);
+ __assign_str(name);
+ spin_unlock(&dmabuf->name_lock);
+ __entry->size = dmabuf->size;
+ __entry->ino = dmabuf->file->f_inode->i_ino;
+ __entry->f_refcnt = file_count(dmabuf->file);
+ ),
+
+ TP_printk("exp_name=%s name=%s size=%zu ino=%lu f_refcnt=%ld",
+ __get_str(exp_name),
+ __get_str(name),
+ __entry->size,
+ __entry->ino,
+ __entry->f_refcnt)
+);
+
+TRACE_EVENT(dma_buf_get,
+
+ TP_PROTO(int fd, struct file *file),
+
+ TP_ARGS(fd, file),
+
+ TP_STRUCT__entry(
+ __string(exp_name, ((struct dma_buf *)file->private_data)->exp_name)
+ __string(name, ((struct dma_buf *)file->private_data)->name)
+ __field(size_t, size)
+ __field(ino_t, ino)
+ __field(int, fd)
+ __field(long, f_refcnt)
+ ),
+
+ TP_fast_assign(
+ struct dma_buf *dmabuf = (struct dma_buf *)file->private_data;
+
+ __assign_str(exp_name);
+ spin_lock(&dmabuf->name_lock);
+ __assign_str(name);
+ spin_unlock(&dmabuf->name_lock);
+ __entry->size = dmabuf->size;
+ __entry->ino = dmabuf->file->f_inode->i_ino;
+ __entry->fd = fd;
+ __entry->f_refcnt = file_count(file);
+ ),
+
+ TP_printk("exp_name=%s name=%s size=%zu ino=%lu fd=%d f_refcnt=%ld",
+ __get_str(exp_name),
+ __get_str(name),
+ __entry->size,
+ __entry->ino,
+ __entry->fd,
+ __entry->f_refcnt)
+);
+
+TRACE_EVENT(dma_buf_put,
+
+ TP_PROTO(struct dma_buf *dmabuf),
+
+ TP_ARGS(dmabuf),
+
+ TP_STRUCT__entry(
+ __string(exp_name, dmabuf->exp_name)
+ __string(name, dmabuf->name)
+ __field(size_t, size)
+ __field(ino_t, ino)
+ __field(long, f_refcnt)
+ ),
+
+ TP_fast_assign(
+ __assign_str(exp_name);
+ spin_lock(&dmabuf->name_lock);
+ __assign_str(name);
+ spin_unlock(&dmabuf->name_lock);
+ __entry->size = dmabuf->size;
+ __entry->ino = dmabuf->file->f_inode->i_ino;
+ __entry->f_refcnt = file_count(dmabuf->file);
+ ),
+
+ TP_printk("exp_name=%s name=%s size=%zu ino=%lu f_refcnt=%ld",
+ __get_str(exp_name),
+ __get_str(name),
+ __entry->size,
+ __entry->ino,
+ __entry->f_refcnt)
+);
+
+#endif /* _TRACE_DMA_BUF_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>