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