• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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