summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Litke <agl@us.ibm.com>2008-09-03 02:35:08 +0000
committerGreg Kroah-Hartman <gregkh@suse.de>2008-09-08 04:44:22 -0700
commit6fcf36152391ff2efe2d8ed84769090a0bb0d432 (patch)
tree42125cc18f9ad86ba6ae1f59e9b14100ae68d89b
parentda924e49a005cdb4bac9a958f3edff958b770069 (diff)
downloadkernel-common-6fcf36152391ff2efe2d8ed84769090a0bb0d432.tar.gz
kernel-common-6fcf36152391ff2efe2d8ed84769090a0bb0d432.tar.bz2
kernel-common-6fcf36152391ff2efe2d8ed84769090a0bb0d432.zip
mm: make setup_zone_migrate_reserve() aware of overlapping nodes
commit 344c790e3821dac37eb742ddd0b611a300f78b9a upstream I have gotten to the root cause of the hugetlb badness I reported back on August 15th. My system has the following memory topology (note the overlapping node): Node 0 Memory: 0x8000000-0x44000000 Node 1 Memory: 0x0-0x8000000 0x44000000-0x80000000 setup_zone_migrate_reserve() scans the address range 0x0-0x8000000 looking for a pageblock to move onto the MIGRATE_RESERVE list. Finding no candidates, it happily continues the scan into 0x8000000-0x44000000. When a pageblock is found, the pages are moved to the MIGRATE_RESERVE list on the wrong zone. Oops. setup_zone_migrate_reserve() should skip pageblocks in overlapping nodes. Signed-off-by: Adam Litke <agl@us.ibm.com> Acked-by: Mel Gorman <mel@csn.ul.ie> Cc: Dave Hansen <dave@linux.vnet.ibm.com> Cc: Nishanth Aravamudan <nacc@us.ibm.com> Cc: Andy Whitcroft <apw@shadowen.org> 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>
-rw-r--r--mm/page_alloc.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index f32fae3121f0..0d520dce6aea 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -693,6 +693,9 @@ int move_freepages(struct zone *zone,
#endif
for (page = start_page; page <= end_page;) {
+ /* Make sure we are not inadvertently changing nodes */
+ VM_BUG_ON(page_to_nid(page) != zone_to_nid(zone));
+
if (!pfn_valid_within(page_to_pfn(page))) {
page++;
continue;
@@ -2475,6 +2478,10 @@ static void setup_zone_migrate_reserve(struct zone *zone)
continue;
page = pfn_to_page(pfn);
+ /* Watch out for overlapping nodes */
+ if (page_to_nid(page) != zone_to_nid(zone))
+ continue;
+
/* Blocks with reserved pages will never free, skip them. */
if (PageReserved(page))
continue;