[PATCH 2.6.14-rc1-mm1] mm: OVERCOMMIT_GUESS considers lowmem_reserve_ratio.

From: Hideo AOKI
Date: Wed Sep 21 2005 - 14:07:42 EST


Hello,

Attached patch is an enhancement to avoid overcommitting anonymous pages. Please review.

BTW, does anyone know any good tools to test overcommitted situation?

Best regards,
Hideo Aoki

---
Hideo Aoki, Hitachi Computer Products (America) Inc.
This patch is an enhancement of OVERCOMMIT_GUESS algorithm in
__vm_enough_memory().


- why the kernel needed patching

In the OVERCOMMIT_GUESS algorithm, when page caches and swapable
pages are not enough, the algorithm calculates number of free
pages. If the number of free pages is more than required pages, the
algorithm judges to be able to overcommit.

However, there are reserved free pages in free pages. The number of
reserved pages is specified by /proc/sys/vm/lowmem_reserve_ratio. If
all free pages are assigned to anonymous pages, the VM has to
reclaim free pages and VM pressure probably rises.


- the overall design approach in the patch

When the OVERCOMMET_GUESS algorithm calculates number of free pages,
the reserved free pages regard for non-free pages.


- implementation details

This patch changes the following two things.

1) When the OVERCOMMIT_GUESS algorithm calculates the number of free
pages, the algorithm subtracts the number of reserved pages from
the result nr_free_pages().

2) Adding a global variable, totalreserve_pages, to store the number
of reserved pages. The variable is calculated when the VM
initializes and /proc/sys/vm/lowmem_reserve_ratio is changed.


- testing results

I checked that this patch can pass compile.

---

Signed-off-by: Hideo Aoki <haoki@xxxxxxxxxx>

---

include/linux/swap.h | 1 +
mm/mmap.c | 13 +++++++++++++
mm/page_alloc.c | 4 ++++
3 files changed, 18 insertions(+)

diff -uprN linux-2.6.14-rc1-mm1/include/linux/swap.h linux-2.6.14-rc1-mm1-vm-overcommit-fix/include/linux/swap.h
--- linux-2.6.14-rc1-mm1/include/linux/swap.h 2005-09-19 16:05:19.000000000 -0400
+++ linux-2.6.14-rc1-mm1-vm-overcommit-fix/include/linux/swap.h 2005-09-19 16:15:21.000000000 -0400
@@ -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);
diff -uprN linux-2.6.14-rc1-mm1/mm/mmap.c linux-2.6.14-rc1-mm1-vm-overcommit-fix/mm/mmap.c
--- linux-2.6.14-rc1-mm1/mm/mmap.c 2005-09-19 16:11:45.000000000 -0400
+++ linux-2.6.14-rc1-mm1-vm-overcommit-fix/mm/mmap.c 2005-09-19 16:15:21.000000000 -0400
@@ -120,6 +120,19 @@ int __vm_enough_memory(long pages, int c
* only call if we're about to fail.
*/
n = nr_free_pages();
+
+ /*
+ * Leave the lowmem_reserve pages. The pages are not
+ * for anonymous pages.
+ */
+ if (n <= totalreserve_pages)
+ return 0;
+ else
+ n -= totalreserve_pages;
+
+ /*
+ * Leave the last 3% for root
+ */
if (!cap_sys_admin)
n -= n / 32;
free += n;
diff -uprN linux-2.6.14-rc1-mm1/mm/page_alloc.c linux-2.6.14-rc1-mm1-vm-overcommit-fix/mm/page_alloc.c
--- linux-2.6.14-rc1-mm1/mm/page_alloc.c 2005-09-19 16:11:45.000000000 -0400
+++ linux-2.6.14-rc1-mm1-vm-overcommit-fix/mm/page_alloc.c 2005-09-19 16:22:09.000000000 -0400
@@ -51,6 +51,7 @@ EXPORT_SYMBOL(node_possible_map);
struct pglist_data *pgdat_list __read_mostly;
unsigned long totalram_pages __read_mostly;
unsigned long totalhigh_pages __read_mostly;
+unsigned long totalreserve_pages __read_mostly;
long nr_swap_pages;

/*
@@ -2454,6 +2455,7 @@ void __init page_alloc_init(void)
static void setup_per_zone_lowmem_reserve(void)
{
struct pglist_data *pgdat;
+ unsigned long reserve_pages = 0;
int j, idx;

for_each_pgdat(pgdat) {
@@ -2472,10 +2474,12 @@ static void setup_per_zone_lowmem_reserv
lower_zone = pgdat->node_zones + idx;
lower_zone->lowmem_reserve[j] = present_pages /
sysctl_lowmem_reserve_ratio[idx];
+ reserve_pages += lower_zone->lowmem_reserve[j];
present_pages += lower_zone->present_pages;
}
}
}
+ totalreserve_pages = reserve_pages;
}

/*