• 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/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