1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * mm/rss_threshold.c
4 *
5 * Copyright (c) 2022 Huawei Technologies Co., Ltd.
6 */
7 #include <linux/seq_file.h>
8 #include <linux/oom.h>
9 #include <linux/mm.h>
10 #include <linux/sched/mm.h>
11 #include "../fs/proc/internal.h"
12
proc_pid_rss(struct seq_file * m,struct pid_namespace * ns,struct pid * pid,struct task_struct * task)13 int proc_pid_rss(struct seq_file *m, struct pid_namespace *ns,
14 struct pid *pid, struct task_struct *task)
15 {
16 struct mm_struct *mm = get_task_mm(task);
17 unsigned long total_rss;
18
19 if (mm) {
20 total_rss = get_mm_rss(mm);
21 seq_printf(m, "VMRss:%lu KB\n", total_rss << (PAGE_SHIFT - 10));
22 mmput(mm);
23 }
24 return 0;
25 }
26
rss_theashold_oom_kill(struct task_struct * task)27 static int rss_theashold_oom_kill(struct task_struct *task)
28 {
29 if (task)
30 return oom_kill_memcg_member(task, "rss out of range\n");
31 return 0;
32 }
33
listen_rss_threshold(struct mm_struct * mm)34 void listen_rss_threshold(struct mm_struct *mm)
35 {
36 unsigned long total_rss;
37
38 total_rss = get_mm_rss(mm);
39
40 if (!(mm->owner) || mm->rss_threshold == 0)
41 return;
42
43 total_rss = total_rss << (PAGE_SHIFT - 10);
44
45 if (likely(total_rss <= mm->rss_threshold))
46 return;
47
48 if (mm->owner->comm)
49 pr_err("rss_threshold monitor: Killing Pid:%d [%s] (tgid:%d) rss size:%lu KB is out of range:%lu KB\n",
50 mm->owner->pid, mm->owner->comm, mm->owner->tgid,
51 total_rss,
52 mm->rss_threshold);
53 else
54 pr_err("rss_threshold monitor: Killing Pid:%d [NULL] tgid:%d rss size:%lu KB is out of range:%lu KB\n",
55 mm->owner->pid, mm->owner->tgid,
56 total_rss,
57 mm->rss_threshold);
58 rss_theashold_oom_kill(mm->owner);
59 }
60
rss_threshold_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)61 static ssize_t rss_threshold_write(struct file *file, const char __user *buf,
62 size_t count, loff_t *ppos)
63 {
64 struct inode *inode = file_inode(file);
65 struct task_struct *p;
66 struct mm_struct *mm = NULL;
67 unsigned long mem_total;
68 unsigned long rss_threshold;
69 int err;
70
71 err = kstrtoul_from_user(buf, count, 0, &rss_threshold);
72 if (err < 0)
73 return err;
74
75 mem_total = totalram_pages() << (PAGE_SHIFT - 10);
76 if (rss_threshold < 0 || rss_threshold > mem_total)
77 return -EINVAL;
78
79 p = get_proc_task(inode);
80 if (!p)
81 return -ESRCH;
82
83 mm = get_task_mm(p);
84 if (mm) {
85 mm->rss_threshold = rss_threshold;
86 listen_rss_threshold(mm);
87 mmput(mm);
88 }
89
90 put_task_struct(p);
91
92 return count;
93 }
94
rss_threshold_show(struct seq_file * m,void * v)95 static int rss_threshold_show(struct seq_file *m, void *v)
96 {
97 struct inode *inode = m->private;
98 struct task_struct *p;
99 struct mm_struct *mm = NULL;
100
101 p = get_proc_task(inode);
102 if (!p)
103 return -ESRCH;
104
105 mm = get_task_mm(p);
106 if (mm) {
107 seq_printf(m, "Threshold:%lu KB\n", mm->rss_threshold);
108 mmput(mm);
109 }
110 put_task_struct(p);
111
112 return 0;
113 }
114
rss_threshold_open(struct inode * inode,struct file * filp)115 static int rss_threshold_open(struct inode *inode, struct file *filp)
116 {
117 return single_open(filp, rss_threshold_show, inode);
118 }
119
120 const struct file_operations proc_pid_rss_threshold_operations = {
121 .open = rss_threshold_open,
122 .read = seq_read,
123 .write = rss_threshold_write,
124 .llseek = seq_lseek,
125 .release = single_release,
126 };
127