diff --git a/OAT.xml b/OAT.xml
index 125e60d97df6d05daa278e16a7ea52affb893b4e..6385c7a4f59e0624a63aff48a9b15ef4de84ed60 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 f1e1a0b2cae88c5f1c09a0895009ee817a10c2c3..6a35dd810ac3439b407c9adcc5b2574f6ede5b1c 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 445c74a39a931f22762bd6034159e8e16ccacd11..c39cac8f7efa071324dd65bf6805ae6bf8e3daf1 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 4176fa18f692dff4761c742186486e88153239c4..8fd0fc27fe09ae1309417cf981fab07341fbf22f 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 2b2616008a49212af52fc5a8b3153979a2229985..69bb0a199ae950355aa463fed5be1790d0d9d10e 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 0907f94005c842af29e28933e4a60c40a0f11337..a61c17928555b5526fc4c92e163f0c2fc9791e19 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 11f2f83389e57cc2ed350c11130eabfb15bd0c40..f84e9add43a0e27d2de4ddbc5dc33efe76dc30be 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 94ea4fb431637fdb8c465637ddc4211279e1102d..c59ab8041679412c8c30ea2c7e394b299b6d0dd8 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 0000000000000000000000000000000000000000..81f2dfc268e95e1ea0d7aafbdd91e62f08044ffb
--- /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