Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

dma-buf: Remove DMA-BUF sysfs stats

Commit bdb8d06dfefd ("dmabuf: Add the capability to expose DMA-BUF stats
in sysfs") added dmabuf statistics to sysfs in 2021 under
CONFIG_DMABUF_SYSFS_STATS. After being used in production, performance
problems were discovered leading to its deprecation in 2022 in commit
e0a9f1fe206a ("dma-buf: deprecate DMABUF_SYSFS_STATS"). Some of the
problems with this interface were discussed in my LPC 2025 talk. [1][2]

Android was probably the last user of the interface, which has since
been migrated to use the dmabuf BPF iterator [3] to obtain the same
information more cheaply. As promised in that series, now that the
longterm stable 6.18 kernel has been released let's remove the sysfs
dmabuf statistics from the kernel.

[1] https://www.youtube.com/watch?v=D83qygudq9c
[2] https://lpc.events/event/19/contributions/2118/
[3] https://lore.kernel.org/all/20250522230429.941193-1-tjmercier@google.com/

Signed-off-by: T.J. Mercier <tjmercier@google.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
Link: https://patch.msgid.link/20260116190517.3268458-1-tjmercier@google.com

authored by

T.J. Mercier and committed by
Sumit Semwal
ab4c3dcf 3c227be9

-312
-24
Documentation/ABI/testing/sysfs-kernel-dmabuf-buffers
··· 1 - What: /sys/kernel/dmabuf/buffers 2 - Date: May 2021 3 - KernelVersion: v5.13 4 - Contact: Hridya Valsaraju <hridya@google.com> 5 - Description: The /sys/kernel/dmabuf/buffers directory contains a 6 - snapshot of the internal state of every DMA-BUF. 7 - /sys/kernel/dmabuf/buffers/<inode_number> will contain the 8 - statistics for the DMA-BUF with the unique inode number 9 - <inode_number> 10 - Users: kernel memory tuning/debugging tools 11 - 12 - What: /sys/kernel/dmabuf/buffers/<inode_number>/exporter_name 13 - Date: May 2021 14 - KernelVersion: v5.13 15 - Contact: Hridya Valsaraju <hridya@google.com> 16 - Description: This file is read-only and contains the name of the exporter of 17 - the DMA-BUF. 18 - 19 - What: /sys/kernel/dmabuf/buffers/<inode_number>/size 20 - Date: May 2021 21 - KernelVersion: v5.13 22 - Contact: Hridya Valsaraju <hridya@google.com> 23 - Description: This file is read-only and specifies the size of the DMA-BUF in 24 - bytes.
-5
Documentation/driver-api/dma-buf.rst
··· 125 125 .. kernel-doc:: drivers/dma-buf/dma-buf.c 126 126 :doc: implicit fence polling 127 127 128 - DMA-BUF statistics 129 - ~~~~~~~~~~~~~~~~~~ 130 - .. kernel-doc:: drivers/dma-buf/dma-buf-sysfs-stats.c 131 - :doc: overview 132 - 133 128 DMA Buffer ioctls 134 129 ~~~~~~~~~~~~~~~~~ 135 130
-15
drivers/dma-buf/Kconfig
··· 75 75 allows userspace to allocate dma-bufs that can be shared 76 76 between drivers. 77 77 78 - menuconfig DMABUF_SYSFS_STATS 79 - bool "DMA-BUF sysfs statistics (DEPRECATED)" 80 - depends on DMA_SHARED_BUFFER 81 - help 82 - Choose this option to enable DMA-BUF sysfs statistics 83 - in location /sys/kernel/dmabuf/buffers. 84 - 85 - /sys/kernel/dmabuf/buffers/<inode_number> will contain 86 - statistics for the DMA-BUF with the unique inode number 87 - <inode_number>. 88 - 89 - This option is deprecated and should sooner or later be removed. 90 - Android is the only user of this and it turned out that this resulted 91 - in quite some performance problems. 92 - 93 78 source "drivers/dma-buf/heaps/Kconfig" 94 79 95 80 endmenu
-1
drivers/dma-buf/Makefile
··· 6 6 obj-$(CONFIG_SYNC_FILE) += sync_file.o 7 7 obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o 8 8 obj-$(CONFIG_UDMABUF) += udmabuf.o 9 - obj-$(CONFIG_DMABUF_SYSFS_STATS) += dma-buf-sysfs-stats.o 10 9 11 10 dmabuf_selftests-y := \ 12 11 selftest.o \
-202
drivers/dma-buf/dma-buf-sysfs-stats.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * DMA-BUF sysfs statistics. 4 - * 5 - * Copyright (C) 2021 Google LLC. 6 - */ 7 - 8 - #include <linux/dma-buf.h> 9 - #include <linux/dma-resv.h> 10 - #include <linux/kobject.h> 11 - #include <linux/printk.h> 12 - #include <linux/slab.h> 13 - #include <linux/sysfs.h> 14 - 15 - #include "dma-buf-sysfs-stats.h" 16 - 17 - #define to_dma_buf_entry_from_kobj(x) container_of(x, struct dma_buf_sysfs_entry, kobj) 18 - 19 - /** 20 - * DOC: overview 21 - * 22 - * ``/sys/kernel/debug/dma_buf/bufinfo`` provides an overview of every DMA-BUF 23 - * in the system. However, since debugfs is not safe to be mounted in 24 - * production, procfs and sysfs can be used to gather DMA-BUF statistics on 25 - * production systems. 26 - * 27 - * The ``/proc/<pid>/fdinfo/<fd>`` files in procfs can be used to gather 28 - * information about DMA-BUF fds. Detailed documentation about the interface 29 - * is present in Documentation/filesystems/proc.rst. 30 - * 31 - * Unfortunately, the existing procfs interfaces can only provide information 32 - * about the DMA-BUFs for which processes hold fds or have the buffers mmapped 33 - * into their address space. This necessitated the creation of the DMA-BUF sysfs 34 - * statistics interface to provide per-buffer information on production systems. 35 - * 36 - * The interface at ``/sys/kernel/dmabuf/buffers`` exposes information about 37 - * every DMA-BUF when ``CONFIG_DMABUF_SYSFS_STATS`` is enabled. 38 - * 39 - * The following stats are exposed by the interface: 40 - * 41 - * * ``/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name`` 42 - * * ``/sys/kernel/dmabuf/buffers/<inode_number>/size`` 43 - * 44 - * The information in the interface can also be used to derive per-exporter 45 - * statistics. The data from the interface can be gathered on error conditions 46 - * or other important events to provide a snapshot of DMA-BUF usage. 47 - * It can also be collected periodically by telemetry to monitor various metrics. 48 - * 49 - * Detailed documentation about the interface is present in 50 - * Documentation/ABI/testing/sysfs-kernel-dmabuf-buffers. 51 - */ 52 - 53 - struct dma_buf_stats_attribute { 54 - struct attribute attr; 55 - ssize_t (*show)(struct dma_buf *dmabuf, 56 - struct dma_buf_stats_attribute *attr, char *buf); 57 - }; 58 - #define to_dma_buf_stats_attr(x) container_of(x, struct dma_buf_stats_attribute, attr) 59 - 60 - static ssize_t dma_buf_stats_attribute_show(struct kobject *kobj, 61 - struct attribute *attr, 62 - char *buf) 63 - { 64 - struct dma_buf_stats_attribute *attribute; 65 - struct dma_buf_sysfs_entry *sysfs_entry; 66 - struct dma_buf *dmabuf; 67 - 68 - attribute = to_dma_buf_stats_attr(attr); 69 - sysfs_entry = to_dma_buf_entry_from_kobj(kobj); 70 - dmabuf = sysfs_entry->dmabuf; 71 - 72 - if (!dmabuf || !attribute->show) 73 - return -EIO; 74 - 75 - return attribute->show(dmabuf, attribute, buf); 76 - } 77 - 78 - static const struct sysfs_ops dma_buf_stats_sysfs_ops = { 79 - .show = dma_buf_stats_attribute_show, 80 - }; 81 - 82 - static ssize_t exporter_name_show(struct dma_buf *dmabuf, 83 - struct dma_buf_stats_attribute *attr, 84 - char *buf) 85 - { 86 - return sysfs_emit(buf, "%s\n", dmabuf->exp_name); 87 - } 88 - 89 - static ssize_t size_show(struct dma_buf *dmabuf, 90 - struct dma_buf_stats_attribute *attr, 91 - char *buf) 92 - { 93 - return sysfs_emit(buf, "%zu\n", dmabuf->size); 94 - } 95 - 96 - static struct dma_buf_stats_attribute exporter_name_attribute = 97 - __ATTR_RO(exporter_name); 98 - static struct dma_buf_stats_attribute size_attribute = __ATTR_RO(size); 99 - 100 - static struct attribute *dma_buf_stats_default_attrs[] = { 101 - &exporter_name_attribute.attr, 102 - &size_attribute.attr, 103 - NULL, 104 - }; 105 - ATTRIBUTE_GROUPS(dma_buf_stats_default); 106 - 107 - static void dma_buf_sysfs_release(struct kobject *kobj) 108 - { 109 - struct dma_buf_sysfs_entry *sysfs_entry; 110 - 111 - sysfs_entry = to_dma_buf_entry_from_kobj(kobj); 112 - kfree(sysfs_entry); 113 - } 114 - 115 - static const struct kobj_type dma_buf_ktype = { 116 - .sysfs_ops = &dma_buf_stats_sysfs_ops, 117 - .release = dma_buf_sysfs_release, 118 - .default_groups = dma_buf_stats_default_groups, 119 - }; 120 - 121 - void dma_buf_stats_teardown(struct dma_buf *dmabuf) 122 - { 123 - struct dma_buf_sysfs_entry *sysfs_entry; 124 - 125 - sysfs_entry = dmabuf->sysfs_entry; 126 - if (!sysfs_entry) 127 - return; 128 - 129 - kobject_del(&sysfs_entry->kobj); 130 - kobject_put(&sysfs_entry->kobj); 131 - } 132 - 133 - 134 - /* Statistics files do not need to send uevents. */ 135 - static int dmabuf_sysfs_uevent_filter(const struct kobject *kobj) 136 - { 137 - return 0; 138 - } 139 - 140 - static const struct kset_uevent_ops dmabuf_sysfs_no_uevent_ops = { 141 - .filter = dmabuf_sysfs_uevent_filter, 142 - }; 143 - 144 - static struct kset *dma_buf_stats_kset; 145 - static struct kset *dma_buf_per_buffer_stats_kset; 146 - int dma_buf_init_sysfs_statistics(void) 147 - { 148 - dma_buf_stats_kset = kset_create_and_add("dmabuf", 149 - &dmabuf_sysfs_no_uevent_ops, 150 - kernel_kobj); 151 - if (!dma_buf_stats_kset) 152 - return -ENOMEM; 153 - 154 - dma_buf_per_buffer_stats_kset = kset_create_and_add("buffers", 155 - &dmabuf_sysfs_no_uevent_ops, 156 - &dma_buf_stats_kset->kobj); 157 - if (!dma_buf_per_buffer_stats_kset) { 158 - kset_unregister(dma_buf_stats_kset); 159 - return -ENOMEM; 160 - } 161 - 162 - return 0; 163 - } 164 - 165 - void dma_buf_uninit_sysfs_statistics(void) 166 - { 167 - kset_unregister(dma_buf_per_buffer_stats_kset); 168 - kset_unregister(dma_buf_stats_kset); 169 - } 170 - 171 - int dma_buf_stats_setup(struct dma_buf *dmabuf, struct file *file) 172 - { 173 - struct dma_buf_sysfs_entry *sysfs_entry; 174 - int ret; 175 - 176 - if (!dmabuf->exp_name) { 177 - pr_err("exporter name must not be empty if stats needed\n"); 178 - return -EINVAL; 179 - } 180 - 181 - sysfs_entry = kzalloc(sizeof(struct dma_buf_sysfs_entry), GFP_KERNEL); 182 - if (!sysfs_entry) 183 - return -ENOMEM; 184 - 185 - sysfs_entry->kobj.kset = dma_buf_per_buffer_stats_kset; 186 - sysfs_entry->dmabuf = dmabuf; 187 - 188 - dmabuf->sysfs_entry = sysfs_entry; 189 - 190 - /* create the directory for buffer stats */ 191 - ret = kobject_init_and_add(&sysfs_entry->kobj, &dma_buf_ktype, NULL, 192 - "%lu", file_inode(file)->i_ino); 193 - if (ret) 194 - goto err_sysfs_dmabuf; 195 - 196 - return 0; 197 - 198 - err_sysfs_dmabuf: 199 - kobject_put(&sysfs_entry->kobj); 200 - dmabuf->sysfs_entry = NULL; 201 - return ret; 202 - }
-35
drivers/dma-buf/dma-buf-sysfs-stats.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0-only */ 2 - /* 3 - * DMA-BUF sysfs statistics. 4 - * 5 - * Copyright (C) 2021 Google LLC. 6 - */ 7 - 8 - #ifndef _DMA_BUF_SYSFS_STATS_H 9 - #define _DMA_BUF_SYSFS_STATS_H 10 - 11 - #ifdef CONFIG_DMABUF_SYSFS_STATS 12 - 13 - int dma_buf_init_sysfs_statistics(void); 14 - void dma_buf_uninit_sysfs_statistics(void); 15 - 16 - int dma_buf_stats_setup(struct dma_buf *dmabuf, struct file *file); 17 - 18 - void dma_buf_stats_teardown(struct dma_buf *dmabuf); 19 - #else 20 - 21 - static inline int dma_buf_init_sysfs_statistics(void) 22 - { 23 - return 0; 24 - } 25 - 26 - static inline void dma_buf_uninit_sysfs_statistics(void) {} 27 - 28 - static inline int dma_buf_stats_setup(struct dma_buf *dmabuf, struct file *file) 29 - { 30 - return 0; 31 - } 32 - 33 - static inline void dma_buf_stats_teardown(struct dma_buf *dmabuf) {} 34 - #endif 35 - #endif // _DMA_BUF_SYSFS_STATS_H
-18
drivers/dma-buf/dma-buf.c
··· 33 33 #include <uapi/linux/dma-buf.h> 34 34 #include <uapi/linux/magic.h> 35 35 36 - #include "dma-buf-sysfs-stats.h" 37 - 38 36 #define CREATE_TRACE_POINTS 39 37 #include <trace/events/dma_buf.h> 40 38 ··· 182 184 */ 183 185 BUG_ON(dmabuf->cb_in.active || dmabuf->cb_out.active); 184 186 185 - dma_buf_stats_teardown(dmabuf); 186 187 dmabuf->ops->release(dmabuf); 187 188 188 189 if (dmabuf->resv == (struct dma_resv *)&dmabuf[1]) ··· 762 765 dmabuf->resv = resv; 763 766 } 764 767 765 - ret = dma_buf_stats_setup(dmabuf, file); 766 - if (ret) 767 - goto err_dmabuf; 768 - 769 768 file->private_data = dmabuf; 770 769 file->f_path.dentry->d_fsdata = dmabuf; 771 770 dmabuf->file = file; ··· 772 779 773 780 return dmabuf; 774 781 775 - err_dmabuf: 776 - if (!resv) 777 - dma_resv_fini(dmabuf->resv); 778 - kfree(dmabuf); 779 782 err_file: 780 783 fput(file); 781 784 err_module: ··· 1791 1802 1792 1803 static int __init dma_buf_init(void) 1793 1804 { 1794 - int ret; 1795 - 1796 - ret = dma_buf_init_sysfs_statistics(); 1797 - if (ret) 1798 - return ret; 1799 - 1800 1805 dma_buf_mnt = kern_mount(&dma_buf_fs_type); 1801 1806 if (IS_ERR(dma_buf_mnt)) 1802 1807 return PTR_ERR(dma_buf_mnt); ··· 1804 1821 { 1805 1822 dma_buf_uninit_debugfs(); 1806 1823 kern_unmount(dma_buf_mnt); 1807 - dma_buf_uninit_sysfs_statistics(); 1808 1824 } 1809 1825 __exitcall(dma_buf_deinit);
-12
include/linux/dma-buf.h
··· 429 429 430 430 __poll_t active; 431 431 } cb_in, cb_out; 432 - #ifdef CONFIG_DMABUF_SYSFS_STATS 433 - /** 434 - * @sysfs_entry: 435 - * 436 - * For exposing information about this buffer in sysfs. See also 437 - * `DMA-BUF statistics`_ for the uapi this enables. 438 - */ 439 - struct dma_buf_sysfs_entry { 440 - struct kobject kobj; 441 - struct dma_buf *dmabuf; 442 - } *sysfs_entry; 443 - #endif 444 432 }; 445 433 446 434 /**