blob: 474794933d7dfa472f02159ff5d58aa394cc1324 [file] [log] [blame]
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +09001/* drivers/misc/lowmemorykiller.c
2 *
3 * The lowmemorykiller driver lets user-space specify a set of memory thresholds
David Rientjes940f77b2012-02-13 19:28:49 -08004 * where processes with a range of oom_score_adj values will get killed. Specify
5 * the minimum oom_score_adj values in
6 * /sys/module/lowmemorykiller/parameters/adj and the number of free pages in
7 * /sys/module/lowmemorykiller/parameters/minfree. Both files take a comma
8 * separated list of numbers in ascending order.
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +09009 *
10 * For example, write "0,8" to /sys/module/lowmemorykiller/parameters/adj and
Marco Navarra3bf5d652011-12-22 13:28:23 +010011 * "1024,4096" to /sys/module/lowmemorykiller/parameters/minfree to kill
David Rientjes940f77b2012-02-13 19:28:49 -080012 * processes with a oom_score_adj value of 8 or higher when the free memory
13 * drops below 4096 pages and kill processes with a oom_score_adj value of 0 or
14 * higher when the free memory drops below 1024 pages.
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090015 *
16 * The driver considers memory used for caches to be free, but if a large
17 * percentage of the cached memory is locked this can be very inaccurate
18 * and processes may not get killed until the normal oom killer is triggered.
19 *
20 * Copyright (C) 2007-2008 Google, Inc.
21 *
22 * This software is licensed under the terms of the GNU General Public
23 * License version 2, as published by the Free Software Foundation, and
24 * may be copied, distributed, and modified under those terms.
25 *
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
30 *
31 */
32
Dmitry Voytik6b83f912013-03-16 11:37:26 +040033#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
34
Paul Gortmaker380b6542015-10-11 15:47:32 -040035#include <linux/init.h>
36#include <linux/moduleparam.h>
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090037#include <linux/kernel.h>
38#include <linux/mm.h>
39#include <linux/oom.h>
40#include <linux/sched.h>
Arve Hjønnevågeeb0f4f2013-02-26 22:07:35 -080041#include <linux/swap.h>
Anton Vorontsov294b2712012-02-06 20:29:41 +040042#include <linux/rcupdate.h>
San Mehat4755b722010-05-05 11:38:42 -070043#include <linux/profile.h>
44#include <linux/notifier.h>
Liam Mark11a71a32013-01-25 12:40:18 -080045#include <linux/mutex.h>
46#include <linux/delay.h>
seungho1.park7732e1d2012-07-24 10:20:44 +090047#include <linux/swap.h>
Liam Markc1c69b82013-08-30 12:10:39 -070048#include <linux/fs.h>
Liam Mark313d2ee2014-06-03 13:57:47 -070049#include <linux/cpuset.h>
Vinayak Menon11fac0a2015-03-04 20:41:21 +053050#include <linux/vmpressure.h>
Charan Teja Reddy05d778c22017-07-20 20:08:08 +053051#include <linux/freezer.h>
Vinayak Menon11fac0a2015-03-04 20:41:21 +053052
53#define CREATE_TRACE_POINTS
54#include <trace/events/almk.h>
Laura Abbott9a10a802014-09-23 19:31:19 -070055#include <linux/show_mem_notifier.h>
seungho1.park7732e1d2012-07-24 10:20:44 +090056
57#ifdef CONFIG_HIGHMEM
58#define _ZONE ZONE_HIGHMEM
59#else
60#define _ZONE ZONE_NORMAL
61#endif
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090062
Martijn Coenen3aff1e22015-05-26 11:28:47 +020063#define CREATE_TRACE_POINTS
64#include "trace/lowmemorykiller.h"
65
Ioana Ciornei36f16ff2015-11-01 16:38:21 +020066static u32 lowmem_debug_level = 1;
David Rientjesa9c58b902012-12-11 16:02:54 -080067static short lowmem_adj[6] = {
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090068 0,
69 1,
70 6,
71 12,
72};
Sandeep Jainb33061f2016-02-29 18:48:30 +053073
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090074static int lowmem_adj_size = 4;
Greg Kroah-Hartman624b2252012-03-07 13:21:23 -080075static int lowmem_minfree[6] = {
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090076 3 * 512, /* 6MB */
77 2 * 1024, /* 8MB */
78 4 * 1024, /* 16MB */
79 16 * 1024, /* 64MB */
80};
Sandeep Jainb33061f2016-02-29 18:48:30 +053081
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090082static int lowmem_minfree_size = 4;
seungho1.park7732e1d2012-07-24 10:20:44 +090083static int lmk_fast_run = 1;
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090084
Arve Hjønnevåge5d79652012-01-13 22:21:25 +040085static unsigned long lowmem_deathpending_timeout;
San Mehat4755b722010-05-05 11:38:42 -070086
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090087#define lowmem_print(level, x...) \
88 do { \
89 if (lowmem_debug_level >= (level)) \
Dmitry Voytik6b83f912013-03-16 11:37:26 +040090 pr_info(x); \
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090091 } while (0)
92
Dave Chinner7dc19d52013-08-28 10:18:11 +100093static unsigned long lowmem_count(struct shrinker *s,
94 struct shrink_control *sc)
95{
Mel Gorman599d0c92016-07-28 15:45:31 -070096 return global_node_page_state(NR_ACTIVE_ANON) +
97 global_node_page_state(NR_ACTIVE_FILE) +
98 global_node_page_state(NR_INACTIVE_ANON) +
99 global_node_page_state(NR_INACTIVE_FILE);
Dave Chinner7dc19d52013-08-28 10:18:11 +1000100}
101
Vinayak Menon11fac0a2015-03-04 20:41:21 +0530102static atomic_t shift_adj = ATOMIC_INIT(0);
103static short adj_max_shift = 353;
Suyog Sardaee3a85ff2016-06-07 21:15:42 +0530104module_param_named(adj_max_shift, adj_max_shift, short, 0644);
Vinayak Menon11fac0a2015-03-04 20:41:21 +0530105
106/* User knob to enable/disable adaptive lmk feature */
107static int enable_adaptive_lmk;
108module_param_named(enable_adaptive_lmk, enable_adaptive_lmk, int, 0644);
109
110/*
111 * This parameter controls the behaviour of LMK when vmpressure is in
112 * the range of 90-94. Adaptive lmk triggers based on number of file
113 * pages wrt vmpressure_file_min, when vmpressure is in the range of
114 * 90-94. Usually this is a pseudo minfree value, higher than the
115 * highest configured value in minfree array.
116 */
117static int vmpressure_file_min;
118module_param_named(vmpressure_file_min, vmpressure_file_min, int, 0644);
119
Charan Teja Reddy05d778c22017-07-20 20:08:08 +0530120/* User knob to enable/disable oom reaping feature */
121static int oom_reaper;
122module_param_named(oom_reaper, oom_reaper, int, 0644);
123
Vinayak Menon11fac0a2015-03-04 20:41:21 +0530124enum {
125 VMPRESSURE_NO_ADJUST = 0,
126 VMPRESSURE_ADJUST_ENCROACH,
127 VMPRESSURE_ADJUST_NORMAL,
128};
129
130static int adjust_minadj(short *min_score_adj)
131{
132 int ret = VMPRESSURE_NO_ADJUST;
133
134 if (!enable_adaptive_lmk)
135 return 0;
136
137 if (atomic_read(&shift_adj) &&
138 (*min_score_adj > adj_max_shift)) {
139 if (*min_score_adj == OOM_SCORE_ADJ_MAX + 1)
140 ret = VMPRESSURE_ADJUST_ENCROACH;
141 else
142 ret = VMPRESSURE_ADJUST_NORMAL;
143 *min_score_adj = adj_max_shift;
144 }
145 atomic_set(&shift_adj, 0);
146
147 return ret;
148}
149
150static int lmk_vmpressure_notifier(struct notifier_block *nb,
151 unsigned long action, void *data)
152{
153 int other_free, other_file;
154 unsigned long pressure = action;
155 int array_size = ARRAY_SIZE(lowmem_adj);
156
157 if (!enable_adaptive_lmk)
158 return 0;
159
160 if (pressure >= 95) {
161 other_file = global_node_page_state(NR_FILE_PAGES) -
162 global_node_page_state(NR_SHMEM) -
163 total_swapcache_pages();
164 other_free = global_page_state(NR_FREE_PAGES);
165
166 atomic_set(&shift_adj, 1);
167 trace_almk_vmpressure(pressure, other_free, other_file);
168 } else if (pressure >= 90) {
169 if (lowmem_adj_size < array_size)
170 array_size = lowmem_adj_size;
171 if (lowmem_minfree_size < array_size)
172 array_size = lowmem_minfree_size;
173
174 other_file = global_node_page_state(NR_FILE_PAGES) -
175 global_node_page_state(NR_SHMEM) -
176 total_swapcache_pages();
177
178 other_free = global_page_state(NR_FREE_PAGES);
179
180 if ((other_free < lowmem_minfree[array_size - 1]) &&
181 (other_file < vmpressure_file_min)) {
182 atomic_set(&shift_adj, 1);
183 trace_almk_vmpressure(pressure, other_free, other_file);
184 }
Vinayak Menoncae1cff2015-08-19 16:11:04 +0530185 } else if (atomic_read(&shift_adj)) {
186 other_file = global_node_page_state(NR_FILE_PAGES) -
187 global_node_page_state(NR_SHMEM) -
188 total_swapcache_pages();
189
190 other_free = global_page_state(NR_FREE_PAGES);
191 /*
192 * shift_adj would have been set by a previous invocation
193 * of notifier, which is not followed by a lowmem_shrink yet.
194 * Since vmpressure has improved, reset shift_adj to avoid
195 * false adaptive LMK trigger.
196 */
197 trace_almk_vmpressure(pressure, other_free, other_file);
198 atomic_set(&shift_adj, 0);
Vinayak Menon11fac0a2015-03-04 20:41:21 +0530199 }
200
201 return 0;
202}
203
204static struct notifier_block lmk_vmpr_nb = {
205 .notifier_call = lmk_vmpressure_notifier,
206};
207
Liam Mark4f1cdd22013-02-07 14:31:36 -0800208static int test_task_flag(struct task_struct *p, int flag)
209{
Vinayak Menoncc2363002015-05-21 20:44:14 +0530210 struct task_struct *t;
Liam Mark4f1cdd22013-02-07 14:31:36 -0800211
Vinayak Menoncc2363002015-05-21 20:44:14 +0530212 for_each_thread(p, t) {
Liam Mark4f1cdd22013-02-07 14:31:36 -0800213 task_lock(t);
214 if (test_tsk_thread_flag(t, flag)) {
215 task_unlock(t);
216 return 1;
217 }
218 task_unlock(t);
Vinayak Menoncc2363002015-05-21 20:44:14 +0530219 }
Liam Mark4f1cdd22013-02-07 14:31:36 -0800220
221 return 0;
222}
223
Prakash Gupta364bedd2017-04-18 07:32:20 +0530224static int test_task_state(struct task_struct *p, int state)
225{
226 struct task_struct *t;
227
228 for_each_thread(p, t) {
229 task_lock(t);
230 if (t->state & state) {
231 task_unlock(t);
232 return 1;
233 }
234 task_unlock(t);
235 }
236
237 return 0;
238}
239
Liam Mark302cef72012-09-20 14:42:28 -0700240static int test_task_lmk_waiting(struct task_struct *p)
241{
Vinayak Menoncc2363002015-05-21 20:44:14 +0530242 struct task_struct *t;
Liam Mark302cef72012-09-20 14:42:28 -0700243
Vinayak Menoncc2363002015-05-21 20:44:14 +0530244 for_each_thread(p, t) {
Liam Mark302cef72012-09-20 14:42:28 -0700245 task_lock(t);
246 if (task_lmk_waiting(t)) {
247 task_unlock(t);
248 return 1;
249 }
250 task_unlock(t);
Vinayak Menoncc2363002015-05-21 20:44:14 +0530251 }
Liam Mark302cef72012-09-20 14:42:28 -0700252
253 return 0;
254}
255
Liam Mark11a71a32013-01-25 12:40:18 -0800256static DEFINE_MUTEX(scan_mutex);
257
Liam Mark06a5f872013-03-27 12:34:51 -0700258static int can_use_cma_pages(gfp_t gfp_mask)
259{
260 int can_use = 0;
261 int mtype = gfpflags_to_migratetype(gfp_mask);
262 int i = 0;
263 int *mtype_fallbacks = get_migratetype_fallbacks(mtype);
264
265 if (is_migrate_cma(mtype)) {
266 can_use = 1;
267 } else {
268 for (i = 0;; i++) {
269 int fallbacktype = mtype_fallbacks[i];
270
271 if (is_migrate_cma(fallbacktype)) {
272 can_use = 1;
273 break;
274 }
275
276 if (fallbacktype == MIGRATE_TYPES)
277 break;
278 }
279 }
280 return can_use;
281}
282
seungho1.park7732e1d2012-07-24 10:20:44 +0900283void tune_lmk_zone_param(struct zonelist *zonelist, int classzone_idx,
Liam Mark06a5f872013-03-27 12:34:51 -0700284 int *other_free, int *other_file,
285 int use_cma_pages)
seungho1.park7732e1d2012-07-24 10:20:44 +0900286{
287 struct zone *zone;
288 struct zoneref *zoneref;
289 int zone_idx;
290
291 for_each_zone_zonelist(zone, zoneref, zonelist, MAX_NR_ZONES) {
Liam Mark06a5f872013-03-27 12:34:51 -0700292 zone_idx = zonelist_zone_idx(zoneref);
293 if (zone_idx == ZONE_MOVABLE) {
294 if (!use_cma_pages && other_free)
295 *other_free -=
296 zone_page_state(zone, NR_FREE_CMA_PAGES);
seungho1.park7732e1d2012-07-24 10:20:44 +0900297 continue;
Liam Mark06a5f872013-03-27 12:34:51 -0700298 }
seungho1.park7732e1d2012-07-24 10:20:44 +0900299
300 if (zone_idx > classzone_idx) {
301 if (other_free != NULL)
302 *other_free -= zone_page_state(zone,
303 NR_FREE_PAGES);
304 if (other_file != NULL)
305 *other_file -= zone_page_state(zone,
306 NR_ZONE_INACTIVE_FILE) +
307 zone_page_state(zone,
308 NR_ZONE_ACTIVE_FILE);
Susheel Khiani911baf92015-02-12 19:00:15 +0530309 } else if (zone_idx < classzone_idx) {
310 if (zone_watermark_ok(zone, 0, 0, classzone_idx, 0) &&
311 other_free) {
Liam Mark06a5f872013-03-27 12:34:51 -0700312 if (!use_cma_pages) {
313 *other_free -= min(
314 zone->lowmem_reserve[classzone_idx] +
315 zone_page_state(
316 zone, NR_FREE_CMA_PAGES),
317 zone_page_state(
318 zone, NR_FREE_PAGES));
319 } else {
320 *other_free -=
321 zone->lowmem_reserve[classzone_idx];
322 }
323 } else {
Susheel Khiani911baf92015-02-12 19:00:15 +0530324 if (other_free)
325 *other_free -=
326 zone_page_state(zone, NR_FREE_PAGES);
Liam Mark06a5f872013-03-27 12:34:51 -0700327 }
seungho1.park7732e1d2012-07-24 10:20:44 +0900328 }
329 }
330}
331
Liam Markb03ced72014-03-10 16:06:39 -0700332#ifdef CONFIG_HIGHMEM
333static void adjust_gfp_mask(gfp_t *gfp_mask)
334{
335 struct zone *preferred_zone;
336 struct zoneref *zref;
337 struct zonelist *zonelist;
338 enum zone_type high_zoneidx;
339
340 if (current_is_kswapd()) {
341 zonelist = node_zonelist(0, *gfp_mask);
342 high_zoneidx = gfp_zone(*gfp_mask);
343 zref = first_zones_zonelist(zonelist, high_zoneidx, NULL);
344 preferred_zone = zref->zone;
345
346 if (high_zoneidx == ZONE_NORMAL) {
347 if (zone_watermark_ok_safe(
348 preferred_zone, 0,
Srinivas Ramana51608392016-05-13 18:17:41 +0530349 high_wmark_pages(preferred_zone), 0))
Liam Markb03ced72014-03-10 16:06:39 -0700350 *gfp_mask |= __GFP_HIGHMEM;
351 } else if (high_zoneidx == ZONE_HIGHMEM) {
352 *gfp_mask |= __GFP_HIGHMEM;
353 }
354 }
355}
356#else
357static void adjust_gfp_mask(gfp_t *unused)
358{
359}
360#endif
361
seungho1.park7732e1d2012-07-24 10:20:44 +0900362void tune_lmk_param(int *other_free, int *other_file, struct shrink_control *sc)
363{
364 gfp_t gfp_mask;
365 struct zone *preferred_zone;
366 struct zoneref *zref;
367 struct zonelist *zonelist;
368 enum zone_type high_zoneidx, classzone_idx;
369 unsigned long balance_gap;
Liam Mark06a5f872013-03-27 12:34:51 -0700370 int use_cma_pages;
seungho1.park7732e1d2012-07-24 10:20:44 +0900371
372 gfp_mask = sc->gfp_mask;
Liam Markb03ced72014-03-10 16:06:39 -0700373 adjust_gfp_mask(&gfp_mask);
374
seungho1.park7732e1d2012-07-24 10:20:44 +0900375 zonelist = node_zonelist(0, gfp_mask);
376 high_zoneidx = gfp_zone(gfp_mask);
377 zref = first_zones_zonelist(zonelist, high_zoneidx, NULL);
378 preferred_zone = zref->zone;
379 classzone_idx = zone_idx(preferred_zone);
Liam Mark06a5f872013-03-27 12:34:51 -0700380 use_cma_pages = can_use_cma_pages(gfp_mask);
seungho1.park7732e1d2012-07-24 10:20:44 +0900381
382 balance_gap = min(low_wmark_pages(preferred_zone),
383 (preferred_zone->present_pages +
384 100-1) /
385 100);
386
387 if (likely(current_is_kswapd() && zone_watermark_ok(preferred_zone, 0,
388 high_wmark_pages(preferred_zone) + SWAP_CLUSTER_MAX +
389 balance_gap, 0, 0))) {
390 if (lmk_fast_run)
391 tune_lmk_zone_param(zonelist, classzone_idx, other_free,
Liam Mark06a5f872013-03-27 12:34:51 -0700392 other_file, use_cma_pages);
seungho1.park7732e1d2012-07-24 10:20:44 +0900393 else
394 tune_lmk_zone_param(zonelist, classzone_idx, other_free,
Liam Mark06a5f872013-03-27 12:34:51 -0700395 NULL, use_cma_pages);
seungho1.park7732e1d2012-07-24 10:20:44 +0900396
Liam Mark06a5f872013-03-27 12:34:51 -0700397 if (zone_watermark_ok(preferred_zone, 0, 0, _ZONE, 0)) {
398 if (!use_cma_pages) {
399 *other_free -= min(
400 preferred_zone->lowmem_reserve[_ZONE]
401 + zone_page_state(
402 preferred_zone, NR_FREE_CMA_PAGES),
403 zone_page_state(
404 preferred_zone, NR_FREE_PAGES));
405 } else {
406 *other_free -=
407 preferred_zone->lowmem_reserve[_ZONE];
408 }
409 } else {
seungho1.park7732e1d2012-07-24 10:20:44 +0900410 *other_free -= zone_page_state(preferred_zone,
411 NR_FREE_PAGES);
Liam Mark06a5f872013-03-27 12:34:51 -0700412 }
413
seungho1.park7732e1d2012-07-24 10:20:44 +0900414 lowmem_print(4, "lowmem_shrink of kswapd tunning for highmem "
415 "ofree %d, %d\n", *other_free, *other_file);
416 } else {
417 tune_lmk_zone_param(zonelist, classzone_idx, other_free,
Liam Mark06a5f872013-03-27 12:34:51 -0700418 other_file, use_cma_pages);
419
420 if (!use_cma_pages) {
421 *other_free -=
422 zone_page_state(preferred_zone, NR_FREE_CMA_PAGES);
423 }
seungho1.park7732e1d2012-07-24 10:20:44 +0900424
425 lowmem_print(4, "lowmem_shrink tunning for others ofree %d, "
426 "%d\n", *other_free, *other_file);
427 }
428}
429
Charan Teja Reddy05d778c22017-07-20 20:08:08 +0530430static void mark_lmk_victim(struct task_struct *tsk)
431{
432 struct mm_struct *mm = tsk->mm;
433
434 if (!cmpxchg(&tsk->signal->oom_mm, NULL, mm))
435 atomic_inc(&tsk->signal->oom_mm->mm_count);
436}
437
Dave Chinner7dc19d52013-08-28 10:18:11 +1000438static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900439{
Anton Vorontsov95670002012-02-06 20:29:47 +0400440 struct task_struct *tsk;
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900441 struct task_struct *selected = NULL;
Dave Chinner7dc19d52013-08-28 10:18:11 +1000442 unsigned long rem = 0;
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900443 int tasksize;
444 int i;
Vinayak Menon11fac0a2015-03-04 20:41:21 +0530445 int ret = 0;
David Rientjesa9c58b902012-12-11 16:02:54 -0800446 short min_score_adj = OOM_SCORE_ADJ_MAX + 1;
Colin Crosscc635da2016-01-29 22:07:33 -0800447 int minfree = 0;
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900448 int selected_tasksize = 0;
David Rientjesa9c58b902012-12-11 16:02:54 -0800449 short selected_oom_score_adj;
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900450 int array_size = ARRAY_SIZE(lowmem_adj);
Liam Mark11a71a32013-01-25 12:40:18 -0800451 int other_free;
452 int other_file;
453
Prakash Gupta364bedd2017-04-18 07:32:20 +0530454 if (!mutex_trylock(&scan_mutex))
Liam Mark11a71a32013-01-25 12:40:18 -0800455 return 0;
456
457 other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;
Liam Markc1c69b82013-08-30 12:10:39 -0700458
459 if (global_node_page_state(NR_SHMEM) + total_swapcache_pages() +
460 global_node_page_state(NR_UNEVICTABLE) <
461 global_node_page_state(NR_FILE_PAGES))
462 other_file = global_node_page_state(NR_FILE_PAGES) -
Liam Mark11a71a32013-01-25 12:40:18 -0800463 global_node_page_state(NR_SHMEM) -
464 global_node_page_state(NR_UNEVICTABLE) -
465 total_swapcache_pages();
Liam Markc1c69b82013-08-30 12:10:39 -0700466 else
467 other_file = 0;
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900468
seungho1.park7732e1d2012-07-24 10:20:44 +0900469 tune_lmk_param(&other_free, &other_file, sc);
470
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900471 if (lowmem_adj_size < array_size)
472 array_size = lowmem_adj_size;
473 if (lowmem_minfree_size < array_size)
474 array_size = lowmem_minfree_size;
475 for (i = 0; i < array_size; i++) {
Colin Crosscc635da2016-01-29 22:07:33 -0800476 minfree = lowmem_minfree[i];
477 if (other_free < minfree && other_file < minfree) {
David Rientjes940f77b2012-02-13 19:28:49 -0800478 min_score_adj = lowmem_adj[i];
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900479 break;
480 }
481 }
Dave Chinner7dc19d52013-08-28 10:18:11 +1000482
Vinayak Menon11fac0a2015-03-04 20:41:21 +0530483 ret = adjust_minadj(&min_score_adj);
484
Dave Chinner7dc19d52013-08-28 10:18:11 +1000485 lowmem_print(3, "lowmem_scan %lu, %x, ofree %d %d, ma %hd\n",
Ioana Ciorneif8b053e2015-11-01 16:38:22 +0200486 sc->nr_to_scan, sc->gfp_mask, other_free,
487 other_file, min_score_adj);
Dave Chinner7dc19d52013-08-28 10:18:11 +1000488
489 if (min_score_adj == OOM_SCORE_ADJ_MAX + 1) {
Vinayak Menon11fac0a2015-03-04 20:41:21 +0530490 trace_almk_shrink(0, ret, other_free, other_file, 0);
Dave Chinner7dc19d52013-08-28 10:18:11 +1000491 lowmem_print(5, "lowmem_scan %lu, %x, return 0\n",
492 sc->nr_to_scan, sc->gfp_mask);
Liam Mark11a71a32013-01-25 12:40:18 -0800493 mutex_unlock(&scan_mutex);
Dave Chinner7dc19d52013-08-28 10:18:11 +1000494 return 0;
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900495 }
Dave Chinner7dc19d52013-08-28 10:18:11 +1000496
David Rientjes940f77b2012-02-13 19:28:49 -0800497 selected_oom_score_adj = min_score_adj;
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900498
Anton Vorontsov294b2712012-02-06 20:29:41 +0400499 rcu_read_lock();
Anton Vorontsov95670002012-02-06 20:29:47 +0400500 for_each_process(tsk) {
501 struct task_struct *p;
David Rientjesa9c58b902012-12-11 16:02:54 -0800502 short oom_score_adj;
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900503
Anton Vorontsov9823ec92012-02-06 20:30:01 +0400504 if (tsk->flags & PF_KTHREAD)
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900505 continue;
Anton Vorontsov9823ec92012-02-06 20:30:01 +0400506
Liam Mark4f1cdd22013-02-07 14:31:36 -0800507 /* if task no longer has any memory ignore it */
508 if (test_task_flag(tsk, TIF_MM_RELEASED))
509 continue;
510
Liam Mark302cef72012-09-20 14:42:28 -0700511 if (time_before_eq(jiffies, lowmem_deathpending_timeout)) {
512 if (test_task_lmk_waiting(tsk)) {
513 rcu_read_unlock();
Liam Mark11a71a32013-01-25 12:40:18 -0800514 mutex_unlock(&scan_mutex);
Liam Mark302cef72012-09-20 14:42:28 -0700515 return 0;
516 }
517 }
518
Anton Vorontsov95670002012-02-06 20:29:47 +0400519 p = find_lock_task_mm(tsk);
520 if (!p)
521 continue;
522
David Rientjes940f77b2012-02-13 19:28:49 -0800523 oom_score_adj = p->signal->oom_score_adj;
524 if (oom_score_adj < min_score_adj) {
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900525 task_unlock(p);
526 continue;
527 }
Anton Vorontsov95670002012-02-06 20:29:47 +0400528 tasksize = get_mm_rss(p->mm);
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900529 task_unlock(p);
530 if (tasksize <= 0)
531 continue;
532 if (selected) {
David Rientjes940f77b2012-02-13 19:28:49 -0800533 if (oom_score_adj < selected_oom_score_adj)
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900534 continue;
David Rientjes940f77b2012-02-13 19:28:49 -0800535 if (oom_score_adj == selected_oom_score_adj &&
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900536 tasksize <= selected_tasksize)
537 continue;
538 }
539 selected = p;
540 selected_tasksize = tasksize;
David Rientjes940f77b2012-02-13 19:28:49 -0800541 selected_oom_score_adj = oom_score_adj;
Liam Mark313d2ee2014-06-03 13:57:47 -0700542 lowmem_print(3, "select '%s' (%d), adj %hd, size %d, to kill\n",
Colin Crosscc635da2016-01-29 22:07:33 -0800543 p->comm, p->pid, oom_score_adj, tasksize);
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900544 }
545 if (selected) {
Brian Norrisc2aacb62016-02-29 17:40:05 -0800546 long cache_size = other_file * (long)(PAGE_SIZE / 1024);
547 long cache_limit = minfree * (long)(PAGE_SIZE / 1024);
548 long free = other_free * (long)(PAGE_SIZE / 1024);
549
Prakash Gupta364bedd2017-04-18 07:32:20 +0530550 if (test_task_lmk_waiting(selected) &&
551 (test_task_state(selected, TASK_UNINTERRUPTIBLE))) {
552 lowmem_print(2, "'%s' (%d) is already killed\n",
553 selected->comm,
554 selected->pid);
555 rcu_read_unlock();
556 mutex_unlock(&scan_mutex);
557 return 0;
558 }
559
David Rientjese1099a62015-04-28 15:50:46 -0700560 task_lock(selected);
Tetsuo Handa3a81fc22015-09-06 14:25:35 +0900561 send_sig(SIGKILL, selected, 0);
Tetsuo Handa3a81fc22015-09-06 14:25:35 +0900562 if (selected->mm)
Tetsuo Handa77ed2c52016-03-08 20:01:32 +0900563 task_set_lmk_waiting(selected);
Charan Teja Reddy05d778c22017-07-20 20:08:08 +0530564 if (oom_reaper)
565 mark_lmk_victim(selected);
David Rientjese1099a62015-04-28 15:50:46 -0700566 task_unlock(selected);
Charan Teja Reddy05d778c22017-07-20 20:08:08 +0530567 if (oom_reaper)
568 wake_oom_reaper(selected);
Martijn Coenen3aff1e22015-05-26 11:28:47 +0200569 trace_lowmemory_kill(selected, cache_size, cache_limit, free);
Joel Fernandesf44842e2017-07-21 09:41:06 -0700570 lowmem_print(1, "Killing '%s' (%d) (tgid %d), adj %hd,\n"
Liam Mark313d2ee2014-06-03 13:57:47 -0700571 "to free %ldkB on behalf of '%s' (%d) because\n"
572 "cache %ldkB is below limit %ldkB for oom score %hd\n"
573 "Free memory is %ldkB above reserved.\n"
574 "Free CMA is %ldkB\n"
575 "Total reserve is %ldkB\n"
576 "Total free pages is %ldkB\n"
577 "Total file cache is %ldkB\n"
578 "GFP mask is 0x%x\n",
Kyle Yan3dfb68c2017-07-28 16:52:28 -0700579 selected->comm, selected->pid, selected->tgid,
Liam Mark313d2ee2014-06-03 13:57:47 -0700580 selected_oom_score_adj,
581 selected_tasksize * (long)(PAGE_SIZE / 1024),
582 current->comm, current->pid,
583 cache_size, cache_limit,
584 min_score_adj,
585 free,
586 global_page_state(NR_FREE_CMA_PAGES) *
587 (long)(PAGE_SIZE / 1024),
588 totalreserve_pages * (long)(PAGE_SIZE / 1024),
589 global_page_state(NR_FREE_PAGES) *
590 (long)(PAGE_SIZE / 1024),
591 global_node_page_state(NR_FILE_PAGES) *
592 (long)(PAGE_SIZE / 1024),
593 sc->gfp_mask);
594
595 if (lowmem_debug_level >= 2 && selected_oom_score_adj == 0) {
596 show_mem(SHOW_MEM_FILTER_NODES);
Laura Abbott9a10a802014-09-23 19:31:19 -0700597 show_mem_call_notifiers();
Liam Mark313d2ee2014-06-03 13:57:47 -0700598 dump_tasks(NULL, NULL);
599 }
600
David Rientjese1099a62015-04-28 15:50:46 -0700601 lowmem_deathpending_timeout = jiffies + HZ;
Dave Chinner7dc19d52013-08-28 10:18:11 +1000602 rem += selected_tasksize;
Liam Mark4f1cdd22013-02-07 14:31:36 -0800603 rcu_read_unlock();
Liam Mark11a71a32013-01-25 12:40:18 -0800604 /* give the system time to free up the memory */
605 msleep_interruptible(20);
Vinayak Menon11fac0a2015-03-04 20:41:21 +0530606 trace_almk_shrink(selected_tasksize, ret,
607 other_free, other_file,
608 selected_oom_score_adj);
609 } else {
610 trace_almk_shrink(1, ret, other_free, other_file, 0);
Liam Mark4f1cdd22013-02-07 14:31:36 -0800611 rcu_read_unlock();
Vinayak Menon11fac0a2015-03-04 20:41:21 +0530612 }
Tetsuo Handa3a81fc22015-09-06 14:25:35 +0900613
Dave Chinner7dc19d52013-08-28 10:18:11 +1000614 lowmem_print(4, "lowmem_scan %lu, %x, return %lu\n",
Colin Crosscae9bf12011-06-22 16:05:47 -0700615 sc->nr_to_scan, sc->gfp_mask, rem);
Liam Mark11a71a32013-01-25 12:40:18 -0800616 mutex_unlock(&scan_mutex);
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900617 return rem;
618}
619
620static struct shrinker lowmem_shrinker = {
Dave Chinner7dc19d52013-08-28 10:18:11 +1000621 .scan_objects = lowmem_scan,
622 .count_objects = lowmem_count,
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900623 .seeks = DEFAULT_SEEKS * 16
624};
625
626static int __init lowmem_init(void)
627{
628 register_shrinker(&lowmem_shrinker);
Vinayak Menon11fac0a2015-03-04 20:41:21 +0530629 vmpressure_notifier_register(&lmk_vmpr_nb);
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900630 return 0;
631}
Paul Gortmaker380b6542015-10-11 15:47:32 -0400632device_initcall(lowmem_init);
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900633
Arve Hjønnevåg53b10282012-09-25 17:37:14 -0700634#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES
635static short lowmem_oom_adj_to_oom_score_adj(short oom_adj)
636{
637 if (oom_adj == OOM_ADJUST_MAX)
638 return OOM_SCORE_ADJ_MAX;
639 else
640 return (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE;
641}
642
643static void lowmem_autodetect_oom_adj_values(void)
644{
645 int i;
646 short oom_adj;
647 short oom_score_adj;
648 int array_size = ARRAY_SIZE(lowmem_adj);
649
650 if (lowmem_adj_size < array_size)
651 array_size = lowmem_adj_size;
652
653 if (array_size <= 0)
654 return;
655
656 oom_adj = lowmem_adj[array_size - 1];
657 if (oom_adj > OOM_ADJUST_MAX)
658 return;
659
660 oom_score_adj = lowmem_oom_adj_to_oom_score_adj(oom_adj);
661 if (oom_score_adj <= OOM_ADJUST_MAX)
662 return;
663
664 lowmem_print(1, "lowmem_shrink: convert oom_adj to oom_score_adj:\n");
665 for (i = 0; i < array_size; i++) {
666 oom_adj = lowmem_adj[i];
667 oom_score_adj = lowmem_oom_adj_to_oom_score_adj(oom_adj);
668 lowmem_adj[i] = oom_score_adj;
669 lowmem_print(1, "oom_adj %d => oom_score_adj %d\n",
670 oom_adj, oom_score_adj);
671 }
672}
673
674static int lowmem_adj_array_set(const char *val, const struct kernel_param *kp)
675{
676 int ret;
677
678 ret = param_array_ops.set(val, kp);
679
680 /* HACK: Autodetect oom_adj values in lowmem_adj array */
681 lowmem_autodetect_oom_adj_values();
682
683 return ret;
684}
685
686static int lowmem_adj_array_get(char *buffer, const struct kernel_param *kp)
687{
688 return param_array_ops.get(buffer, kp);
689}
690
691static void lowmem_adj_array_free(void *arg)
692{
693 param_array_ops.free(arg);
694}
695
696static struct kernel_param_ops lowmem_adj_array_ops = {
697 .set = lowmem_adj_array_set,
698 .get = lowmem_adj_array_get,
699 .free = lowmem_adj_array_free,
700};
701
702static const struct kparam_array __param_arr_adj = {
703 .max = ARRAY_SIZE(lowmem_adj),
704 .num = &lowmem_adj_size,
705 .ops = &param_ops_short,
706 .elemsize = sizeof(lowmem_adj[0]),
707 .elem = lowmem_adj,
708};
709#endif
710
Paul Gortmaker380b6542015-10-11 15:47:32 -0400711/*
712 * not really modular, but the easiest way to keep compat with existing
713 * bootargs behaviour is to continue using module_param here.
714 */
Eric Salem8abcae42016-09-25 22:33:34 -0500715module_param_named(cost, lowmem_shrinker.seeks, int, 0644);
Arve Hjønnevåg53b10282012-09-25 17:37:14 -0700716#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES
Amit Pundiraedbe642015-10-30 01:16:29 +0530717module_param_cb(adj, &lowmem_adj_array_ops,
718 .arr = &__param_arr_adj,
719 S_IRUGO | S_IWUSR);
Arve Hjønnevåg53b10282012-09-25 17:37:14 -0700720__MODULE_PARM_TYPE(adj, "array of short");
721#else
Eric Salem8abcae42016-09-25 22:33:34 -0500722module_param_array_named(adj, lowmem_adj, short, &lowmem_adj_size, 0644);
Arve Hjønnevåg53b10282012-09-25 17:37:14 -0700723#endif
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900724module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size,
seungho1.park7732e1d2012-07-24 10:20:44 +0900725 S_IRUGO | S_IWUSR);
726module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR);
727module_param_named(lmk_fast_run, lmk_fast_run, int, S_IRUGO | S_IWUSR);
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900728