staging: lowmemorykiller: change lowmem_adj to lowmem_score_adj
PATCH 1/3 staging: lowmemorykiller: change lowmem_adj to lowmem_score_adj
om_adj is deprecated, and in lowmemorykiller module, we use score adj to do the comparing.
---
oom_score_adj = p->signal->oom_score_adj;
if (oom_score_adj < min_score_adj) {
task_unlock(p);
continue;
}---
This patch makes the variable name consistent with the usage.
--- drivers/staging/android/lowmemorykiller.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-)
drivers/staging/android/lowmemorykiller.c +15 -14
@@ -7,9 +7,9 @@* /sys/module/lowmemorykiller/parameters/minfree. Both files take a comma * separated list of numbers in ascending order. * -* For example, write "0,8" to /sys/module/lowmemorykiller/parameters/adj and -* "1024,4096" to /sys/module/lowmemorykiller/parameters/minfree to kill -* processes with a oom_score_adj value of 8 or higher when the free memory +* For example, write "0,470" to /sys/module/lowmemorykiller/parameters/score_adj +* and "1024,4096" to /sys/module/lowmemorykiller/parameters/minfree to kill +* processes with a oom_score_adj value of 470 or higher when the free memory * drops below 4096 pages and kill processes with a oom_score_adj value of 0 or * higher when the free memory drops below 1024 pages. *
@@ -44,14 +44,15 @@#include <linux/notifier.h> static u32 lowmem_debug_level =1 ; -static short lowmem_adj[6 ] = { + +static short lowmem_score_adj[6 ] = {0 , -1 , -6 , -12 , +58 , +352 , +705 , }; -static int lowmem_adj_size =4 ; +static int lowmem_score_adj_size =4 ;static int lowmem_minfree[6 ] = {3 *512 ,/* 6MB */ 2 *1024 ,/* 8MB */
@@ -89,20 +90,20 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)int minfree =0 ;int selected_tasksize =0 ;short selected_oom_score_adj; -int array_size =ARRAY_SIZE (lowmem_adj); +int array_size =ARRAY_SIZE (lowmem_score_adj);int other_free =global_page_state (NR_FREE_PAGES ) - totalreserve_pages;int other_file =global_page_state (NR_FILE_PAGES ) -global_page_state (NR_SHMEM ) -total_swapcache_pages (); -if (lowmem_adj_size < array_size) - array_size = lowmem_adj_size; +if (lowmem_score_adj_size < array_size) + array_size = lowmem_score_adj_size;if (lowmem_minfree_size < array_size) array_size = lowmem_minfree_size;for (i =0 ; i < array_size; i++) { minfree = lowmem_minfree[i];if (other_free < minfree && other_file < minfree) { - min_score_adj = lowmem_adj[i]; + min_score_adj = lowmem_score_adj[i];break ; } }
@@ -165,7 +166,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)if (selected->mm)task_set_lmk_waiting (selected);task_unlock (selected); - lowmem_print(1, "Killing '%s' (%d), adj %hd,\n" + lowmem_print(1, "Killing '%s' (%d), score adj %hd,\n" " to free %ldkB on behalf of '%s' (%d) because\n" " cache %ldkB is below limit %ldkB for oom_score_adj %hd\n" " Free memory is %ldkB above reserved\n",
@@ -205,7 +206,7 @@ device_initcall(lowmem_init);* bootargs behaviour is to continue using module_param here. */ module_param_named (cost, lowmem_shrinker.seeks, int,S_IRUGO |S_IWUSR ); -module_param_array_named (adj, lowmem_adj, short, &lowmem_adj_size, +module_param_array_named (score_adj, lowmem_score_adj, short, &lowmem_score_adj_size,S_IRUGO |S_IWUSR );module_param_array_named (minfree, lowmem_minfree, uint, &lowmem_minfree_size,S_IRUGO |S_IWUSR );
Signature · 1 line
1.9.1
PATCH 2/3 staging: lowmemorykiller: count anon pages only when we have swap devices
lowmem_count() should only count anon pages when we have swap device.
--- drivers/staging/android/lowmemorykiller.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/staging/android/lowmemorykiller.c +8 -4
@@ -73,10 +73,14 @@ static unsigned long lowmem_deathpending_timeout;static unsigned long lowmem_count (struct shrinker *s,struct shrink_control *sc) { -return global_page_state (NR_ACTIVE_ANON ) + -global_page_state (NR_ACTIVE_FILE ) + -global_page_state (NR_INACTIVE_ANON ) + -global_page_state (NR_INACTIVE_FILE ); +unsigned long freeable =global_page_state (NR_ACTIVE_FILE ) + +global_page_state (NR_INACTIVE_FILE ); + +if (get_nr_swap_pages () >0 ) + freeable +=global_page_state (NR_ACTIVE_ANON ) + +global_page_state (NR_INACTIVE_ANON ); + +return freeable; }static unsigned long lowmem_scan (struct shrinker *s,struct shrink_control *sc)
Signature · 1 line
1.9.1
Re: [PATCH 2/3] staging: lowmemorykiller: count anon pages only when we have swap devices
Quoted 2 lines · Ganesh Mahendran
lowmem_count()should only count anon pages when we have swap device.
Why?
Quoted 18 lines
Signed-off-by Ganesh Mahendran <[email protected]>--- drivers/staging/android/lowmemorykiller.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)drivers/staging/android/lowmemorykiller.c +1
-4@@ -73,10 +73,14 @@ static unsigned long lowmem_deathpending_timeout;static unsigned long lowmem_count (struct shrinker *s,struct shrink_control *sc) { -return global_page_state (NR_ACTIVE_ANON ) + -global_page_state (NR_ACTIVE_FILE ) + -global_page_state (NR_INACTIVE_ANON ) + -global_page_state (NR_INACTIVE_FILE ); + unsigned long freeable = global_page_state(NR_ACTIVE_FILE) +
drivers/staging/android/lowmemorykiller.c static unsigned long lowmem_deathpending_timeout; · line 86
Quoted 10 lines
drivers/staging/android/lowmemorykiller.c +7
-0+global_page_state (NR_INACTIVE_FILE ); + +if (get_nr_swap_pages () >0 ) + freeable +=global_page_state (NR_ACTIVE_ANON ) + +global_page_state (NR_INACTIVE_ANON ); + +return freeable; }static unsigned long lowmem_scan (struct shrinker *s,struct shrink_control *sc)
Shouldn't this be advertising the amount of memory that is freeable by killing the process with the highest priority oom_score_adj? It's not legitimate to say it can free all anon and file memory if nothing is oom killable, so this function is wrong both originally and with your patched version.
Re: [PATCH 2/3] staging: lowmemorykiller: count anon pages only when we have swap devices
Hi, David:
Quoted 6 lines · David Rientjes
Quoted 2 lines · Ganesh Mahendran
lowmem_count()should only count anon pages when we have swap device.Why?
I make a mistake. I thought lowmem_count will return the shrinkalbe page of a process.
Quoted 28 lines
Quoted 28 lines
Signed-off-by Ganesh Mahendran <[email protected]>--- drivers/staging/android/lowmemorykiller.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)drivers/staging/android/lowmemorykiller.c +8
-4@@ -73,10 +73,14 @@ static unsigned long lowmem_deathpending_timeout;static unsigned long lowmem_count (struct shrinker *s,struct shrink_control *sc) { -return global_page_state (NR_ACTIVE_ANON ) + -global_page_state (NR_ACTIVE_FILE ) + -global_page_state (NR_INACTIVE_ANON ) + -global_page_state (NR_INACTIVE_FILE ); +unsigned long freeable =global_page_state (NR_ACTIVE_FILE ) + +global_page_state (NR_INACTIVE_FILE ); + +if (get_nr_swap_pages () >0 ) + freeable +=global_page_state (NR_ACTIVE_ANON ) + +global_page_state (NR_INACTIVE_ANON ); + +return freeable; }
Quoted 7 lines
drivers/staging/android/lowmemorykiller.c static unsigned long lowmem_deathpending_timeout; · line 86
Quoted 1 line
drivers/staging/android/lowmemorykiller.c +0
-0static unsigned long lowmem_scan (struct shrinker *s,struct shrink_control *sc)Shouldn't this be advertising the amount of memory that is freeable by killing the process with the highest priority
oom_score_adj? It's not legitimate to say it can free all anon and file memory if nothing is oom killable, so this function is wrong both originally and with your patched version.
Yes, so should we just simply return 1 to make do_shrink_slab() go ahead? Then lowmem_scan() will do the real job to scan all the process.
Thanks.
Re: [PATCH 2/3] staging: lowmemorykiller: count anon pages only when we have swap devices
On (06/22/16 11:27), Ganesh Mahendran wrote:
[..]
Quoted 35 lines
Quoted 27 lines
Quoted 27 lines
Signed-off-by Ganesh Mahendran <[email protected]>--- drivers/staging/android/lowmemorykiller.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)drivers/staging/android/lowmemorykiller.c +8
-4@@ -73,10 +73,14 @@ static unsigned long lowmem_deathpending_timeout;static unsigned long lowmem_count (struct shrinker *s,struct shrink_control *sc) { -return global_page_state (NR_ACTIVE_ANON ) + -global_page_state (NR_ACTIVE_FILE ) + -global_page_state (NR_INACTIVE_ANON ) + -global_page_state (NR_INACTIVE_FILE ); +unsigned long freeable =global_page_state (NR_ACTIVE_FILE ) + +global_page_state (NR_INACTIVE_FILE ); + +if (get_nr_swap_pages () >0 ) + freeable +=global_page_state (NR_ACTIVE_ANON ) + +global_page_state (NR_INACTIVE_ANON ); + +return freeable; }Quoted 7 lines
drivers/staging/android/lowmemorykiller.c static unsigned long lowmem_deathpending_timeout; · line 86
Quoted 1 line
drivers/staging/android/lowmemorykiller.c +0
-0static unsigned long lowmem_scan (struct shrinker *s,struct shrink_control *sc)Shouldn't this be advertising the amount of memory that is freeable by killing the process with the highest priority
oom_score_adj? It's not legitimate to say it can free all anon and file memory if nothing is oom killable, so this function is wrong both originally and with your patched version.
Quoted 2 lines
Yes, so should we just simply return 1 to make
do_shrink_slab()go ahead? Thenlowmem_scan()will do the real job to scan all the process.
hm, looking at ->scan (lowmem_scan) shouldn't it return SHRINK_STOP when it has nothing to free instead of 0?
-ss
Re: [PATCH 2/3] staging: lowmemorykiller: count anon pages only when we have swap devices
2016-06-23 16:42 GMT+08:00 Sergey Senozhatsky
<[email protected]>:
Quoted 37 lines · Ganesh Mahendran
[..]
Quoted 35 lines
Quoted 34 lines
Quoted 18 lines
Signed-off-by Ganesh Mahendran <[email protected]>--- drivers/staging/android/lowmemorykiller.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)drivers/staging/android/lowmemorykiller.c +1
-4@@ -73,10 +73,14 @@ static unsigned long lowmem_deathpending_timeout;static unsigned long lowmem_count (struct shrinker *s,struct shrink_control *sc) { -return global_page_state (NR_ACTIVE_ANON ) + -global_page_state (NR_ACTIVE_FILE ) + -global_page_state (NR_INACTIVE_ANON ) + -global_page_state (NR_INACTIVE_FILE ); + unsigned long freeable = global_page_state(NR_ACTIVE_FILE) +drivers/staging/android/lowmemorykiller.c static unsigned long lowmem_deathpending_timeout; · line 86
Quoted 10 lines
drivers/staging/android/lowmemorykiller.c +7
-0+global_page_state (NR_INACTIVE_FILE ); + +if (get_nr_swap_pages () >0 ) + freeable +=global_page_state (NR_ACTIVE_ANON ) + +global_page_state (NR_INACTIVE_ANON ); + +return freeable; }static unsigned long lowmem_scan (struct shrinker *s,struct shrink_control *sc)Shouldn't this be advertising the amount of memory that is freeable by killing the process with the highest priority
oom_score_adj? It's not legitimate to say it can free all anon and file memory if nothing is oom killable, so this function is wrong both originally and with your patched version.
Quoted 5 lines
Quoted 2 lines
Yes, so should we just simply return 1 to make
do_shrink_slab()go ahead? Thenlowmem_scan()will do the real job to scan all the process.hm, looking at ->scan (
lowmem_scan) shouldn't it returnSHRINK_STOPwhen it has nothing to free instead of 0?
Yes, you are right. It should return SHRINK_STOP.
Quoted 2 lines
-ssPATCH 3/3 staging: lowmemorykiller: select the task with maximum rss to kill
In reply to Ganesh MahendranCurrent task selecting logic in LMK does not fully aware of the memory pressure. It may select the task with maximum score adj, but with least tasksize.
For example, if min_score_adj is 200, and there are 2 tasks in system:
task a: score adj 500, tasksize 200M
task b: score adj 1000, tasksize 1M
Current LMK logic will select *task b*. But now the system already have much memory pressure.
We should select the task with maximum task from all the tasks which score adj >= min_score_adj.
--- drivers/staging/android/lowmemorykiller.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-)
drivers/staging/android/lowmemorykiller.c +12 -13
@@ -122,8 +122,6 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)return 0 ; } - selected_oom_score_adj = min_score_adj; -rcu_read_lock ();for_each_process (tsk) {struct task_struct *p;
@@ -151,18 +149,19 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)task_unlock (p);if (tasksize <=0 )continue ; -if (selected) { -if (oom_score_adj < selected_oom_score_adj) -continue ; -if (oom_score_adj == selected_oom_score_adj && - tasksize <= selected_tasksize) -continue ; + +/* +* From the processes which score adj >= min_score_adj, +* we select the one with the maximum tasksize. +*/ +if (selected_tasksize < tasksize) { + selected = p; + selected_tasksize = tasksize; + selected_oom_score_adj = oom_score_adj; + +lowmem_print (2 ,"select '%s' (%d), adj %hd, size %d, to kill\n" , + p->comm, p->pid, oom_score_adj, tasksize); } - selected = p; - selected_tasksize = tasksize; - selected_oom_score_adj = oom_score_adj; -lowmem_print (2 ,"select '%s' (%d), adj %hd, size %d, to kill\n" , - p->comm, p->pid, oom_score_adj, tasksize); }if (selected) {task_lock (selected);
Signature · 1 line
1.9.1
Re: [PATCH 3/3] staging: lowmemorykiller: select the task with maximum rss to kill
Quoted 4 lines · Ganesh Mahendran
Current task selecting logic in LMK does not fully aware of the memory pressure. It may select the task with maximum score adj, but with least tasksize.
Quoted 9 lines
For example, if
min_score_adjis 200, and there are 2 tasks in system:
task a: score adj 500, tasksize 200M
task b: score adj 1000, tasksize 1M
Current LMK logic will select *task b*. But now the system already have much memory pressure.We should select the task with maximum task from all the tasks which score adj >=
min_score_adj.
Unfortunately, I'm not sure that we can get away with this although I agree that it is a better result (kill a large process, avoid lowmem or oom for longer).
It changes the kill order for systems that have already fine-tuned their oom_score_adj settings and can regress because of this change. If systems really want task b to be killed above, this breaks and they have no immediate way of fixing it.
Re: [PATCH 3/3] staging: lowmemorykiller: select the task with maximum rss to kill
Hi, David:
Quoted 12 lines · David Rientjes
Quoted 10 lines · Ganesh Mahendran
Current task selecting logic in LMK does not fully aware of the memory pressure. It may select the task with maximum score adj, but with least tasksize.
For example, if
min_score_adjis 200, and there are 2 tasks in system:
task a: score adj 500, tasksize 200M
task b: score adj 1000, tasksize 1M
Current LMK logic will select *task b*. But now the system already have much memory pressure.
Quoted 7 lines
Quoted 3 lines
We should select the task with maximum task from all the tasks which score adj >=
min_score_adj.Unfortunately, I'm not sure that we can get away with this although I agree that it is a better result (kill a large process, avoid lowmem or oom for longer).
Yes, from our testing with this patch applied, system works more smoothly, and user have better experience.
Quoted 5 lines
It changes the kill order for systems that have already fine-tuned their
oom_score_adjsettings and can regress because of this change. If systems really want task b to be killed above, this breaks and they have no immediate way of fixing it.
I think the processes with score_adj >= min_score_adj are all acceptable if we kill them. In android products, LMK does the main job to free memory when system is hard to shrink file/anon pages. If LMK does not free enough memory, the system will be very slow before OOM is triggered. During this period, user will have bad experience.
So LMK need to work effectivly to let system running smoothly, as user experience is very important for android system.
Thanks.
Quoted 12 lines · Ganesh Mahendran
om_adjis deprecated, and in lowmemorykiller module, we use score adj to do the comparing.
---oom_score_adj = p->signal->oom_score_adj; if (oom_score_adj < min_score_adj) { task_unlock(p); continue; }---
This patch makes the variable name consistent with the usage.
Umm, I don't think you can just remove a parameter to a module and replace it with something that has a different unit and not think that userspace will break as a result.
Hi, David:
Quoted 12 lines · David Rientjes
Quoted 10 lines · Ganesh Mahendran
om_adjis deprecated, and in lowmemorykiller module, we use score adj to do the comparing.
---oom_score_adj = p->signal->oom_score_adj; if (oom_score_adj < min_score_adj) { task_unlock(p); continue; }---
Quoted 6 lines
Quoted 2 lines
This patch makes the variable name consistent with the usage.
Umm, I don't think you can just remove a parameter to a module and replace it with something that has a different unit and not think that userspace will break as a result.
You are right, this change will break android AMS which will set the LMK watermark via /sys/module/lowmemorykiller/parameters/adj.
Please help to review below change. Only make the varialbe name consistent with the variable usage.
------
Quoted 1 line
From
394872fc1993a04ae471b10d7f971d4544812ec4Mon Sep 17 00:00:00 2001
From: Ganesh Mahendran <[email protected]>
Date: Wed, 22 Jun 2016 10:53:13 +0800
Subject: [PATCH v2] staging: lowmemorykiller: make variable name consistent with
the varialbe usage
LMK use oom_score_adj to do the comparing. But the variable name is *_adj. This patch makes thevarialbe name consistent with the varialb usage to avoid ambiguity.
*_adj -> *_score_adj
---
v2:
do not change user API - David
--- drivers/staging/android/lowmemorykiller.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-)
drivers/staging/android/lowmemorykiller.c +12 -11
@@ -44,14 +44,15 @@#include <linux/notifier.h> static u32 lowmem_debug_level =1 ; -static short lowmem_adj[6 ] = { + +static short lowmem_score_adj[6 ] = {0 , -1 , -6 , -12 , +58 , +352 , +705 , }; -static int lowmem_adj_size =4 ; +static int lowmem_score_adj_size =4 ;static int lowmem_minfree[6 ] = {3 *512 ,/* 6MB */ 2 *1024 ,/* 8MB */
@@ -89,20 +90,20 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)int minfree =0 ;int selected_tasksize =0 ;short selected_oom_score_adj; -int array_size =ARRAY_SIZE (lowmem_adj); +int array_size =ARRAY_SIZE (lowmem_score_adj);int other_free =global_page_state (NR_FREE_PAGES ) - totalreserve_pages;int other_file =global_page_state (NR_FILE_PAGES ) -global_page_state (NR_SHMEM ) -total_swapcache_pages (); -if (lowmem_adj_size < array_size) - array_size = lowmem_adj_size; +if (lowmem_score_adj_size < array_size) + array_size = lowmem_score_adj_size;if (lowmem_minfree_size < array_size) array_size = lowmem_minfree_size;for (i =0 ; i < array_size; i++) { minfree = lowmem_minfree[i];if (other_free < minfree && other_file < minfree) { - min_score_adj = lowmem_adj[i]; + min_score_adj = lowmem_score_adj[i];break ; } }
@@ -165,7 +166,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)if (selected->mm)task_set_lmk_waiting (selected);task_unlock (selected); - lowmem_print(1, "Killing '%s' (%d), adj %hd,\n" + lowmem_print(1, "Killing '%s' (%d), score adj %hd,\n" " to free %ldkB on behalf of '%s' (%d) because\n" " cache %ldkB is below limit %ldkB for oom_score_adj %hd\n" " Free memory is %ldkB above reserved\n",
@@ -205,7 +206,7 @@ device_initcall(lowmem_init);* bootargs behaviour is to continue using module_param here. */ module_param_named (cost, lowmem_shrinker.seeks, int,S_IRUGO |S_IWUSR ); -module_param_array_named (adj, lowmem_adj, short, &lowmem_adj_size, +module_param_array_named (adj, lowmem_score_adj, short, &lowmem_score_adj_size,S_IRUGO |S_IWUSR );module_param_array_named (minfree, lowmem_minfree, uint, &lowmem_minfree_size,S_IRUGO |S_IWUSR );
Signature · 1 line
1.9.1