[RFC PATCH bpf-next v7 07/11] mm/bpf: Add bpf_try_to_free_mem_cgroup_pages kfunc

From: Hui Zhu

Date: Mon May 25 2026 - 22:27:57 EST


From: Hui Zhu <zhuhui@xxxxxxxxxx>

Expose the memory cgroup reclaim interface to BPF programs by adding
the bpf_try_to_free_mem_cgroup_pages kfunc. This allows BPF to
trigger memory reclamation for a specific cgroup.

The kfunc wraps try_to_free_mem_cgroup_pages and introduces a
swappiness parameter with the following semantics:
Values in [MIN_SWAPPINESS, SWAPPINESS_ANON_ONLY] are passed through
as an explicit swappiness override.
Values below MIN_SWAPPINESS indicate the use of the system default
(passed as NULL to the core reclaim path).
Values above SWAPPINESS_ANON_ONLY are rejected as invalid (-EINVAL).

Note that the swappiness override is only respected by the core
reclaim path if the MEMCG_RECLAIM_PROACTIVE flag is set in
reclaim_options.

Swap usage during reclaim is gated on reclaim_options: swap is
considered only when MEMCG_RECLAIM_MAY_SWAP is set. Without this
flag, reclaim is restricted to file-backed pages regardless of the
swappiness value or the cgroup's swappiness setting.

Also include <linux/swap.h> for the swappiness macro definitions and
register the function with the KF_SLEEPABLE flag.

Signed-off-by: Barry Song <baohua@xxxxxxxxxx>
Signed-off-by: Geliang Tang <geliang@xxxxxxxxxx>
Signed-off-by: Hui Zhu <zhuhui@xxxxxxxxxx>
---
mm/bpf_memcontrol.c | 57 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)

diff --git a/mm/bpf_memcontrol.c b/mm/bpf_memcontrol.c
index 1f726a7b22e3..0353c8736aa5 100644
--- a/mm/bpf_memcontrol.c
+++ b/mm/bpf_memcontrol.c
@@ -6,6 +6,7 @@
*/

#include <linux/memcontrol.h>
+#include <linux/swap.h>
#include <linux/bpf.h>

/* Protects memcg->bpf_ops pointer for read and write. */
@@ -162,6 +163,60 @@ __bpf_kfunc void bpf_mem_cgroup_flush_stats(struct mem_cgroup *memcg)
mem_cgroup_flush_stats(memcg);
}

+/**
+ * bpf_try_to_free_mem_cgroup_pages - attempt to reclaim pages from
+ * a memory cgroup
+ * @memcg: the target memory cgroup to reclaim from
+ * @nr_pages: the number of pages to reclaim
+ * @gfp_mask: GFP flags controlling the reclaim behavior
+ * @reclaim_options: bitmask of MEMCG_RECLAIM_* flags to tune
+ * reclaim strategy
+ * @swappiness: swappiness override value, or a sentinel to use
+ * the default
+ *
+ * BPF-facing wrapper around try_to_free_mem_cgroup_pages() that
+ * validates and translates the @swappiness argument before
+ * delegating to the core reclaim path.
+ *
+ * The @swappiness parameter follows these semantics:
+ * - Values in [MIN_SWAPPINESS, SWAPPINESS_ANON_ONLY] are passed
+ * through as an explicit swappiness override.
+ * - Values below MIN_SWAPPINESS are treated as "use the system
+ * default"; the override pointer is set to NULL and the cgroup's
+ * own swappiness setting takes effect.
+ * - Values above SWAPPINESS_ANON_ONLY are rejected as invalid.
+ * - If @reclaim_options does not include MEMCG_RECLAIM_PROACTIVE,
+ * the @swappiness override is ignored entirely by the core
+ * reclaim path and the system default is used regardless.
+ *
+ * Swap usage during reclaim is gated on @reclaim_options: swap is
+ * considered only when MEMCG_RECLAIM_MAY_SWAP is set. Without this
+ * flag, reclaim is restricted to file-backed pages regardless of the
+ * @swappiness value or the cgroup's swappiness setting.
+ *
+ * Return:
+ * The number of pages actually reclaimed on success, or -%EINVAL
+ * if @swappiness exceeds SWAPPINESS_ANON_ONLY.
+ */
+unsigned long bpf_try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
+ unsigned long nr_pages,
+ gfp_t gfp_mask,
+ unsigned int reclaim_options,
+ int swappiness)
+{
+ int *swapiness_ptr;
+
+ if (swappiness > SWAPPINESS_ANON_ONLY)
+ return -EINVAL;
+ else if (swappiness < MIN_SWAPPINESS)
+ swapiness_ptr = NULL;
+ else
+ swapiness_ptr = &swappiness;
+
+ return try_to_free_mem_cgroup_pages(memcg, nr_pages, gfp_mask,
+ reclaim_options, swapiness_ptr);
+}
+
__bpf_kfunc_end_defs();

BTF_KFUNCS_START(bpf_memcontrol_kfuncs)
@@ -175,6 +230,8 @@ BTF_ID_FLAGS(func, bpf_mem_cgroup_usage)
BTF_ID_FLAGS(func, bpf_mem_cgroup_page_state)
BTF_ID_FLAGS(func, bpf_mem_cgroup_flush_stats, KF_SLEEPABLE)

+BTF_ID_FLAGS(func, bpf_try_to_free_mem_cgroup_pages, KF_SLEEPABLE)
+
BTF_KFUNCS_END(bpf_memcontrol_kfuncs)

static const struct btf_kfunc_id_set bpf_memcontrol_kfunc_set = {
--
2.43.0