diff options
-rw-r--r-- | mm/page_alloc.c | 81 |
1 files changed, 41 insertions, 40 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 2523d5b3b22f..36a2f18c5e0a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -4839,18 +4839,17 @@ static void zoneref_set_zone(struct zone *zone, struct zoneref *zoneref) | |||
4839 | * | 4839 | * |
4840 | * Add all populated zones of a node to the zonelist. | 4840 | * Add all populated zones of a node to the zonelist. |
4841 | */ | 4841 | */ |
4842 | static int build_zonelists_node(pg_data_t *pgdat, struct zonelist *zonelist, | 4842 | static int build_zonerefs_node(pg_data_t *pgdat, struct zoneref *zonerefs) |
4843 | int nr_zones) | ||
4844 | { | 4843 | { |
4845 | struct zone *zone; | 4844 | struct zone *zone; |
4846 | enum zone_type zone_type = MAX_NR_ZONES; | 4845 | enum zone_type zone_type = MAX_NR_ZONES; |
4846 | int nr_zones = 0; | ||
4847 | 4847 | ||
4848 | do { | 4848 | do { |
4849 | zone_type--; | 4849 | zone_type--; |
4850 | zone = pgdat->node_zones + zone_type; | 4850 | zone = pgdat->node_zones + zone_type; |
4851 | if (managed_zone(zone)) { | 4851 | if (managed_zone(zone)) { |
4852 | zoneref_set_zone(zone, | 4852 | zoneref_set_zone(zone, &zonerefs[nr_zones++]); |
4853 | &zonelist->_zonerefs[nr_zones++]); | ||
4854 | check_highest_zone(zone_type); | 4853 | check_highest_zone(zone_type); |
4855 | } | 4854 | } |
4856 | } while (zone_type); | 4855 | } while (zone_type); |
@@ -4977,17 +4976,24 @@ static int find_next_best_node(int node, nodemask_t *used_node_mask) | |||
4977 | * This results in maximum locality--normal zone overflows into local | 4976 | * This results in maximum locality--normal zone overflows into local |
4978 | * DMA zone, if any--but risks exhausting DMA zone. | 4977 | * DMA zone, if any--but risks exhausting DMA zone. |
4979 | */ | 4978 | */ |
4980 | static void build_zonelists_in_node_order(pg_data_t *pgdat, int node) | 4979 | static void build_zonelists_in_node_order(pg_data_t *pgdat, int *node_order, |
4980 | unsigned nr_nodes) | ||
4981 | { | 4981 | { |
4982 | int j; | 4982 | struct zoneref *zonerefs; |
4983 | struct zonelist *zonelist; | 4983 | int i; |
4984 | |||
4985 | zonerefs = pgdat->node_zonelists[ZONELIST_FALLBACK]._zonerefs; | ||
4986 | |||
4987 | for (i = 0; i < nr_nodes; i++) { | ||
4988 | int nr_zones; | ||
4984 | 4989 | ||
4985 | zonelist = &pgdat->node_zonelists[ZONELIST_FALLBACK]; | 4990 | pg_data_t *node = NODE_DATA(node_order[i]); |
4986 | for (j = 0; zonelist->_zonerefs[j].zone != NULL; j++) | 4991 | |
4987 | ; | 4992 | nr_zones = build_zonerefs_node(node, zonerefs); |
4988 | j = build_zonelists_node(NODE_DATA(node), zonelist, j); | 4993 | zonerefs += nr_zones; |
4989 | zonelist->_zonerefs[j].zone = NULL; | 4994 | } |
4990 | zonelist->_zonerefs[j].zone_idx = 0; | 4995 | zonerefs->zone = NULL; |
4996 | zonerefs->zone_idx = 0; | ||
4991 | } | 4997 | } |
4992 | 4998 | ||
4993 | /* | 4999 | /* |
@@ -4995,13 +5001,14 @@ static void build_zonelists_in_node_order(pg_data_t *pgdat, int node) | |||
4995 | */ | 5001 | */ |
4996 | static void build_thisnode_zonelists(pg_data_t *pgdat) | 5002 | static void build_thisnode_zonelists(pg_data_t *pgdat) |
4997 | { | 5003 | { |
4998 | int j; | 5004 | struct zoneref *zonerefs; |
4999 | struct zonelist *zonelist; | 5005 | int nr_zones; |
5000 | 5006 | ||
5001 | zonelist = &pgdat->node_zonelists[ZONELIST_NOFALLBACK]; | 5007 | zonerefs = pgdat->node_zonelists[ZONELIST_NOFALLBACK]._zonerefs; |
5002 | j = build_zonelists_node(pgdat, zonelist, 0); | 5008 | nr_zones = build_zonerefs_node(pgdat, zonerefs); |
5003 | zonelist->_zonerefs[j].zone = NULL; | 5009 | zonerefs += nr_zones; |
5004 | zonelist->_zonerefs[j].zone_idx = 0; | 5010 | zonerefs->zone = NULL; |
5011 | zonerefs->zone_idx = 0; | ||
5005 | } | 5012 | } |
5006 | 5013 | ||
5007 | /* | 5014 | /* |
@@ -5010,21 +5017,13 @@ static void build_thisnode_zonelists(pg_data_t *pgdat) | |||
5010 | * exhausted, but results in overflowing to remote node while memory | 5017 | * exhausted, but results in overflowing to remote node while memory |
5011 | * may still exist in local DMA zone. | 5018 | * may still exist in local DMA zone. |
5012 | */ | 5019 | */ |
5013 | static int node_order[MAX_NUMNODES]; | ||
5014 | 5020 | ||
5015 | static void build_zonelists(pg_data_t *pgdat) | 5021 | static void build_zonelists(pg_data_t *pgdat) |
5016 | { | 5022 | { |
5017 | int i, node, load; | 5023 | static int node_order[MAX_NUMNODES]; |
5024 | int node, load, nr_nodes = 0; | ||
5018 | nodemask_t used_mask; | 5025 | nodemask_t used_mask; |
5019 | int local_node, prev_node; | 5026 | int local_node, prev_node; |
5020 | struct zonelist *zonelist; | ||
5021 | |||
5022 | /* initialize zonelists */ | ||
5023 | for (i = 0; i < MAX_ZONELISTS; i++) { | ||
5024 | zonelist = pgdat->node_zonelists + i; | ||
5025 | zonelist->_zonerefs[0].zone = NULL; | ||
5026 | zonelist->_zonerefs[0].zone_idx = 0; | ||
5027 | } | ||
5028 | 5027 | ||
5029 | /* NUMA-aware ordering of nodes */ | 5028 | /* NUMA-aware ordering of nodes */ |
5030 | local_node = pgdat->node_id; | 5029 | local_node = pgdat->node_id; |
@@ -5033,8 +5032,6 @@ static void build_zonelists(pg_data_t *pgdat) | |||
5033 | nodes_clear(used_mask); | 5032 | nodes_clear(used_mask); |
5034 | 5033 | ||
5035 | memset(node_order, 0, sizeof(node_order)); | 5034 | memset(node_order, 0, sizeof(node_order)); |
5036 | i = 0; | ||
5037 | |||
5038 | while ((node = find_next_best_node(local_node, &used_mask)) >= 0) { | 5035 | while ((node = find_next_best_node(local_node, &used_mask)) >= 0) { |
5039 | /* | 5036 | /* |
5040 | * We don't want to pressure a particular node. | 5037 | * We don't want to pressure a particular node. |
@@ -5045,11 +5042,12 @@ static void build_zonelists(pg_data_t *pgdat) | |||
5045 | node_distance(local_node, prev_node)) | 5042 | node_distance(local_node, prev_node)) |
5046 | node_load[node] = load; | 5043 | node_load[node] = load; |
5047 | 5044 | ||
5045 | node_order[nr_nodes++] = node; | ||
5048 | prev_node = node; | 5046 | prev_node = node; |
5049 | load--; | 5047 | load--; |
5050 | build_zonelists_in_node_order(pgdat, node); | ||
5051 | } | 5048 | } |
5052 | 5049 | ||
5050 | build_zonelists_in_node_order(pgdat, node_order, nr_nodes); | ||
5053 | build_thisnode_zonelists(pgdat); | 5051 | build_thisnode_zonelists(pgdat); |
5054 | } | 5052 | } |
5055 | 5053 | ||
@@ -5078,13 +5076,14 @@ static void setup_min_slab_ratio(void); | |||
5078 | static void build_zonelists(pg_data_t *pgdat) | 5076 | static void build_zonelists(pg_data_t *pgdat) |
5079 | { | 5077 | { |
5080 | int node, local_node; | 5078 | int node, local_node; |
5081 | enum zone_type j; | 5079 | struct zoneref *zonerefs; |
5082 | struct zonelist *zonelist; | 5080 | int nr_zones; |
5083 | 5081 | ||
5084 | local_node = pgdat->node_id; | 5082 | local_node = pgdat->node_id; |
5085 | 5083 | ||
5086 | zonelist = &pgdat->node_zonelists[ZONELIST_FALLBACK]; | 5084 | zonerefs = pgdat->node_zonelists[ZONELIST_FALLBACK]._zonerefs; |
5087 | j = build_zonelists_node(pgdat, zonelist, 0); | 5085 | nr_zones = build_zonerefs_node(pgdat, zonerefs); |
5086 | zonerefs += nr_zones; | ||
5088 | 5087 | ||
5089 | /* | 5088 | /* |
5090 | * Now we build the zonelist so that it contains the zones | 5089 | * Now we build the zonelist so that it contains the zones |
@@ -5097,16 +5096,18 @@ static void build_zonelists(pg_data_t *pgdat) | |||
5097 | for (node = local_node + 1; node < MAX_NUMNODES; node++) { | 5096 | for (node = local_node + 1; node < MAX_NUMNODES; node++) { |
5098 | if (!node_online(node)) | 5097 | if (!node_online(node)) |
5099 | continue; | 5098 | continue; |
5100 | j = build_zonelists_node(NODE_DATA(node), zonelist, j); | 5099 | nr_zones = build_zonerefs_node(NODE_DATA(node), zonerefs); |
5100 | zonerefs += nr_zones; | ||
5101 | } | 5101 | } |
5102 | for (node = 0; node < local_node; node++) { | 5102 | for (node = 0; node < local_node; node++) { |
5103 | if (!node_online(node)) | 5103 | if (!node_online(node)) |
5104 | continue; | 5104 | continue; |
5105 | j = build_zonelists_node(NODE_DATA(node), zonelist, j); | 5105 | nr_zones = build_zonerefs_node(NODE_DATA(node), zonerefs); |
5106 | zonerefs += nr_zones; | ||
5106 | } | 5107 | } |
5107 | 5108 | ||
5108 | zonelist->_zonerefs[j].zone = NULL; | 5109 | zonerefs->zone = NULL; |
5109 | zonelist->_zonerefs[j].zone_idx = 0; | 5110 | zonerefs->zone_idx = 0; |
5110 | } | 5111 | } |
5111 | 5112 | ||
5112 | #endif /* CONFIG_NUMA */ | 5113 | #endif /* CONFIG_NUMA */ |