> diff --git a/mm/bpf_memcontrol.c b/mm/bpf_memcontrol.c
> index 716df49d7647..92272f9a5825 100644
> --- a/mm/bpf_memcontrol.c
> +++ b/mm/bpf_memcontrol.c

[ ... ]

> @@ -159,6 +160,97 @@ __bpf_kfunc void bpf_mem_cgroup_flush_stats(struct 
> mem_cgroup *memcg)
>       mem_cgroup_flush_stats(memcg);
>  }
>
> +/**
> + * bpf_proactive_reclaim - proactively reclaim memory from a memory
> + *                         cgroup
> + * @memcg: the target memory cgroup to reclaim from
> + * @size:  the amount of memory to reclaim, in bytes
> + *
> + * Trigger one proactive reclaim pass on @memcg, similar to a write to
> + * the memory.reclaim cgroup file: pages are reclaimed according to the
> + * cgroup's own swappiness setting and swap is allowed. Note that,
> + * unlike memory.reclaim, this does not retry until @size is reached;
> + * callers can invoke it again if needed.
> + *
> + * Return:
> + *   The number of pages actually reclaimed, or 0 if @size is smaller
> + *   than a page or the calling task is already in a reclaim/freeing
> + *   context (PF_MEMALLOC).
> + */
> +__bpf_kfunc unsigned long bpf_proactive_reclaim(struct mem_cgroup *memcg,
> +                                             unsigned long size)
> +{
> +     unsigned long nr_pages = size / PAGE_SIZE;
> +
> +     if (!nr_pages || unlikely(bpf_in_reclaim_context()))
> +             return 0;
> +
> +     return try_to_free_mem_cgroup_pages(memcg, nr_pages, GFP_KERNEL,
> +                                         MEMCG_RECLAIM_MAY_SWAP |
> +                                         MEMCG_RECLAIM_PROACTIVE, NULL);
> +}
> +
> +/**
> + * bpf_proactive_reclaim_swappiness - proactively reclaim memory from a
> + *                                    memory cgroup with an explicit
> + *                                    swappiness
> + * @memcg:      the target memory cgroup to reclaim from
> + * @size:       the amount of memory to reclaim, in bytes
> + * @swappiness: swappiness override for this reclaim pass
> + *
> + * Same as bpf_proactive_reclaim(), except that the anon/file reclaim
> + * balance is controlled by @swappiness instead of the cgroup's
> + * swappiness setting. Valid values are [MIN_SWAPPINESS, MAX_SWAPPINESS]
> + * and SWAPPINESS_ANON_ONLY, which restricts reclaim to anon folios.
> + *
> + * Return:
> + *   The number of pages actually reclaimed, or 0 if @size is smaller
> + *   than a page, @swappiness is out of range, or the calling task is
> + *   already in a reclaim/freeing context (PF_MEMALLOC).
> + */
> +__bpf_kfunc unsigned long
> +bpf_proactive_reclaim_swappiness(struct mem_cgroup *memcg, unsigned long 
> size,
> +                              int swappiness)
> +{
> +     unsigned long nr_pages = size / PAGE_SIZE;
> +
> +     if (!nr_pages || swappiness < MIN_SWAPPINESS ||
> +         swappiness > SWAPPINESS_ANON_ONLY ||
> +         unlikely(bpf_in_reclaim_context()))
> +             return 0;
> +
> +     return try_to_free_mem_cgroup_pages(memcg, nr_pages, GFP_KERNEL,
> +                                         MEMCG_RECLAIM_MAY_SWAP |
> +                                         MEMCG_RECLAIM_PROACTIVE,
> +                                         &swappiness);
> +}

This isn't a bug, but these two kfuncs are nearly identical apart from the
swappiness range check and passing '&swappiness' vs 'NULL' to
try_to_free_mem_cgroup_pages(). Both compute 'nr_pages = size /
PAGE_SIZE', both apply the same '!nr_pages ||
unlikely(bpf_in_reclaim_context())' guard, and both use identical
'GFP_KERNEL, MEMCG_RECLAIM_MAY_SWAP | MEMCG_RECLAIM_PROACTIVE' arguments.

Would a shared static helper taking an 'int *swappiness' parameter (the
shape try_to_free_mem_cgroup_pages() already accepts) keep the guard logic
and reclaim flags in one place?


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/32118218829

Reply via email to