Subject: Re: [RFC PATCH bpf-next v7 00/11] mm: BPF struct_ops for dynamic memory protection and async reclaim

From: "teawater" <[email-masked]>
Date: Wed, 27 May 2026 09:31:25 +0000

> 
> On Tue, 26 May 2026 10:20:00 +0800 Hui Zhu <[email-masked]> wrote:
> 
> > 
> > From: Hui Zhu <[email-masked]>
> >  
> >  Overview:
> >  This series introduces BPF struct_ops support for the memory controller,
> >  enabling userspace BPF programs to implement custom, dynamic memory
> >  management policies per cgroup. The feature allows BPF programs to hook
> >  into the core reclaim and charge paths without requiring kernel
> >  modifications, providing a flexible alternative to static knobs such as
> >  memory.low and memory.min.
> >  
> >  The series enables two complementary use cases.
> >  
...
...
...
> >  
> >  Asynchronous proactive reclaim: the memcg_charged and memcg_uncharged
> >  hooks, combined with the BPF workqueue mechanism and the new
> >  bpf_try_to_free_mem_cgroup_pages() kfunc, enable BPF programs to perform
> >  proactive background reclaim without blocking the charge path. The
> >  pattern works as follows: the memcg_charged callback tracks accumulated
> >  memory usage; when usage crosses a configurable threshold, it enqueues an
> >  asynchronous work item via bpf_wq_start() and returns immediately without
> >  throttling the charging task. The workqueue callback then invokes
> >  bpf_try_to_free_mem_cgroup_pages() to reclaim pages from the target
> >  cgroup; if usage remains elevated after reclaim, the callback re-enqueues
> >  itself to continue. This allows a BPF program to keep a cgroup's
> >  footprint below its hard limit (memory.max) entirely in the background,
> >  avoiding the OOM killer or direct-reclaim stalls that would otherwise
> >  occur. The selftest for this feature (patch 10/11) validates the
> >  mechanism concretely: a workload that writes and mmaps a 64 MB file inside
> >  a 32 MB cgroup reliably triggers memory.events "max" events without BPF;
> >  with the async reclaim program attached, the "max" counter does not
> >  increase at all across the same workload.
> > 
> Hi Hui,
> 
> Thanks for the series.
> Would it not be simpler to just have another memcg knob, something like
> memory.high_async.
> When memory usage > memory.high_async, queue a per-memcg work item that calls
> try_to_free_mem_cgroup_pages() until usage drops back below some threshold.
> I am not sure I see what programability aspect from bpf you need here.
> 
> Thanks

Hi Usama,

That's a good question.

By introducing a new BPF kfunc bpf_try_to_free_mem_cgroup_pages,
a BPF program can flexibly control when to start and stop async
reclaim, rather than being constrained to trigger and stop based
solely on memcg usage or one or two fixed events, as with
traditional proactive reclaim interfaces.

For example, async reclaim could be triggered based on PSI, or
on the number of page faults, or even on a combination of
multiple events working together to decide both when to start
and when to stop async reclaim.

That is the motivation behind adding the BPF kfunc
bpf_try_to_free_mem_cgroup_pages in this patch set.

I admit the cover letter did not explain this well enough, and
the example code does not demonstrate this use case either. I
will address both in the next version.

Best,
Hui

> 
> > 
> > 08/11 selftests/bpf: Add tests for memcg_bpf_ops
> >  Adds prog_tests/memcg_ops.c covering three scenarios:
> >  memcg_charged-only throttling, below_low + memcg_charged
> >  interaction, and below_min + memcg_charged interaction. A
> >  tracepoint on memcg:count_memcg_events (PGFAULT) is used to
> >  detect memory pressure and trigger hooks accordingly.
...
...
...
> >  -- 
> >  2.43.0