Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 4435

kernel-2.6.18-194.11.1.el5.src.rpm

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;