From: Bhavna Sarathy <bnagendr@redhat.com> Date: Thu, 15 Oct 2009 13:19:59 -0400 Subject: [xen] fix crash with memory imbalance Message-id: <4AD7217F.50809@redhat.com> Patchwork-id: 21166 O-Subject: Re: [RHEL5 PATCH] Fix Xen crash with memory imbalance Bugzilla: 526785 RH-Acked-by: Rik van Riel <riel@redhat.com> RH-Acked-by: Christopher Lalancette <clalance@redhat.com> RH-Acked-by: Markus Armbruster <armbru@redhat.com> Resolves BZ 526785 During RHEL5.4 experimental kernel testing, AMD found an issue when a system has memory imbalance leading to memory-less nodes, and this leads to a Xen crash. This is a corner case, and does not occur on systems that are properly configured. See BZ for further details. The attached patch fixes the issue, by not iterating over all nodes by using a "for" loop, since there can be holes in the node map. Instead, replace the modulo up counter with the respective macros utilizing the nodes_online map. Upstream: (issue found on RHEL first) The patch has been submitted upstream, commit 07ceb817720cf0a332d3de19ba46cec129e53e38 Testing: The patch has been tested on several Dinar platforms, and it fixes the issue. Brew build: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=2026602 diff --git a/common/page_alloc.c b/common/page_alloc.c index c94b5cb..8dd18e2 100644 --- a/common/page_alloc.c +++ b/common/page_alloc.c @@ -362,7 +362,6 @@ static struct page_info *alloc_heap_pages( struct page_info *pg; ASSERT(node >= 0); - ASSERT(node < num_nodes); ASSERT(zone_lo <= zone_hi); ASSERT(zone_hi < NR_ZONES); @@ -391,8 +390,9 @@ static struct page_info *alloc_heap_pages( } while ( zone-- > zone_lo ); /* careful: unsigned zone may wrap */ /* Pick next node, wrapping around if needed. */ - if ( ++node == num_nodes ) - node = 0; + node = next_node(node, node_online_map); + if (node == MAX_NUMNODES) + node = first_node(node_online_map); } /* No suitable memory blocks. Fail the request. */ @@ -454,7 +454,6 @@ static void free_heap_pages( ASSERT(zone < NR_ZONES); ASSERT(order <= MAX_ORDER); ASSERT(node >= 0); - ASSERT(node < num_online_nodes()); for ( i = 0; i < (1 << order); i++ ) { @@ -567,13 +566,13 @@ void init_heap_pages( static unsigned long avail_heap_pages( unsigned int zone_lo, unsigned int zone_hi, unsigned int node) { - unsigned int i, zone, num_nodes = num_online_nodes(); + unsigned int i, zone; unsigned long free_pages = 0; if ( zone_hi >= NR_ZONES ) zone_hi = NR_ZONES - 1; - for ( i = 0; i < num_nodes; i++ ) + for_each_online_node(i) { if ( !avail[i] ) continue;