// SPDX-License-Identifier: GPL-2.0-only /* * DMA-BUF sysfs statistics. * * Copyright (C) 2021 Google LLC. */ #include <linux/dma-buf.h> #include <linux/dma-resv.h> #include <linux/kobject.h> #include <linux/printk.h> #include <linux/slab.h> #include <linux/sysfs.h> #include "dma-buf-sysfs-stats.h" #define to_dma_buf_entry_from_kobj(x) … /** * DOC: overview * * ``/sys/kernel/debug/dma_buf/bufinfo`` provides an overview of every DMA-BUF * in the system. However, since debugfs is not safe to be mounted in * production, procfs and sysfs can be used to gather DMA-BUF statistics on * production systems. * * The ``/proc/<pid>/fdinfo/<fd>`` files in procfs can be used to gather * information about DMA-BUF fds. Detailed documentation about the interface * is present in Documentation/filesystems/proc.rst. * * Unfortunately, the existing procfs interfaces can only provide information * about the DMA-BUFs for which processes hold fds or have the buffers mmapped * into their address space. This necessitated the creation of the DMA-BUF sysfs * statistics interface to provide per-buffer information on production systems. * * The interface at ``/sys/kernel/dmabuf/buffers`` exposes information about * every DMA-BUF when ``CONFIG_DMABUF_SYSFS_STATS`` is enabled. * * The following stats are exposed by the interface: * * * ``/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name`` * * ``/sys/kernel/dmabuf/buffers/<inode_number>/size`` * * The information in the interface can also be used to derive per-exporter * statistics. The data from the interface can be gathered on error conditions * or other important events to provide a snapshot of DMA-BUF usage. * It can also be collected periodically by telemetry to monitor various metrics. * * Detailed documentation about the interface is present in * Documentation/ABI/testing/sysfs-kernel-dmabuf-buffers. */ struct dma_buf_stats_attribute { … }; #define to_dma_buf_stats_attr(x) … static ssize_t dma_buf_stats_attribute_show(struct kobject *kobj, struct attribute *attr, char *buf) { … } static const struct sysfs_ops dma_buf_stats_sysfs_ops = …; static ssize_t exporter_name_show(struct dma_buf *dmabuf, struct dma_buf_stats_attribute *attr, char *buf) { … } static ssize_t size_show(struct dma_buf *dmabuf, struct dma_buf_stats_attribute *attr, char *buf) { … } static struct dma_buf_stats_attribute exporter_name_attribute = …; static struct dma_buf_stats_attribute size_attribute = …; static struct attribute *dma_buf_stats_default_attrs[] = …; ATTRIBUTE_GROUPS(…); static void dma_buf_sysfs_release(struct kobject *kobj) { … } static const struct kobj_type dma_buf_ktype = …; void dma_buf_stats_teardown(struct dma_buf *dmabuf) { … } /* Statistics files do not need to send uevents. */ static int dmabuf_sysfs_uevent_filter(const struct kobject *kobj) { … } static const struct kset_uevent_ops dmabuf_sysfs_no_uevent_ops = …; static struct kset *dma_buf_stats_kset; static struct kset *dma_buf_per_buffer_stats_kset; int dma_buf_init_sysfs_statistics(void) { … } void dma_buf_uninit_sysfs_statistics(void) { … } int dma_buf_stats_setup(struct dma_buf *dmabuf, struct file *file) { … }