From 0f656a3188669d5a4b1b36d89e6848e06d2b03b2 Mon Sep 17 00:00:00 2001 From: w00955705 Date: Wed, 10 Sep 2025 16:21:15 +0800 Subject: [PATCH] fix rss_threshold on linux6.6 release branch Signed-off-by: w00955705 Change-Id: I91388368423485ef976d94b5022eca5c90710d27 --- OAT.xml | 4 ++ fs/proc/base.c | 4 ++ fs/proc/internal.h | 6 ++ include/linux/mm.h | 12 ++++ include/linux/mm_types.h | 4 +- kernel/fork.c | 3 + mm/Kconfig | 9 +++ mm/Makefile | 1 + mm/rss_threshold.c | 117 +++++++++++++++++++++++++++++++++++++++ 9 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 mm/rss_threshold.c diff --git a/OAT.xml b/OAT.xml index 125e60d97df6..6385c7a4f59e 100644 --- a/OAT.xml +++ b/OAT.xml @@ -24,8 +24,10 @@ + + @@ -38,7 +40,9 @@ + + diff --git a/fs/proc/base.c b/fs/proc/base.c index f1e1a0b2cae8..6a35dd810ac3 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -3510,6 +3510,10 @@ static const struct pid_entry tgid_base_stuff[] = { #endif #ifdef CONFIG_TIME_NS REG("timens_offsets", S_IRUGO|S_IWUSR, proc_timens_offsets_operations), +#endif +#ifdef CONFIG_RSS_THRESHOLD + ONE("rss", S_IRUGO, proc_pid_rss), + REG("rss_threshold", S_IRUGO|S_IWUSR, proc_pid_rss_threshold_operations), #endif REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations), #ifdef CONFIG_HAVE_ARCH_TRACEHOOK diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 445c74a39a93..c39cac8f7efa 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -187,6 +187,12 @@ extern int pid_delete_dentry(const struct dentry *); extern int proc_pid_readdir(struct file *, struct dir_context *); struct dentry *proc_pid_lookup(struct dentry *, unsigned int); extern loff_t mem_lseek(struct file *, loff_t, int); +#ifdef CONFIG_RSS_THRESHOLD +extern int proc_pid_rss(struct seq_file *, struct pid_namespace *, + struct pid *, struct task_struct *); +extern void listen_rss_threshold(struct mm_struct *mm); +extern const struct file_operations proc_pid_rss_threshold_operations; +#endif /* Lookups */ typedef struct dentry *instantiate_t(struct dentry *, diff --git a/include/linux/mm.h b/include/linux/mm.h index 4176fa18f692..8fd0fc27fe09 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2584,10 +2584,18 @@ static inline unsigned long get_mm_counter_sum(struct mm_struct *mm, int member) void mm_trace_rss_stat(struct mm_struct *mm, int member); +#ifdef CONFIG_RSS_THRESHOLD +void listen_rss_threshold(struct mm_struct *mm); +#endif + static inline void add_mm_counter(struct mm_struct *mm, int member, long value) { percpu_counter_add(&mm->rss_stat[member], value); +#ifdef CONFIG_RSS_THRESHOLD + listen_rss_threshold(mm); +#endif + mm_trace_rss_stat(mm, member); } @@ -2595,6 +2603,10 @@ static inline void inc_mm_counter(struct mm_struct *mm, int member) { percpu_counter_inc(&mm->rss_stat[member]); +#ifdef CONFIG_RSS_THRESHOLD + listen_rss_threshold(mm); +#endif + mm_trace_rss_stat(mm, member); } diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 2b2616008a49..69bb0a199ae9 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -853,7 +853,9 @@ struct mm_struct { unsigned long hiwater_rss; /* High-watermark of RSS usage */ unsigned long hiwater_vm; /* High-water virtual memory usage */ - +#ifdef CONFIG_RSS_THRESHOLD + unsigned long rss_threshold; /* A threshold monitor RSS */ +#endif unsigned long total_vm; /* Total pages mapped */ unsigned long locked_vm; /* Pages that have PG_mlocked set */ atomic64_t pinned_vm; /* Refcount permanently increased */ diff --git a/kernel/fork.c b/kernel/fork.c index 0907f94005c8..a61c17928555 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1283,6 +1283,9 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p, { mt_init_flags(&mm->mm_mt, MM_MT_FLAGS); mt_set_external_lock(&mm->mm_mt, &mm->mmap_lock); +#ifdef CONFIG_RSS_THRESHOLD + mm->rss_threshold = 0; +#endif atomic_set(&mm->mm_users, 1); atomic_set(&mm->mm_count, 1); seqcount_init(&mm->write_protect_seq); diff --git a/mm/Kconfig b/mm/Kconfig index 11f2f83389e5..f84e9add43a0 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -1357,5 +1357,14 @@ config PURGEABLE_ASHMEM Support purgeable ashmem for process source "mm/damon/Kconfig" +# +# Use rss_threshold to monitoring RSS +# +config RSS_THRESHOLD + bool "Enable /proc//rss and /proc//rss_threshold to monitoring RSS" + default n + depends on PROC_FS && MEMCG + help + Set a threshold to monitoring RSS in per pid endmenu diff --git a/mm/Makefile b/mm/Makefile index 94ea4fb43163..c59ab8041679 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -71,6 +71,7 @@ ifdef CONFIG_MMU obj-$(CONFIG_ADVISE_SYSCALLS) += madvise.o endif +obj-$(CONFIG_RSS_THRESHOLD) += rss_threshold.o obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o swap_slots.o obj-$(CONFIG_ZSWAP) += zswap.o obj-$(CONFIG_HAS_DMA) += dmapool.o diff --git a/mm/rss_threshold.c b/mm/rss_threshold.c new file mode 100644 index 000000000000..81f2dfc268e9 --- /dev/null +++ b/mm/rss_threshold.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * mm/rss_threshold.c + * + * Copyright (c) 2022 Huawei Technologies Co., Ltd. + */ +#include +#include +#include +#include "../fs/proc/internal.h" + +int proc_pid_rss(struct seq_file *m, struct pid_namespace *ns, + struct pid *pid, struct task_struct *task) +{ + struct mm_struct *mm = get_task_mm(task); + unsigned long total_rss; + + if (mm) { + total_rss = get_mm_rss(mm); + seq_printf(m, "VMRss:%lu KB\n", total_rss << (PAGE_SHIFT - 10)); + mmput(mm); + } + return 0; +} + +void listen_rss_threshold(struct mm_struct *mm) +{ + unsigned long total_rss; + + total_rss = get_mm_rss(mm); + + if (!(mm->owner) || mm->rss_threshold == 0) + return; + + total_rss = total_rss << (PAGE_SHIFT - 10); + + if (likely(total_rss <= mm->rss_threshold)) + return; + + if (mm->owner->comm) + pr_err("rss_threshold monitor:Pid:%d [%s] rss size:%lu KB is out of range:%lu KB\n", + mm->owner->pid, mm->owner->comm, + total_rss, + mm->rss_threshold); + else + pr_err("rss_threshold monitor:Pid:%d [NULL] rss size:%lu KB is out of range:%lu KB\n", + mm->owner->pid, + total_rss, + mm->rss_threshold); +} + +static ssize_t rss_threshold_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct inode *inode = file_inode(file); + struct task_struct *p; + struct mm_struct *mm = NULL; + unsigned long mem_total; + unsigned long rss_threshold; + int err; + + err = kstrtoul_from_user(buf, count, 0, &rss_threshold); + if (err < 0) + return err; + + mem_total = totalram_pages() << (PAGE_SHIFT - 10); + if (rss_threshold < 0 || rss_threshold > mem_total) + return -EINVAL; + + p = get_proc_task(inode); + if (!p) + return -ESRCH; + + mm = get_task_mm(p); + if (mm) { + mm->rss_threshold = rss_threshold; + listen_rss_threshold(mm); + mmput(mm); + } + + put_task_struct(p); + + return count; +} + +static int rss_threshold_show(struct seq_file *m, void *v) +{ + struct inode *inode = m->private; + struct task_struct *p; + struct mm_struct *mm = NULL; + + p = get_proc_task(inode); + if (!p) + return -ESRCH; + + mm = get_task_mm(p); + if (mm) { + seq_printf(m, "Threshold:%lu KB\n", mm->rss_threshold); + mmput(mm); + } + put_task_struct(p); + + return 0; +} + +static int rss_threshold_open(struct inode *inode, struct file *filp) +{ + return single_open(filp, rss_threshold_show, inode); +} + +const struct file_operations proc_pid_rss_threshold_operations = { + .open = rss_threshold_open, + .read = seq_read, + .write = rss_threshold_write, + .llseek = seq_lseek, + .release = single_release, +}; \ No newline at end of file -- Gitee