|
@@ -4839,18 +4839,17 @@ static void zoneref_set_zone(struct zone *zone, struct zoneref *zoneref)
|
|
|
*
|
|
|
* Add all populated zones of a node to the zonelist.
|
|
|
*/
|
|
|
-static int build_zonelists_node(pg_data_t *pgdat, struct zonelist *zonelist,
|
|
|
- int nr_zones)
|
|
|
+static int build_zonerefs_node(pg_data_t *pgdat, struct zoneref *zonerefs)
|
|
|
{
|
|
|
struct zone *zone;
|
|
|
enum zone_type zone_type = MAX_NR_ZONES;
|
|
|
+ int nr_zones = 0;
|
|
|
|
|
|
do {
|
|
|
zone_type--;
|
|
|
zone = pgdat->node_zones + zone_type;
|
|
|
if (managed_zone(zone)) {
|
|
|
- zoneref_set_zone(zone,
|
|
|
- &zonelist->_zonerefs[nr_zones++]);
|
|
|
+ zoneref_set_zone(zone, &zonerefs[nr_zones++]);
|
|
|
check_highest_zone(zone_type);
|
|
|
}
|
|
|
} while (zone_type);
|
|
@@ -4977,17 +4976,24 @@ static int find_next_best_node(int node, nodemask_t *used_node_mask)
|
|
|
* This results in maximum locality--normal zone overflows into local
|
|
|
* DMA zone, if any--but risks exhausting DMA zone.
|
|
|
*/
|
|
|
-static void build_zonelists_in_node_order(pg_data_t *pgdat, int node)
|
|
|
+static void build_zonelists_in_node_order(pg_data_t *pgdat, int *node_order,
|
|
|
+ unsigned nr_nodes)
|
|
|
{
|
|
|
- int j;
|
|
|
- struct zonelist *zonelist;
|
|
|
+ struct zoneref *zonerefs;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ zonerefs = pgdat->node_zonelists[ZONELIST_FALLBACK]._zonerefs;
|
|
|
+
|
|
|
+ for (i = 0; i < nr_nodes; i++) {
|
|
|
+ int nr_zones;
|
|
|
|
|
|
- zonelist = &pgdat->node_zonelists[ZONELIST_FALLBACK];
|
|
|
- for (j = 0; zonelist->_zonerefs[j].zone != NULL; j++)
|
|
|
- ;
|
|
|
- j = build_zonelists_node(NODE_DATA(node), zonelist, j);
|
|
|
- zonelist->_zonerefs[j].zone = NULL;
|
|
|
- zonelist->_zonerefs[j].zone_idx = 0;
|
|
|
+ pg_data_t *node = NODE_DATA(node_order[i]);
|
|
|
+
|
|
|
+ nr_zones = build_zonerefs_node(node, zonerefs);
|
|
|
+ zonerefs += nr_zones;
|
|
|
+ }
|
|
|
+ zonerefs->zone = NULL;
|
|
|
+ zonerefs->zone_idx = 0;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -4995,13 +5001,14 @@ static void build_zonelists_in_node_order(pg_data_t *pgdat, int node)
|
|
|
*/
|
|
|
static void build_thisnode_zonelists(pg_data_t *pgdat)
|
|
|
{
|
|
|
- int j;
|
|
|
- struct zonelist *zonelist;
|
|
|
+ struct zoneref *zonerefs;
|
|
|
+ int nr_zones;
|
|
|
|
|
|
- zonelist = &pgdat->node_zonelists[ZONELIST_NOFALLBACK];
|
|
|
- j = build_zonelists_node(pgdat, zonelist, 0);
|
|
|
- zonelist->_zonerefs[j].zone = NULL;
|
|
|
- zonelist->_zonerefs[j].zone_idx = 0;
|
|
|
+ zonerefs = pgdat->node_zonelists[ZONELIST_NOFALLBACK]._zonerefs;
|
|
|
+ nr_zones = build_zonerefs_node(pgdat, zonerefs);
|
|
|
+ zonerefs += nr_zones;
|
|
|
+ zonerefs->zone = NULL;
|
|
|
+ zonerefs->zone_idx = 0;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -5010,21 +5017,13 @@ static void build_thisnode_zonelists(pg_data_t *pgdat)
|
|
|
* exhausted, but results in overflowing to remote node while memory
|
|
|
* may still exist in local DMA zone.
|
|
|
*/
|
|
|
-static int node_order[MAX_NUMNODES];
|
|
|
|
|
|
static void build_zonelists(pg_data_t *pgdat)
|
|
|
{
|
|
|
- int i, node, load;
|
|
|
+ static int node_order[MAX_NUMNODES];
|
|
|
+ int node, load, nr_nodes = 0;
|
|
|
nodemask_t used_mask;
|
|
|
int local_node, prev_node;
|
|
|
- struct zonelist *zonelist;
|
|
|
-
|
|
|
- /* initialize zonelists */
|
|
|
- for (i = 0; i < MAX_ZONELISTS; i++) {
|
|
|
- zonelist = pgdat->node_zonelists + i;
|
|
|
- zonelist->_zonerefs[0].zone = NULL;
|
|
|
- zonelist->_zonerefs[0].zone_idx = 0;
|
|
|
- }
|
|
|
|
|
|
/* NUMA-aware ordering of nodes */
|
|
|
local_node = pgdat->node_id;
|
|
@@ -5033,8 +5032,6 @@ static void build_zonelists(pg_data_t *pgdat)
|
|
|
nodes_clear(used_mask);
|
|
|
|
|
|
memset(node_order, 0, sizeof(node_order));
|
|
|
- i = 0;
|
|
|
-
|
|
|
while ((node = find_next_best_node(local_node, &used_mask)) >= 0) {
|
|
|
/*
|
|
|
* We don't want to pressure a particular node.
|
|
@@ -5045,11 +5042,12 @@ static void build_zonelists(pg_data_t *pgdat)
|
|
|
node_distance(local_node, prev_node))
|
|
|
node_load[node] = load;
|
|
|
|
|
|
+ node_order[nr_nodes++] = node;
|
|
|
prev_node = node;
|
|
|
load--;
|
|
|
- build_zonelists_in_node_order(pgdat, node);
|
|
|
}
|
|
|
|
|
|
+ build_zonelists_in_node_order(pgdat, node_order, nr_nodes);
|
|
|
build_thisnode_zonelists(pgdat);
|
|
|
}
|
|
|
|
|
@@ -5078,13 +5076,14 @@ static void setup_min_slab_ratio(void);
|
|
|
static void build_zonelists(pg_data_t *pgdat)
|
|
|
{
|
|
|
int node, local_node;
|
|
|
- enum zone_type j;
|
|
|
- struct zonelist *zonelist;
|
|
|
+ struct zoneref *zonerefs;
|
|
|
+ int nr_zones;
|
|
|
|
|
|
local_node = pgdat->node_id;
|
|
|
|
|
|
- zonelist = &pgdat->node_zonelists[ZONELIST_FALLBACK];
|
|
|
- j = build_zonelists_node(pgdat, zonelist, 0);
|
|
|
+ zonerefs = pgdat->node_zonelists[ZONELIST_FALLBACK]._zonerefs;
|
|
|
+ nr_zones = build_zonerefs_node(pgdat, zonerefs);
|
|
|
+ zonerefs += nr_zones;
|
|
|
|
|
|
/*
|
|
|
* Now we build the zonelist so that it contains the zones
|
|
@@ -5097,16 +5096,18 @@ static void build_zonelists(pg_data_t *pgdat)
|
|
|
for (node = local_node + 1; node < MAX_NUMNODES; node++) {
|
|
|
if (!node_online(node))
|
|
|
continue;
|
|
|
- j = build_zonelists_node(NODE_DATA(node), zonelist, j);
|
|
|
+ nr_zones = build_zonerefs_node(NODE_DATA(node), zonerefs);
|
|
|
+ zonerefs += nr_zones;
|
|
|
}
|
|
|
for (node = 0; node < local_node; node++) {
|
|
|
if (!node_online(node))
|
|
|
continue;
|
|
|
- j = build_zonelists_node(NODE_DATA(node), zonelist, j);
|
|
|
+ nr_zones = build_zonerefs_node(NODE_DATA(node), zonerefs);
|
|
|
+ zonerefs += nr_zones;
|
|
|
}
|
|
|
|
|
|
- zonelist->_zonerefs[j].zone = NULL;
|
|
|
- zonelist->_zonerefs[j].zone_idx = 0;
|
|
|
+ zonerefs->zone = NULL;
|
|
|
+ zonerefs->zone_idx = 0;
|
|
|
}
|
|
|
|
|
|
#endif /* CONFIG_NUMA */
|