]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - mm/page_alloc.c
mm, numa: reclaim from all nodes within reclaim distance
[mirror_ubuntu-zesty-kernel.git] / mm / page_alloc.c
index dbb53866c3aa9696b68eff6d05ccb771738c34ac..9b8e6243a52410458bd5bb33a8d1c4f3137105f8 100644 (file)
@@ -1799,6 +1799,22 @@ static void zlc_clear_zones_full(struct zonelist *zonelist)
        bitmap_zero(zlc->fullzones, MAX_ZONES_PER_ZONELIST);
 }
 
+static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone)
+{
+       return node_isset(local_zone->node, zone->zone_pgdat->reclaim_nodes);
+}
+
+static void __paginginit init_zone_allows_reclaim(int nid)
+{
+       int i;
+
+       for_each_online_node(i)
+               if (node_distance(nid, i) <= RECLAIM_DISTANCE) {
+                       node_set(i, NODE_DATA(nid)->reclaim_nodes);
+                       zone_reclaim_mode = 1;
+               }
+}
+
 #else  /* CONFIG_NUMA */
 
 static nodemask_t *zlc_setup(struct zonelist *zonelist, int alloc_flags)
@@ -1819,6 +1835,15 @@ static void zlc_mark_zone_full(struct zonelist *zonelist, struct zoneref *z)
 static void zlc_clear_zones_full(struct zonelist *zonelist)
 {
 }
+
+static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone)
+{
+       return true;
+}
+
+static inline void init_zone_allows_reclaim(int nid)
+{
+}
 #endif /* CONFIG_NUMA */
 
 /*
@@ -1903,7 +1928,8 @@ zonelist_scan:
                                did_zlc_setup = 1;
                        }
 
-                       if (zone_reclaim_mode == 0)
+                       if (zone_reclaim_mode == 0 ||
+                           !zone_allows_reclaim(preferred_zone, zone))
                                goto this_zone_full;
 
                        /*
@@ -3364,21 +3390,13 @@ static void build_zonelists(pg_data_t *pgdat)
        j = 0;
 
        while ((node = find_next_best_node(local_node, &used_mask)) >= 0) {
-               int distance = node_distance(local_node, node);
-
-               /*
-                * If another node is sufficiently far away then it is better
-                * to reclaim pages in a zone before going off node.
-                */
-               if (distance > RECLAIM_DISTANCE)
-                       zone_reclaim_mode = 1;
-
                /*
                 * We don't want to pressure a particular node.
                 * So adding penalty to the first node in same
                 * distance group to make it round-robin.
                 */
-               if (distance != node_distance(local_node, prev_node))
+               if (node_distance(local_node, node) !=
+                   node_distance(local_node, prev_node))
                        node_load[node] = load;
 
                prev_node = node;
@@ -4552,6 +4570,7 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size,
 
        pgdat->node_id = nid;
        pgdat->node_start_pfn = node_start_pfn;
+       init_zone_allows_reclaim(nid);
        calculate_node_totalpages(pgdat, zones_size, zholes_size);
 
        alloc_node_mem_map(pgdat);