mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-05 08:44:14 +02:00
Clean up mm/vmpressure.c by separating the cgroup v1 userspace eventfd interface from the shared and v2 in-kernel code. Currently, almost half of mm/vmpressure.c exists to serve tree=true: struct vmpressure_event, the events list and its mutex, the work_struct and vmpressure_work_fn that drains tree_scanned/tree_reclaimed, the parent walk, vmpressure_event(), vmpressure_register_event(), vmpressure_unregister_event(), and vmpressure_prio() (which always calls vmpressure() with tree=true). Move it all into mm/memcontrol-v1.c (built only when CONFIG_MEMCG_V1=y) as a single contiguous block, following the per-component layout already used by that file. Keeping the v1 vmpressure code with the rest of the deprecated cgroup v1 memory controller makes the full footprint of the CONFIG_MEMCG_V1 option easy to see in one place, which matters more than component-level file separation for code that has no active development. vmpressure.c keeps the shared bits (constants, vmpressure_calc_level, the runtime hierarchy check, the tree=false body, init/cleanup plumbing) and calls into three small v1 hooks for the tree=true accumulator and the v1 portions of init/cleanup. The hooks have static-inline no-op stubs in include/linux/vmpressure.h for the !MEMCG_V1 case, so callers don't need ifdefs. vmpressure_prio() gets the same treatment, which means vmscan.c's call site disappears at compile time on v2-only kernels. The only #ifdef CONFIG_MEMCG_V1 in source remains around the v1-only fields inside struct vmpressure itself. Memory savings on CONFIG_MEMCG_V1=n (measured with pahole): struct vmpressure : 112B -> 24B struct mem_cgroup : 1664B -> 1536B This split is the first step toward eventually making vmpressure CONFIG_MEMCG_V1 only. The v2 in-kernel socket pressure path (tree=false) cannot be removed today immediately: PSI is not an exact replacement for vmpressure, and switching networking socket-buffer back-off to PSI may regress networking performance or increase memory pressure in workloads that today rely on vmpressure's hysteresis. The medium-term plan is to introduce a PSI-based socket-pressure path, keep vmpressure available for v2 behind a defconfig as an opt-out for several releases, and only then drop the tree=false path entirely, at which point everything that remains of the vmpressure block in mm/memcontrol-v1.c is the whole subsystem. Link: https://lore.kernel.org/20260630112617.1198623-3-usama.arif@linux.dev Signed-off-by: Usama Arif <usama.arif@linux.dev> Acked-by: Shakeel Butt <shakeel.butt@linux.dev> Cc: David Hildenbrand <david@kernel.org> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Michal Koutný <mkoutny@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Roman Gushchin <roman.gushchin@linux.dev> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Tejun Heo <tj@kernel.org> Cc: Vlastimil Babka <vbabka@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
90 lines
3.0 KiB
C
90 lines
3.0 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __LINUX_VMPRESSURE_H
|
|
#define __LINUX_VMPRESSURE_H
|
|
|
|
#include <linux/mutex.h>
|
|
#include <linux/list.h>
|
|
#include <linux/workqueue.h>
|
|
#include <linux/gfp.h>
|
|
#include <linux/types.h>
|
|
#include <linux/cgroup.h>
|
|
#include <linux/eventfd.h>
|
|
|
|
struct vmpressure {
|
|
unsigned long scanned;
|
|
unsigned long reclaimed;
|
|
/* The lock is used to keep the scanned/reclaimed in sync. */
|
|
spinlock_t sr_lock;
|
|
|
|
#ifdef CONFIG_MEMCG_V1
|
|
/*
|
|
* tree=true accumulators feed the v1 userspace eventfd interface
|
|
* (memory.pressure_level). Drained by @work. v2 has no equivalent
|
|
* interface, so this state is omitted on CONFIG_MEMCG_V1=n builds.
|
|
*/
|
|
unsigned long tree_scanned;
|
|
unsigned long tree_reclaimed;
|
|
/* The list of vmpressure_event structs. */
|
|
struct list_head events;
|
|
/* Have to grab the lock on events traversal or modifications. */
|
|
struct mutex events_lock;
|
|
|
|
struct work_struct work;
|
|
#endif
|
|
};
|
|
|
|
enum vmpressure_levels {
|
|
VMPRESSURE_LOW = 0,
|
|
VMPRESSURE_MEDIUM,
|
|
VMPRESSURE_CRITICAL,
|
|
VMPRESSURE_NUM_LEVELS,
|
|
};
|
|
|
|
struct mem_cgroup;
|
|
|
|
#ifdef CONFIG_MEMCG
|
|
void vmpressure(gfp_t gfp, int order, struct mem_cgroup *memcg, bool tree,
|
|
unsigned long scanned, unsigned long reclaimed);
|
|
extern void vmpressure_init(struct vmpressure *vmpr);
|
|
extern void vmpressure_cleanup(struct vmpressure *vmpr);
|
|
extern struct vmpressure *memcg_to_vmpressure(struct mem_cgroup *memcg);
|
|
extern struct mem_cgroup *vmpressure_to_memcg(struct vmpressure *vmpr);
|
|
|
|
/* Shared with the v1 vmpressure block in mm/memcontrol-v1.c. */
|
|
extern const unsigned long vmpressure_win;
|
|
extern enum vmpressure_levels vmpressure_calc_level(unsigned long scanned,
|
|
unsigned long reclaimed);
|
|
|
|
#ifdef CONFIG_MEMCG_V1
|
|
extern void vmpressure_prio(gfp_t gfp, struct mem_cgroup *memcg, int prio);
|
|
extern int vmpressure_register_event(struct mem_cgroup *memcg,
|
|
struct eventfd_ctx *eventfd,
|
|
const char *args);
|
|
extern void vmpressure_unregister_event(struct mem_cgroup *memcg,
|
|
struct eventfd_ctx *eventfd);
|
|
|
|
/* v1 hooks called from mm/vmpressure.c; no-ops below when !MEMCG_V1. */
|
|
extern void vmpressure_v1_init(struct vmpressure *vmpr);
|
|
extern void vmpressure_v1_cleanup(struct vmpressure *vmpr);
|
|
extern void vmpressure_v1_account_tree(struct vmpressure *vmpr,
|
|
unsigned long scanned,
|
|
unsigned long reclaimed);
|
|
#else
|
|
static inline void vmpressure_prio(gfp_t gfp, struct mem_cgroup *memcg,
|
|
int prio) {}
|
|
static inline void vmpressure_v1_init(struct vmpressure *vmpr) {}
|
|
static inline void vmpressure_v1_cleanup(struct vmpressure *vmpr) {}
|
|
static inline void vmpressure_v1_account_tree(struct vmpressure *vmpr,
|
|
unsigned long scanned,
|
|
unsigned long reclaimed) {}
|
|
#endif /* CONFIG_MEMCG_V1 */
|
|
|
|
#else /* !CONFIG_MEMCG */
|
|
static inline void vmpressure(gfp_t gfp, int order, struct mem_cgroup *memcg,
|
|
bool tree, unsigned long scanned,
|
|
unsigned long reclaimed) {}
|
|
static inline void vmpressure_prio(gfp_t gfp, struct mem_cgroup *memcg,
|
|
int prio) {}
|
|
#endif /* CONFIG_MEMCG */
|
|
#endif /* __LINUX_VMPRESSURE_H */
|