| From jejb@kernel.org Wed Sep 3 08:25:42 2008 |
| From: Adam Litke <agl@us.ibm.com> |
| Date: Wed, 3 Sep 2008 02:35:08 GMT |
| Subject: mm: make setup_zone_migrate_reserve() aware of overlapping nodes |
| To: jejb@kernel.org, stable@kernel.org |
| Message-ID: <200809030235.m832Z8Wn015432@hera.kernel.org> |
| |
| From: Adam Litke <agl@us.ibm.com> |
| |
| 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> |
| |
| --- |
| mm/page_alloc.c | 7 +++++++ |
| 1 file changed, 7 insertions(+) |
| |
| --- a/mm/page_alloc.c |
| +++ b/mm/page_alloc.c |
| @@ -717,6 +717,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; |
| @@ -2476,6 +2479,10 @@ static void setup_zone_migrate_reserve(s |
| 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; |