[PATCH v2 2/2] dma-buf: system_heap: account for system heap allocation in memcg

Eric Chanudet posted 2 patches 3 weeks, 5 days ago
There is a newer version of this series
[PATCH v2 2/2] dma-buf: system_heap: account for system heap allocation in memcg
Posted by Eric Chanudet 3 weeks, 5 days ago
The system dma-buf heap lets userspace allocate buffers from the page
allocator. However, these allocations are not accounted for in memcg,
allowing processes to escape limits that may be configured.

Pass __GFP_ACCOUNT for system heap allocations, based on the
dma_heap.mem_accounting parameter, to use memcg and account for them.

Signed-off-by: Eric Chanudet <echanude@redhat.com>
---
 drivers/dma-buf/heaps/system_heap.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c
index 4c782fe33fd497a74eb5065797259576f9b651b6..139b50df64ed4c4a6fdd69f25fe48324fbe2c481 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -52,6 +52,8 @@ static gfp_t order_flags[] = {HIGH_ORDER_GFP, HIGH_ORDER_GFP, LOW_ORDER_GFP};
 static const unsigned int orders[] = {8, 4, 0};
 #define NUM_ORDERS ARRAY_SIZE(orders)
 
+extern bool mem_accounting;
+
 static int dup_sg_table(struct sg_table *from, struct sg_table *to)
 {
 	struct scatterlist *sg, *new_sg;
@@ -320,14 +322,17 @@ static struct page *alloc_largest_available(unsigned long size,
 {
 	struct page *page;
 	int i;
+	gfp_t flags;
 
 	for (i = 0; i < NUM_ORDERS; i++) {
 		if (size <  (PAGE_SIZE << orders[i]))
 			continue;
 		if (max_order < orders[i])
 			continue;
-
-		page = alloc_pages(order_flags[i], orders[i]);
+		flags = order_flags[i];
+		if (mem_accounting)
+			flags |= __GFP_ACCOUNT;
+		page = alloc_pages(flags, orders[i]);
 		if (!page)
 			continue;
 		return page;

-- 
2.52.0
Re: [PATCH v2 2/2] dma-buf: system_heap: account for system heap allocation in memcg
Posted by Christian König 3 weeks, 5 days ago
On 1/13/26 22:32, Eric Chanudet wrote:
> The system dma-buf heap lets userspace allocate buffers from the page
> allocator. However, these allocations are not accounted for in memcg,
> allowing processes to escape limits that may be configured.
> 
> Pass __GFP_ACCOUNT for system heap allocations, based on the
> dma_heap.mem_accounting parameter, to use memcg and account for them.
> 
> Signed-off-by: Eric Chanudet <echanude@redhat.com>
> ---
>  drivers/dma-buf/heaps/system_heap.c | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c
> index 4c782fe33fd497a74eb5065797259576f9b651b6..139b50df64ed4c4a6fdd69f25fe48324fbe2c481 100644
> --- a/drivers/dma-buf/heaps/system_heap.c
> +++ b/drivers/dma-buf/heaps/system_heap.c
> @@ -52,6 +52,8 @@ static gfp_t order_flags[] = {HIGH_ORDER_GFP, HIGH_ORDER_GFP, LOW_ORDER_GFP};
>  static const unsigned int orders[] = {8, 4, 0};
>  #define NUM_ORDERS ARRAY_SIZE(orders)
>  
> +extern bool mem_accounting;

Please define that in some header. Apart from that looks good technically.

But after the discussion it sounds more and more like we don't want to account device driver allocated memory in memcg at all.

Regards,
Christian.


> +
>  static int dup_sg_table(struct sg_table *from, struct sg_table *to)
>  {
>  	struct scatterlist *sg, *new_sg;
> @@ -320,14 +322,17 @@ static struct page *alloc_largest_available(unsigned long size,
>  {
>  	struct page *page;
>  	int i;
> +	gfp_t flags;
>  
>  	for (i = 0; i < NUM_ORDERS; i++) {
>  		if (size <  (PAGE_SIZE << orders[i]))
>  			continue;
>  		if (max_order < orders[i])
>  			continue;
> -
> -		page = alloc_pages(order_flags[i], orders[i]);
> +		flags = order_flags[i];
> +		if (mem_accounting)
> +			flags |= __GFP_ACCOUNT;
> +		page = alloc_pages(flags, orders[i]);
>  		if (!page)
>  			continue;
>  		return page;
>
Re: [PATCH v2 2/2] dma-buf: system_heap: account for system heap allocation in memcg
Posted by Eric Chanudet 3 weeks, 4 days ago
On Wed, Jan 14, 2026 at 11:38:27AM +0100, Christian König wrote:
> On 1/13/26 22:32, Eric Chanudet wrote:
> > The system dma-buf heap lets userspace allocate buffers from the page
> > allocator. However, these allocations are not accounted for in memcg,
> > allowing processes to escape limits that may be configured.
> > 
> > Pass __GFP_ACCOUNT for system heap allocations, based on the
> > dma_heap.mem_accounting parameter, to use memcg and account for them.
> > 
> > Signed-off-by: Eric Chanudet <echanude@redhat.com>
> > ---
> >  drivers/dma-buf/heaps/system_heap.c | 9 +++++++--
> >  1 file changed, 7 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c
> > index 4c782fe33fd497a74eb5065797259576f9b651b6..139b50df64ed4c4a6fdd69f25fe48324fbe2c481 100644
> > --- a/drivers/dma-buf/heaps/system_heap.c
> > +++ b/drivers/dma-buf/heaps/system_heap.c
> > @@ -52,6 +52,8 @@ static gfp_t order_flags[] = {HIGH_ORDER_GFP, HIGH_ORDER_GFP, LOW_ORDER_GFP};
> >  static const unsigned int orders[] = {8, 4, 0};
> >  #define NUM_ORDERS ARRAY_SIZE(orders)
> >  
> > +extern bool mem_accounting;
> 
> Please define that in some header. Apart from that looks good technically.

Thank you for the review, I can move it to linux/dma-heap.h in a v3
since it's intended for other heaps as well.

> But after the discussion it sounds more and more like we don't want to account device driver allocated memory in memcg at all.

From the threads in v1 I thought adding the switch left open a
consideration to use memcg with driver allocated memory for userspace,
even with the known caveats that implies. Re-reading your last reply[1],
that's not quite the case it sounds like.

Best,

[1] https://lore.kernel.org/all/e38d87d3-a114-43f9-be93-03e9b9f40844@amd.com/

> 
> Regards,
> Christian.
> 
> 
> > +
> >  static int dup_sg_table(struct sg_table *from, struct sg_table *to)
> >  {
> >  	struct scatterlist *sg, *new_sg;
> > @@ -320,14 +322,17 @@ static struct page *alloc_largest_available(unsigned long size,
> >  {
> >  	struct page *page;
> >  	int i;
> > +	gfp_t flags;
> >  
> >  	for (i = 0; i < NUM_ORDERS; i++) {
> >  		if (size <  (PAGE_SIZE << orders[i]))
> >  			continue;
> >  		if (max_order < orders[i])
> >  			continue;
> > -
> > -		page = alloc_pages(order_flags[i], orders[i]);
> > +		flags = order_flags[i];
> > +		if (mem_accounting)
> > +			flags |= __GFP_ACCOUNT;
> > +		page = alloc_pages(flags, orders[i]);
> >  		if (!page)
> >  			continue;
> >  		return page;
> > 
> 

-- 
Eric Chanudet