[PATCH RFC v2 0/8] memcg: dma-buf cgroup accounting and charge transfer
From: Albert Esteve
Date: Wed Oct 21 2026 - 11:43:19 EST
This series adds memory cgroup accounting for dma-buf allocations,
building on T.J. Mercier's earlier series [1] and incorporating
feedback from the v1 and LPC discussions.
Patch 1 introduces the MEMCG_DMABUF stat and charge/uncharge helpers.
Rather than charging at the page level via __GFP_ACCOUNT (which would
require every dma-buf exporter to implement charging, and makes
cross-cgroup transfer impractical without access to backing pages),
we track charges externally on struct dma_buf via a MEMCG_DMABUF stat
counter and route all accounting through a single path, removing the
__GFP_ACCOUNT flag from system-heap allocations to avoid double
counting.
Patch 2 adds a charge_fd field to DMA_HEAP_IOCTL_ALLOC, accepting
either a pidfd or a cgroupfd to identify the target cgroup at
allocation time. If the target cgroup cannot accommodate the charge,
the allocation returns -ENOMEM.
Patches 3-4 add LSM hooks for the two charge_fd flavours:
security_dma_buf_charge_task() gates the pidfd path (target
identified by task credentials) and security_dma_buf_charge_cgroup()
gates the cgroupfd path (target identified by cgroup directory label).
Patches 5-6 implement the SELinux side under a dma_buf object class
with charge_task and charge_cgroup permissions. For charge_cgroup,
the target SID is derived from the cgroup directory's SELinux label.
Patch 7 adds DMA_BUF_IOCTL_XFER_CHARGE, a general ioctl on any
dma-buf fd to transfer charges (or charge) post-allocation. This
covers the double-hop allocator case (SurfaceFlinger -> gralloc) and
works for buffers from any exporter (DRM, V4L2, etc.). If the
receiving cgroup lacks capacity for the charge, the ioctl returns
-ENOMEM and the original charge is preserved.
Patch 8 adds selftests.
Known limitations:
- Single-owner model: a dma-buf carries one memcg charge regardless
of how many processes share it.
- Only memcg accounting. CMA heaps would additionally need dmem
controller integration.
- Charging CMA-backed heaps to memcg charges unreclaimable memory:
when a cgroup hits its limit, try_charge_memcg() may trigger a
reclaim pass that cannot free CMA pages. A future version could
move charging into per-heap callbacks.
- If a transfer of an uncharged buffer fails, the buffer remains
uncharged. The allocator (userspace) is expected to handle this
(e.g., retry, free, ...).
- The LSM hook is intentionally narrow. Broader cgroup access controls
could be a separate effort.
[1] https://lore.kernel.org/cgroups/20230109213809.418135-1-tjmercier@xxxxxxxxxx/
Signed-off-by: Albert Esteve <aesteve@xxxxxxxxxx>
---
Changes in v2:
- Move charge_pid_fd to charge_fd, accepting cgroupfd in addition
to pidfd per Christian König.
- New DMA_BUF_IOCTL_XFER_CHARGE ioctl for post-allocation charge
transfer on any dma-buf, not just dma-heap buffers per Christian König
and T.J. Mercier.
- Moved __GFP_ACCOUNT removal to patch 1 per Barry Song.
- dma-buf charge/uncharge helpers take struct dma_buf * directly
to avoid the need for caller to manage size calculations.
- Added test_xfer_charge_cgroupfd_self to dmabuf-heap selftests.
- Added LSM and SELinux hooks for cgroupfd-based charging.
- Rebased to v7.3-rc7.
- Link to v1: https://lore.kernel.org/r/20260512-v2_20230123_tjmercier_google_com-v1-0-6326701c3691@xxxxxxxxxx
---
Albert Esteve (7):
dma-heap: charge dma-buf memory via explicit memcg
security: dma-buf: Add dma_buf_charge_task LSM hook
security: dma-buf: Add dma_buf_charge_cgroup LSM hook
selinux: Restrict cross-cgroup dma-buf charging
selinux: Restrict dma-buf direct cgroup charging
dma-buf: transfer memcg charges via DMA_BUF_IOCTL_XFER_CHARGE
selftests/dmabuf-heaps: Add dma-buf memcg accounting tests
T.J. Mercier (1):
memcg: Add MEMCG_DMABUF accounting infrastructure
Documentation/admin-guide/cgroup-v2.rst | 5 +
drivers/dma-buf/dma-buf.c | 80 ++++++++
drivers/dma-buf/dma-heap.c | 72 ++++++-
drivers/dma-buf/heaps/system_heap.c | 2 -
include/linux/dma-buf.h | 4 +
include/linux/lsm_hook_defs.h | 2 +
include/linux/memcontrol.h | 29 +++
include/linux/security.h | 14 ++
include/uapi/linux/dma-buf.h | 26 +++
include/uapi/linux/dma-heap.h | 7 +
mm/memcontrol.c | 94 +++++++++
security/security.c | 32 +++
security/selinux/hooks.c | 40 ++++
security/selinux/include/classmap.h | 1 +
tools/testing/selftests/cgroup/Makefile | 2 +-
tools/testing/selftests/cgroup/test_memcontrol.c | 145 +++++++++++++-
tools/testing/selftests/dmabuf-heaps/config | 1 +
tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c | 222 ++++++++++++++++++++-
tools/testing/selftests/dmabuf-heaps/vmtest.sh | 205 +++++++++++++++++++
19 files changed, 974 insertions(+), 9 deletions(-)
---
base-commit: 24a19b953e2a3d0ea5a8c4951a0ab8f32720c907
change-id: 20260508-v2_20230123_tjmercier_google_com-f44fcfb16530
Best regards,
--
Albert Esteve <aesteve@xxxxxxxxxx>