Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

staging, android: remove lowmemory killer from the tree

Lowmemory killer is sitting in the staging tree since 2008 without any
serious interest for fixing issues brought up by the MM folks. The main
objection is that the implementation is basically broken by design:
- it hooks into slab shrinker API which is not suitable for this
purpose. lowmem_count implementation just shows this nicely.
There is no scaling based on the memory pressure and no
feedback to the generic shrinker infrastructure.
Moreover lowmem_scan is called way too often for the heavy
work it performs.
- it is not reclaim context aware - no NUMA and/or memcg
awareness.

As the code stands right now it just adds a maintenance overhead when
core MM changes have to update lowmemorykiller.c as well. It also seems
that the alternative LMK implementation will be solely in the userspace
so this code has no perspective it seems. The staging tree is supposed
to be for a code which needs to be put in shape before it can be merged
which is not the case here obviously.

Signed-off-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Michal Hocko and committed by
Greg Kroah-Hartman
915e70f9 12ab1659

-227
-10
drivers/staging/android/Kconfig
··· 14 14 It is, in theory, a good memory allocator for low-memory devices, 15 15 because it can discard shared memory units when under memory pressure. 16 16 17 - config ANDROID_LOW_MEMORY_KILLER 18 - bool "Android Low Memory Killer" 19 - ---help--- 20 - Registers processes to be killed when low memory conditions, this is useful 21 - as there is no particular swap space on android. 22 - 23 - The registered process will kill according to the priorities in android init 24 - scripts (/init.rc), and it defines priority values with minimum free memory size 25 - for each priority. 26 - 27 17 source "drivers/staging/android/ion/Kconfig" 28 18 29 19 endif # if ANDROID
-1
drivers/staging/android/Makefile
··· 3 3 obj-y += ion/ 4 4 5 5 obj-$(CONFIG_ASHMEM) += ashmem.o 6 - obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o
-212
drivers/staging/android/lowmemorykiller.c
··· 1 - /* drivers/misc/lowmemorykiller.c 2 - * 3 - * The lowmemorykiller driver lets user-space specify a set of memory thresholds 4 - * 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. 9 - * 10 - * For example, write "0,8" to /sys/module/lowmemorykiller/parameters/adj and 11 - * "1024,4096" to /sys/module/lowmemorykiller/parameters/minfree to kill 12 - * 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. 15 - * 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 - 33 - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 34 - 35 - #include <linux/init.h> 36 - #include <linux/moduleparam.h> 37 - #include <linux/kernel.h> 38 - #include <linux/mm.h> 39 - #include <linux/oom.h> 40 - #include <linux/sched/signal.h> 41 - #include <linux/swap.h> 42 - #include <linux/rcupdate.h> 43 - #include <linux/profile.h> 44 - #include <linux/notifier.h> 45 - 46 - static u32 lowmem_debug_level = 1; 47 - static short lowmem_adj[6] = { 48 - 0, 49 - 1, 50 - 6, 51 - 12, 52 - }; 53 - 54 - static int lowmem_adj_size = 4; 55 - static int lowmem_minfree[6] = { 56 - 3 * 512, /* 6MB */ 57 - 2 * 1024, /* 8MB */ 58 - 4 * 1024, /* 16MB */ 59 - 16 * 1024, /* 64MB */ 60 - }; 61 - 62 - static int lowmem_minfree_size = 4; 63 - 64 - static unsigned long lowmem_deathpending_timeout; 65 - 66 - #define lowmem_print(level, x...) \ 67 - do { \ 68 - if (lowmem_debug_level >= (level)) \ 69 - pr_info(x); \ 70 - } while (0) 71 - 72 - static unsigned long lowmem_count(struct shrinker *s, 73 - struct shrink_control *sc) 74 - { 75 - return global_node_page_state(NR_ACTIVE_ANON) + 76 - global_node_page_state(NR_ACTIVE_FILE) + 77 - global_node_page_state(NR_INACTIVE_ANON) + 78 - global_node_page_state(NR_INACTIVE_FILE); 79 - } 80 - 81 - static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) 82 - { 83 - struct task_struct *tsk; 84 - struct task_struct *selected = NULL; 85 - unsigned long rem = 0; 86 - int tasksize; 87 - int i; 88 - short min_score_adj = OOM_SCORE_ADJ_MAX + 1; 89 - int minfree = 0; 90 - int selected_tasksize = 0; 91 - short selected_oom_score_adj; 92 - int array_size = ARRAY_SIZE(lowmem_adj); 93 - int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages; 94 - int other_file = global_node_page_state(NR_FILE_PAGES) - 95 - global_node_page_state(NR_SHMEM) - 96 - total_swapcache_pages(); 97 - 98 - if (lowmem_adj_size < array_size) 99 - array_size = lowmem_adj_size; 100 - if (lowmem_minfree_size < array_size) 101 - array_size = lowmem_minfree_size; 102 - for (i = 0; i < array_size; i++) { 103 - minfree = lowmem_minfree[i]; 104 - if (other_free < minfree && other_file < minfree) { 105 - min_score_adj = lowmem_adj[i]; 106 - break; 107 - } 108 - } 109 - 110 - lowmem_print(3, "lowmem_scan %lu, %x, ofree %d %d, ma %hd\n", 111 - sc->nr_to_scan, sc->gfp_mask, other_free, 112 - other_file, min_score_adj); 113 - 114 - if (min_score_adj == OOM_SCORE_ADJ_MAX + 1) { 115 - lowmem_print(5, "lowmem_scan %lu, %x, return 0\n", 116 - sc->nr_to_scan, sc->gfp_mask); 117 - return 0; 118 - } 119 - 120 - selected_oom_score_adj = min_score_adj; 121 - 122 - rcu_read_lock(); 123 - for_each_process(tsk) { 124 - struct task_struct *p; 125 - short oom_score_adj; 126 - 127 - if (tsk->flags & PF_KTHREAD) 128 - continue; 129 - 130 - p = find_lock_task_mm(tsk); 131 - if (!p) 132 - continue; 133 - 134 - if (task_lmk_waiting(p) && 135 - time_before_eq(jiffies, lowmem_deathpending_timeout)) { 136 - task_unlock(p); 137 - rcu_read_unlock(); 138 - return 0; 139 - } 140 - oom_score_adj = p->signal->oom_score_adj; 141 - if (oom_score_adj < min_score_adj) { 142 - task_unlock(p); 143 - continue; 144 - } 145 - tasksize = get_mm_rss(p->mm); 146 - task_unlock(p); 147 - if (tasksize <= 0) 148 - continue; 149 - if (selected) { 150 - if (oom_score_adj < selected_oom_score_adj) 151 - continue; 152 - if (oom_score_adj == selected_oom_score_adj && 153 - tasksize <= selected_tasksize) 154 - continue; 155 - } 156 - selected = p; 157 - selected_tasksize = tasksize; 158 - selected_oom_score_adj = oom_score_adj; 159 - lowmem_print(2, "select '%s' (%d), adj %hd, size %d, to kill\n", 160 - p->comm, p->pid, oom_score_adj, tasksize); 161 - } 162 - if (selected) { 163 - task_lock(selected); 164 - send_sig(SIGKILL, selected, 0); 165 - if (selected->mm) 166 - task_set_lmk_waiting(selected); 167 - task_unlock(selected); 168 - lowmem_print(1, "Killing '%s' (%d), adj %hd,\n" 169 - " to free %ldkB on behalf of '%s' (%d) because\n" 170 - " cache %ldkB is below limit %ldkB for oom_score_adj %hd\n" 171 - " Free memory is %ldkB above reserved\n", 172 - selected->comm, selected->pid, 173 - selected_oom_score_adj, 174 - selected_tasksize * (long)(PAGE_SIZE / 1024), 175 - current->comm, current->pid, 176 - other_file * (long)(PAGE_SIZE / 1024), 177 - minfree * (long)(PAGE_SIZE / 1024), 178 - min_score_adj, 179 - other_free * (long)(PAGE_SIZE / 1024)); 180 - lowmem_deathpending_timeout = jiffies + HZ; 181 - rem += selected_tasksize; 182 - } 183 - 184 - lowmem_print(4, "lowmem_scan %lu, %x, return %lu\n", 185 - sc->nr_to_scan, sc->gfp_mask, rem); 186 - rcu_read_unlock(); 187 - return rem; 188 - } 189 - 190 - static struct shrinker lowmem_shrinker = { 191 - .scan_objects = lowmem_scan, 192 - .count_objects = lowmem_count, 193 - .seeks = DEFAULT_SEEKS * 16 194 - }; 195 - 196 - static int __init lowmem_init(void) 197 - { 198 - register_shrinker(&lowmem_shrinker); 199 - return 0; 200 - } 201 - device_initcall(lowmem_init); 202 - 203 - /* 204 - * not really modular, but the easiest way to keep compat with existing 205 - * bootargs behaviour is to continue using module_param here. 206 - */ 207 - module_param_named(cost, lowmem_shrinker.seeks, int, 0644); 208 - module_param_array_named(adj, lowmem_adj, short, &lowmem_adj_size, 0644); 209 - module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size, 210 - 0644); 211 - module_param_named(debug_level, lowmem_debug_level, uint, 0644); 212 -
-4
include/linux/sched.h
··· 1256 1256 #define PFA_NO_NEW_PRIVS 0 /* May not gain new privileges. */ 1257 1257 #define PFA_SPREAD_PAGE 1 /* Spread page cache over cpuset */ 1258 1258 #define PFA_SPREAD_SLAB 2 /* Spread some slab caches over cpuset */ 1259 - #define PFA_LMK_WAITING 3 /* Lowmemorykiller is waiting */ 1260 1259 1261 1260 1262 1261 #define TASK_PFA_TEST(name, func) \ ··· 1280 1281 TASK_PFA_TEST(SPREAD_SLAB, spread_slab) 1281 1282 TASK_PFA_SET(SPREAD_SLAB, spread_slab) 1282 1283 TASK_PFA_CLEAR(SPREAD_SLAB, spread_slab) 1283 - 1284 - TASK_PFA_TEST(LMK_WAITING, lmk_waiting) 1285 - TASK_PFA_SET(LMK_WAITING, lmk_waiting) 1286 1284 1287 1285 static inline void 1288 1286 tsk_restore_flags(struct task_struct *task, unsigned long orig_flags, unsigned long flags)