[PATCH RFC 12/12] media: videobuf2: Track buffer allocations through the dmem cgroup

Maxime Ripard
2025-03-10T12:06:51Z

The dmem cgroup allows to track any DMA memory allocation made by the
userspace. Let's charge our allocations in videobuf2 to enable proper
memory tracking.

Signed-off-by: Maxime Ripard <mripard@kernel.org>
---
drivers/media/common/videobuf2/videobuf2-dma-contig.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
index a13ec569c82f6da2d977222b94af32e74c6c6c82..48384e18030812f4f89f1c225c38def2ac6aa3ca 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
@@ -8,10 +8,11 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*/

+#include <linux/cgroup_dmem.h>
#include <linux/dma-buf.h>
#include <linux/module.h>
#include <linux/refcount.h>
#include <linux/scatterlist.h>
#include <linux/sched.h>
@@ -40,10 +41,14 @@ struct vb2_dc_buf {
struct sg_table *sgt_base;

/* DMABUF related */
struct dma_buf_attachment *db_attach;

+#ifdef CONFIG_CGROUP_DMEM
+ struct dmem_cgroup_pool_state *cgroup_pool_state;
+#endif
+
struct vb2_buffer *vb;
bool non_coherent_mem;
};

/*********************************************/
@@ -169,10 +174,14 @@ static void vb2_dc_put(void *buf_priv)
struct vb2_dc_buf *buf = buf_priv;

if (!refcount_dec_and_test(&buf->refcount))
return;

+#ifdef CONFIG_CGROUP_DMEM
+ dmem_cgroup_uncharge(buf->cgroup_pool_state, buf->size);
+#endif
+
if (buf->non_coherent_mem) {
if (buf->vaddr)
dma_vunmap_noncontiguous(buf->dev, buf->vaddr);
dma_free_noncontiguous(buf->dev, buf->size,
buf->dma_sgt, buf->dma_dir);
@@ -230,10 +239,11 @@ static int vb2_dc_alloc_non_coherent(struct vb2_dc_buf *buf)

static void *vb2_dc_alloc(struct vb2_buffer *vb,
struct device *dev,
unsigned long size)
{
+ struct dmem_cgroup_pool_state *pool;
struct vb2_dc_buf *buf;
int ret;

if (WARN_ON(!dev))
return ERR_PTR(-EINVAL);
@@ -249,25 +259,34 @@ static void *vb2_dc_alloc(struct vb2_buffer *vb,

buf->size = size;
/* Prevent the device from being released while the buffer is used */
buf->dev = get_device(dev);

+ ret = dmem_cgroup_try_charge(dma_get_dmem_cgroup_region(dev), size, &pool, NULL);
+ if (ret)
+ return ret;
+
if (buf->non_coherent_mem)
ret = vb2_dc_alloc_non_coherent(buf);
else
ret = vb2_dc_alloc_coherent(buf);

if (ret) {
dev_err(dev, "dma alloc of size %lu failed\n", size);
+ dmem_cgroup_uncharge(pool, size);
kfree(buf);
return ERR_PTR(-ENOMEM);
}

buf->handler.refcount = &buf->refcount;
buf->handler.put = vb2_dc_put;
buf->handler.arg = buf;

+#ifdef CONFIG_CGROUP_DMEM
+ buf->cgroup_pool_state = pool;
+#endif
+
refcount_set(&buf->refcount, 1);

return buf;
}

--
2.48.1