summaryrefslogtreecommitdiffstats
path: root/queue-2.6.32/mm-fix-negative-commitlimit-when-gigantic-hugepages-are.patch
diff options
context:
space:
mode:
Diffstat (limited to 'queue-2.6.32/mm-fix-negative-commitlimit-when-gigantic-hugepages-are.patch')
-rw-r--r--queue-2.6.32/mm-fix-negative-commitlimit-when-gigantic-hugepages-are.patch73
1 files changed, 73 insertions, 0 deletions
diff --git a/queue-2.6.32/mm-fix-negative-commitlimit-when-gigantic-hugepages-are.patch b/queue-2.6.32/mm-fix-negative-commitlimit-when-gigantic-hugepages-are.patch
new file mode 100644
index 0000000..68221fa
--- /dev/null
+++ b/queue-2.6.32/mm-fix-negative-commitlimit-when-gigantic-hugepages-are.patch
@@ -0,0 +1,73 @@
+From b0320c7b7d1ac1bd5c2d9dff3258524ab39bad32 Mon Sep 17 00:00:00 2001
+From: Rafael Aquini <aquini@linux.com>
+Date: Wed, 15 Jun 2011 15:08:39 -0700
+Subject: mm: fix negative commitlimit when gigantic hugepages are
+ allocated
+
+From: Rafael Aquini <aquini@linux.com>
+
+commit b0320c7b7d1ac1bd5c2d9dff3258524ab39bad32 upstream.
+
+When 1GB hugepages are allocated on a system, free(1) reports less
+available memory than what really is installed in the box. Also, if the
+total size of hugepages allocated on a system is over half of the total
+memory size, CommitLimit becomes a negative number.
+
+The problem is that gigantic hugepages (order > MAX_ORDER) can only be
+allocated at boot with bootmem, thus its frames are not accounted to
+'totalram_pages'. However, they are accounted to hugetlb_total_pages()
+
+What happens to turn CommitLimit into a negative number is this
+calculation, in fs/proc/meminfo.c:
+
+ allowed = ((totalram_pages - hugetlb_total_pages())
+ * sysctl_overcommit_ratio / 100) + total_swap_pages;
+
+A similar calculation occurs in __vm_enough_memory() in mm/mmap.c.
+
+Also, every vm statistic which depends on 'totalram_pages' will render
+confusing values, as if system were 'missing' some part of its memory.
+
+Impact of this bug:
+
+When gigantic hugepages are allocated and sysctl_overcommit_memory ==
+OVERCOMMIT_NEVER. In a such situation, __vm_enough_memory() goes through
+the mentioned 'allowed' calculation and might end up mistakenly returning
+-ENOMEM, thus forcing the system to start reclaiming pages earlier than it
+would be ususal, and this could cause detrimental impact to overall
+system's performance, depending on the workload.
+
+Besides the aforementioned scenario, I can only think of this causing
+annoyances with memory reports from /proc/meminfo and free(1).
+
+[akpm@linux-foundation.org: standardize comment layout]
+Reported-by: Russ Anderson <rja@sgi.com>
+Signed-off-by: Rafael Aquini <aquini@linux.com>
+Acked-by: Russ Anderson <rja@sgi.com>
+Cc: Andrea Arcangeli <aarcange@redhat.com>
+Cc: Christoph Lameter <cl@linux.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ mm/hugetlb.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -1074,6 +1074,14 @@ static void __init gather_bootmem_preall
+ WARN_ON(page_count(page) != 1);
+ prep_compound_huge_page(page, h->order);
+ prep_new_huge_page(h, page, page_to_nid(page));
++ /*
++ * If we had gigantic hugepages allocated at boot time, we need
++ * to restore the 'stolen' pages to totalram_pages in order to
++ * fix confusing memory reports from free(1) and another
++ * side-effects, like CommitLimit going negative.
++ */
++ if (h->order > (MAX_ORDER - 1))
++ totalram_pages += 1 << h->order;
+ }
+ }
+