mm: An enhancement of OVERCOMMIT_GUESS
Subsystems (4)
PATCH 1/3 mm: An enhancement of OVERCOMMIT_GUESS
Hello Andrew,
Could you apply my patches to your tree?
These patches are an enhancement of OVERCOMMIT_GUESS algorithm in __vm_enough_memory(). The detailed description is in attached patch.
Actually, these are the revised patch which I sent to lkml in the last year.
http://marc.theaimsgroup.com/?l=linux-kernel&m=112993489022427&w=2
I wrote a test kernel module to show the result of the patches. For your information, I also would like to send the module in later e-mail.
Best regards,
Hideo Aoki
---
Hideo Aoki, Hitachi Computer Products (America) Inc.
These patches are an enhancement of OVERCOMMIT_GUESS algorithm in __vm_enough_memory().
- why the kernel needed patching
When the kernel can't allocate anonymous pages in practice, currnet OVERCOMMIT_GUESS could return success. This implementation might be the cause of oom kill in memory pressure situation.
If the Linux runs with page reservation features like /proc/sys/vm/lowmem_reserve_ratio and without swap region, I think the oom kill occurs easily.
- the overall design approach in the patch
When the OVERCOMMET_GUESS algorithm calculates number of free pages, the reserved free pages are regarded as non-free pages.
This change helps to avoid the pitfall that the number of free pages become less than the number which the kernel tries to keep free.
- testing results
I tested the patches using my test kernel module.
If the patches aren't applied to the kernel, __vm_enough_memory() returns success in the situation but autual page allocation is failed.
On the other hand, if the patches are applied to the kernel, memory allocation failure is avoided since __vm_enough_memory() returns failure in the situation.
I checked that on i386 SMP 16GB memory machine. I haven't tested on nommu environment currently.
- changelog
v5:
- updated to 2.6.17-rc1-mm1
- did more strict tests.
- added the enhancement to mm/nommu.c too
v4:
- dealing with pages_high as reserved pages
- updated the code for 2.6.14-rc4-mm1
v3 (private):
- enhanced error handling in __vm_enough_memory
- fixed an issue related calculation of totalreserve_pages
v2 (private):
- fixed error handling bug
- updated test results
- updated the code for 2.6.14-rc2-mm2
This patch adds totalreserve_pages for __vm_enough_memory().
Calculate_totalreserve_pages() checks maximum lowmem_reserve pages and pages_high in each zone. Finally, the function stores the sum of each zone to totalreserve_pages.
The totalreserve_pages is calculated when the VM is initilized. And the variable is updated when /proc/sys/vm/lowmem_reserve_raito or /proc/sys/vm/min_free_kbytes are changed.
---
include/linux/swap.h | 1 + mm/page_alloc.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+)
include/linux/swap.h +1 -0
@@ -155,6 +155,7 @@ extern void swapin_readahead(swp_entry_t/* linux/mm/page_alloc.c */ extern unsigned long totalram_pages;extern unsigned long totalhigh_pages; +extern unsigned long totalreserve_pages;extern long nr_swap_pages;extern unsigned int nr_free_pages (void );extern unsigned int nr_free_pages_pgdat (pg_data_t *pgdat);
mm/page_alloc.c +39 -0
@@ -51,6 +51,7 @@ nodemask_t node_possible_map __read_mostEXPORT_SYMBOL (node_possible_map);unsigned long totalram_pages__read_mostly ;unsigned long totalhigh_pages__read_mostly ; +unsigned long totalreserve_pages__read_mostly ;long nr_swap_pages;int percpu_pagelist_fraction;
@@ -2548,6 +2549,38 @@ void __init page_alloc_init(void) }/* +* calculate_totalreserve_pages - called when sysctl_lower_zone_reserve_ratio +* or min_free_kbytes changes. +*/ +static void calculate_totalreserve_pages (void ) +{ +struct pglist_data *pgdat; +unsigned long reserve_pages =0 ; +int i, j; + +for_each_online_pgdat (pgdat) { +for (i =0 ; i <MAX_NR_ZONES ; i++) { +struct zone *zone = pgdat->node_zones + i; +unsigned long max =0 ; + +/* Find valid and maximum lowmem_reserve in the zone */ +for (j = i; j <MAX_NR_ZONES ; j++) { +if (zone->lowmem_reserve[j] > max) + max = zone->lowmem_reserve[j]; + } + +/* we treat pages_high as reserved pages. */ + max += zone->pages_high; + +if (max > zone->present_pages) + max = zone->present_pages; + reserve_pages += max; + } + } + totalreserve_pages = reserve_pages; +} + +/* * setup_per_zone_lowmem_reserve - called whenever * sysctl_lower_zone_reserve_ratio changes. Ensures that each zone * has a correct pages reserved value, so an adequate number of
@@ -2578,6 +2611,9 @@ static void setup_per_zone_lowmem_reserv } } } + +/* update totalreserve_pages */ +calculate_totalreserve_pages (); }/*
@@ -2632,6 +2668,9 @@ void setup_per_zone_pages_min(void) zone->pages_high = zone->pages_min + tmp /2 ;spin_unlock_irqrestore (&zone->lru_lock, flags); } + +/* update totalreserve_pages */ +calculate_totalreserve_pages (); }/*
A test kernel module of OVERCOMMIT_GUESS
Hello Andrew,
This is a kernel module patch which I developed to test my patches.
The module makes a kind of memory pressure situation. After that, the module tests if the OVERCOMMIT_GUESS detects overcommit.
The module has "mode" option. If you specify "mode=1", the module tries to allocate pages in the test phase.
Here is the test result when I did "mode=1" test on my machine.
* 2.6.17-rc1-mm1
kernel: Test MAY be <failed>.
kernel: allocation failed: out of vmalloc space - use vmalloc=<size> to increase size.
kernel: allocation failed: out of vmalloc space - use vmalloc=<size> to increase size.
kernel: Test SURELY was <FAILED>.
* 2.6.17-rc1-mm1 + my patches
kernel: Test was <PASSED>.
Unfortunately, this kernel module needs another kernel patch. I will send it in later e-mail.
Please note that I don't intend to propose to apply the module to kernel tree.
Best regards,
Hideo Aoki
---
Hideo Aoki, Hitachi Computer Products (America) Inc.
A kernel module to test OVERCOMMIT_GUESS.
lib/Kconfig.debug | 11 + mm/Makefile | 1 mm/test_overcommit.c | 515 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 527 insertions(+)
lib/Kconfig.debug +11 -0
@@ -282,6 +282,17 @@ config RCU_TORTURE_TEST Say M if you want the RCU torture tests to build as a module. Say N if you are unsure. +config OVERCOMMIT_GUESS_TEST + tristate "An overcommit guess testing module" + depends on DEBUG_KERNEL && X86 + default n + help + This option provides a kernel module that can test OVERCOMMIT_GUESS + in __vm_enough_memory(). + + You should say N or M here. Say M if you want to build the module. + Say N if you are unsure. + config WANT_EXTRA_DEBUG_INFORMATION bool select DEBUG_INFO
mm/Makefile +1 -0
@@ -24,4 +24,5 @@ obj-$(CONFIG_SLAB) += slab.o obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o obj-$(CONFIG_FS_XIP) += filemap_xip.o obj-$(CONFIG_MIGRATION) += migrate.o +obj-$(CONFIG_OVERCOMMIT_GUESS_TEST) += test_overcommit.o
mm/test_overcommit.c +515 -0
515 lines not on this page · raw message
A patch for test_overcommit module
In reply to Hideo AOKIThe test module needs this kernel patch.
I don't intend to propose to apply this patch to kernel tree.
---
Hideo Aoki, Hitachi Computer Products (America) Inc.
This patch exports the symbols which a kernel module has to refer.
include/linux/mman.h | 1 + mm/page_alloc.c | 1 + mm/slab.c | 1 + mm/swap.c | 1 + 4 files changed, 4 insertions(+)
include/linux/mman.h +1 -0
@@ -24,6 +24,7 @@ static inline void vm_acct_memory(long p {atomic_add (pages, &vm_committed_space); } +EXPORT_SYMBOL (vm_acct_memory);#endif static inline void vm_unacct_memory (long pages)
mm/page_alloc.c +1 -0
@@ -52,6 +52,7 @@ EXPORT_SYMBOL(node_possible_map);unsigned long totalram_pages__read_mostly ;unsigned long totalhigh_pages__read_mostly ;long nr_swap_pages; +EXPORT_SYMBOL (nr_swap_pages);int percpu_pagelist_fraction;static void __free_pages_ok (struct page *page,unsigned int order);
mm/slab.c +1 -0
@@ -692,6 +692,7 @@ static struct list_head cache_chain;* SLAB_RECLAIM_ACCOUNT turns this on per-slab */ atomic_t slab_reclaim_pages; +EXPORT_SYMBOL (slab_reclaim_pages);/* * chicken and egg problem: delay the per-cpu array allocation
mm/swap.c +1 -0
@@ -499,6 +499,7 @@ void vm_acct_memory(long pages) }preempt_enable (); } +EXPORT_SYMBOL (vm_acct_memory);#ifdef CONFIG_HOTPLUG_CPU
Hi, AOKI-san
Quoted 7 lines · On Wed, 05 Apr 2006 19:47:27 -0400 Hideo AOKI <[email protected]> wrote:
Hello Andrew,
Could you apply my patches to your tree?
These patches are an enhancement of
OVERCOMMIT_GUESSalgorithm in__vm_enough_memory(). The detailed description is in attached patch.
I think adding a function like this is more simple way. (call this istead of nr_free_pages().)
==
int nr_available_memory()
{
unsigned long sum = 0;
for_each_zone(zone) {
if (zone->free_pages > zone->pages_high)
sum += zone->free_pages - zone->pages_high;
}
return sum;
}==
BTW, vm_enough_memory() doesn't eat cpuset information ?
-Kame
Hi Kamezawa-san,
Thank you for your comments.
Quoted 24 lines · KAMEZAWA Hiroyuki
Hi, AOKI-san
Quoted 6 lines · On Wed, 05 Apr 2006 19:47:27 -0400 Hideo AOKI <[email protected]> wrote:
Hello Andrew,
Could you apply my patches to your tree?
These patches are an enhancement of
OVERCOMMIT_GUESSalgorithm in__vm_enough_memory(). The detailed description is in attached patch.I think adding a function like this is more simple way. (call this istead of
nr_free_pages().)
==int nr_available_memory() { unsigned long sum = 0; for_each_zone(zone) { if (zone->free_pages > zone->pages_high) sum += zone->free_pages - zone->pages_high; } return sum; }
Quoted 1 line
==
I like your idea. But, in the function, I think we need to care lowmem_reserve too.
Since __vm_enough_memory() doesn't know zone and cpuset information, we have to guess proper value of lowmem_reserve in each zone like I did in calculate_totalreserve_pages() in my patch. Do you think that we can do this calculation every time?
If it is good enough, I'll make revised patch.
Quoted 1 line
BTW,
vm_enough_memory()doesn't eat cpuset information ?
I think this is another point which we should improve.
Best regards,
Hideo Aoki
---
Hideo Aoki, Hitachi Computer Products (America) Inc.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 9 lines · On Thu, 06 Apr 2006 03:20:10 -0400 Hideo AOKI <[email protected]> wrote:
Hi Kamezawa-san,
Thank you for your comments.
Quoted 1 line · KAMEZAWA Hiroyuki
Hi, AOKI-san
I like your idea. But, in the function, I think we need to care
lowmem_reservetoo.
Ah, I see.
Quoted 7 lines
Since
__vm_enough_memory()doesn't know zone and cpuset information, we have to guess proper value oflowmem_reservein each zone like I did incalculate_totalreserve_pages()in my patch. Do you think that we can do this calculation every time?If it is good enough, I'll make revised patch.
I just thought to show "how to calculate" in unified way is better. But if things goes ugly, please ignore my comment.
Do you have a detailed comparison of test result with and without this patch ? I'm interested in.
I'm sorry if I missed your post of result.
Cheers!
-Kame
Hi Kamezawa-san,
Thank you for your quick response. And sorry for slow response.
Quoted 11 lines · KAMEZAWA Hiroyuki
Quoted 7 lines · Hideo AOKI
Since
__vm_enough_memory()doesn't know zone and cpuset information, we have to guess proper value oflowmem_reservein each zone like I did incalculate_totalreserve_pages()in my patch. Do you think that we can do this calculation every time?If it is good enough, I'll make revised patch.
I just thought to show "how to calculate" in unified way is better.
I got it.
Quoted 1 line
Do you have a detailed comparison of test result with and without this patch ?
Yes. I have test logs and attach them to this e-mail.
The logs are verbose output of my test kernel module which I already sent to lkml.
http://marc.theaimsgroup.com/?l=linux-kernel&m=114428121522349&w=2
Test machine was i386 4GB memory PC. I didn't use swap region.
Let me explain a few things about the log.
* 2.6.17-rc1-mm1
HIGH: <active 18220><inactive 12278><free 1419><sum 31917><present 622220>
NORMAL: <active 1618><inactive 2293><free 1397><sum 5308><present 225280>
The test module consumes free pages until the number of free pages is less than pages_high.
<buf 3916><cache 31785><slab reclaim 1550><swap 0> <+ 1> <target 33336>
This line shows the status of memory just before the module calls __vm_enough_memory(). Meaning of each item is below.
buf: bufferram
cache: page cache
slab reclaim: slab_reclaim_pages
swap: nr_swap_pages
+: margin
target: the number of pages to ask __vm_enough_memory()Test MAY be <failed>.
This line shows __vm_enough_memory() returned success.
Please let me know if you have any questions and suggestions.
Regards,
Hideo Aoki
---
Hideo Aoki, Hitachi Computer Products (America) Inc.
* 2.6.17-rc1-mm1
Apr 6 20:33:33 dhcp1 kernel: Test module was loaded. <mode 1> Apr 6 20:33:33 dhcp1 kernel: init ...<3>done Apr 6 20:33:33 dhcp1 kernel: Apr 6 20:33:33 dhcp1 kernel: HIGH: <active 18238><inactive 12278><free 590698><sum 621214><present 622220> Apr 6 20:33:34 dhcp1 kernel: HighMem <target 589272>, <3> Apr 6 20:33:34 dhcp1 kernel: HIGH: <active 18220><inactive 12278><free 1512><sum 32010><present 622220> Apr 6 20:33:34 dhcp1 kernel: Apr 6 20:33:34 dhcp1 kernel: HIGH: <active 18220><inactive 12278><free 1512><sum 32010><present 622220> Apr 6 20:33:34 dhcp1 kernel: HighMem <target 86>, <3> Apr 6 20:33:34 dhcp1 kernel: HIGH: <active 18220><inactive 12278><free 1419><sum 31917><present 622220> Apr 6 20:33:34 dhcp1 kernel: already satisfied Apr 6 20:33:34 dhcp1 kernel: Apr 6 20:33:34 dhcp1 kernel: NORMAL: <active 1618><inactive 2277><free 205532><sum 209427><present 225280> Apr 6 20:33:34 dhcp1 kernel: Normal <target 204124>, <3> Apr 6 20:33:34 dhcp1 kernel: NORMAL: <active 1618><inactive 2291><free 1490><sum 5399><present 225280> Apr 6 20:33:34 dhcp1 kernel: Apr 6 20:33:34 dhcp1 kernel: NORMAL: <active 1618><inactive 2293><free 1490><sum 5401><present 225280> Apr 6 20:33:34 dhcp1 kernel: Normal <target 82>, <3> Apr 6 20:33:34 dhcp1 kernel: NORMAL: <active 1618><inactive 2293><free 1428><sum 5339><present 225280> Apr 6 20:33:34 dhcp1 kernel: Apr 6 20:33:34 dhcp1 kernel: NORMAL: <active 1618><inactive 2293><free 1428><sum 5339><present 225280> Apr 6 20:33:34 dhcp1 kernel: Normal <target 20>, <3> Apr 6 20:33:34 dhcp1 kernel: NORMAL: <active 1618><inactive 2293><free 1397><sum 5308><present 225280> Apr 6 20:33:34 dhcp1 kernel: already satisfied Apr 6 20:33:34 dhcp1 kernel: concrete test ... Apr 6 20:33:34 dhcp1 kernel: <buf 3916><cache 31785><slab reclaim 1550><swap 0> <+ 1> <target 33336> Apr 6 20:33:34 dhcp1 kernel: Test MAY be <failed>. Apr 6 20:33:34 dhcp1 kernel: allocation failed: out of vmalloc space - use vmalloc=<size> to increase size. Apr 6 20:33:35 dhcp1 kernel: allocation failed: out of vmalloc space - use vmalloc=<size> to increase size. Apr 6 20:33:35 dhcp1 kernel: Test SURELY was <FAILED>. Apr 6 20:33:35 dhcp1 kernel: concrete test ...done.
* 2.6.17-rc1-mm1 + patches
Apr 6 20:56:36 dhcp1 kernel: Test module was loaded. <mode 1> Apr 6 20:56:36 dhcp1 kernel: init ...<3>done Apr 6 20:56:36 dhcp1 kernel: Apr 6 20:56:36 dhcp1 kernel: HIGH: <active 17074><inactive 13427><free 590727><sum 621228><present 622220> Apr 6 20:56:36 dhcp1 kernel: HighMem <target 589301>, <3> Apr 6 20:56:36 dhcp1 kernel: HIGH: <active 17074><inactive 13427><free 1479><sum 31980><present 622220> Apr 6 20:56:36 dhcp1 kernel: Apr 6 20:56:36 dhcp1 kernel: HIGH: <active 17074><inactive 13427><free 1479><sum 31980><present 622220> Apr 6 20:56:36 dhcp1 kernel: HighMem <target 53>, <3> Apr 6 20:56:36 dhcp1 kernel: HIGH: <active 17074><inactive 13427><free 1417><sum 31918><present 622220> Apr 6 20:56:36 dhcp1 kernel: already satisfied Apr 6 20:56:36 dhcp1 kernel: Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2248><free 205669><sum 209543><present 225280> Apr 6 20:56:36 dhcp1 kernel: Normal <target 204261>, <3> Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2262><free 1441><sum 5329><present 225280> Apr 6 20:56:36 dhcp1 kernel: Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2264><free 1441><sum 5331><present 225280> Apr 6 20:56:36 dhcp1 kernel: Normal <target 33>, <3> Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2264><free 1410><sum 5300><present 225280> Apr 6 20:56:36 dhcp1 kernel: Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2264><free 1410><sum 5300><present 225280> Apr 6 20:56:36 dhcp1 kernel: Normal <target 2>, <3> Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2265><free 1410><sum 5301><present 225280> Apr 6 20:56:36 dhcp1 kernel: Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2265><free 1410><sum 5301><present 225280> Apr 6 20:56:36 dhcp1 kernel: Normal <target 2>, <3> Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2265><free 1410><sum 5301><present 225280> Apr 6 20:56:36 dhcp1 kernel: Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2265><free 1410><sum 5301><present 225280> Apr 6 20:56:36 dhcp1 kernel: Normal <target 2>, <3> Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2265><free 1410><sum 5301><present 225280> Apr 6 20:56:36 dhcp1 kernel: Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2265><free 1410><sum 5301><present 225280> Apr 6 20:56:36 dhcp1 kernel: Normal <target 2>, <3> Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2265><free 1410><sum 5301><present 225280> Apr 6 20:56:36 dhcp1 kernel: Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2265><free 1410><sum 5301><present 225280> Apr 6 20:56:36 dhcp1 kernel: Normal <target 2>, <3> Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2265><free 1410><sum 5301><present 225280> Apr 6 20:56:36 dhcp1 kernel: Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2265><free 1410><sum 5301><present 225280> Apr 6 20:56:36 dhcp1 kernel: Normal <target 2>, <3> Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2265><free 1410><sum 5301><present 225280> Apr 6 20:56:36 dhcp1 kernel: Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2265><free 1410><sum 5301><present 225280> Apr 6 20:56:36 dhcp1 kernel: Normal <target 2>, <3> Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2265><free 1410><sum 5301><present 225280> Apr 6 20:56:36 dhcp1 kernel: Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2265><free 1410><sum 5301><present 225280> Apr 6 20:56:36 dhcp1 kernel: Normal <target 2>, <3> Apr 6 20:56:36 dhcp1 kernel: NORMAL: <active 1626><inactive 2265><free 1379><sum 5270><present 225280> Apr 6 20:56:36 dhcp1 kernel: already satisfied Apr 6 20:56:36 dhcp1 kernel: concrete test ... Apr 6 20:56:36 dhcp1 kernel: <buf 3902><cache 31720><slab reclaim 1538><swap 0> <+ 1> <target 33259> Apr 6 20:56:36 dhcp1 kernel: Test was <PASSED>. Apr 6 20:56:36 dhcp1 kernel: concrete test ...done. Apr 6 20:56:48 dhcp1 kernel: Unloading module ...