aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Lameter <clameter@sgi.com>2006-09-26 02:31:19 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-26 11:48:47 -0400
commit19655d3487001d7df0e10e9cbfc27c758b77c2b5 (patch)
tree8d0aaa216bd32bd64e3a9652fd34d40bdb9d1075
parent2f6726e54a9410e2e4cee864947c05e954051916 (diff)
[PATCH] linearly index zone->node_zonelists[]
I wonder why we need this bitmask indexing into zone->node_zonelists[]? We always start with the highest zone and then include all lower zones if we build zonelists. Are there really cases where we need allocation from ZONE_DMA or ZONE_HIGHMEM but not ZONE_NORMAL? It seems that the current implementation of highest_zone() makes that already impossible. If we go linear on the index then gfp_zone() == highest_zone() and a lot of definitions fall by the wayside. We can now revert back to the use of gfp_zone() in mempolicy.c ;-) Signed-off-by: Christoph Lameter <clameter@sgi.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--include/linux/gfp.h12
-rw-r--r--include/linux/mmzone.h52
-rw-r--r--mm/mempolicy.c2
-rw-r--r--mm/page_alloc.c27
4 files changed, 18 insertions, 75 deletions
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index a0992d392d79..63ab88a36f39 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -12,9 +12,6 @@ struct vm_area_struct;
12 * 12 *
13 * Zone modifiers (see linux/mmzone.h - low three bits) 13 * Zone modifiers (see linux/mmzone.h - low three bits)
14 * 14 *
15 * These may be masked by GFP_ZONEMASK to make allocations with this bit
16 * set fall back to ZONE_NORMAL.
17 *
18 * Do not put any conditional on these. If necessary modify the definitions 15 * Do not put any conditional on these. If necessary modify the definitions
19 * without the underscores and use the consistently. The definitions here may 16 * without the underscores and use the consistently. The definitions here may
20 * be used in bit comparisons. 17 * be used in bit comparisons.
@@ -78,14 +75,7 @@ struct vm_area_struct;
78#define GFP_DMA32 __GFP_DMA32 75#define GFP_DMA32 __GFP_DMA32
79 76
80 77
81static inline int gfp_zone(gfp_t gfp) 78static inline enum zone_type gfp_zone(gfp_t flags)
82{
83 int zone = GFP_ZONEMASK & (__force int) gfp;
84 BUG_ON(zone >= GFP_ZONETYPES);
85 return zone;
86}
87
88static inline enum zone_type highest_zone(gfp_t flags)
89{ 79{
90 if (flags & __GFP_DMA) 80 if (flags & __GFP_DMA)
91 return ZONE_DMA; 81 return ZONE_DMA;
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 76d33e688593..7fe317164b73 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -137,60 +137,18 @@ enum zone_type {
137 MAX_NR_ZONES 137 MAX_NR_ZONES
138}; 138};
139 139
140
141/* 140/*
142 * When a memory allocation must conform to specific limitations (such 141 * When a memory allocation must conform to specific limitations (such
143 * as being suitable for DMA) the caller will pass in hints to the 142 * as being suitable for DMA) the caller will pass in hints to the
144 * allocator in the gfp_mask, in the zone modifier bits. These bits 143 * allocator in the gfp_mask, in the zone modifier bits. These bits
145 * are used to select a priority ordered list of memory zones which 144 * are used to select a priority ordered list of memory zones which
146 * match the requested limits. GFP_ZONEMASK defines which bits within 145 * match the requested limits. See gfp_zone() in include/linux/gfp.h
147 * the gfp_mask should be considered as zone modifiers. Each valid
148 * combination of the zone modifier bits has a corresponding list
149 * of zones (in node_zonelists). Thus for two zone modifiers there
150 * will be a maximum of 4 (2 ** 2) zonelists, for 3 modifiers there will
151 * be 8 (2 ** 3) zonelists. GFP_ZONETYPES defines the number of possible
152 * combinations of zone modifiers in "zone modifier space".
153 *
154 * As an optimisation any zone modifier bits which are only valid when
155 * no other zone modifier bits are set (loners) should be placed in
156 * the highest order bits of this field. This allows us to reduce the
157 * extent of the zonelists thus saving space. For example in the case
158 * of three zone modifier bits, we could require up to eight zonelists.
159 * If the left most zone modifier is a "loner" then the highest valid
160 * zonelist would be four allowing us to allocate only five zonelists.
161 * Use the first form for GFP_ZONETYPES when the left most bit is not
162 * a "loner", otherwise use the second.
163 *
164 * NOTE! Make sure this matches the zones in <linux/gfp.h>
165 */ 146 */
166 147
167#ifdef CONFIG_ZONE_DMA32 148#if !defined(CONFIG_ZONE_DMA32) && !defined(CONFIG_HIGHMEM)
168 149#define ZONES_SHIFT 1
169#ifdef CONFIG_HIGHMEM
170#define GFP_ZONETYPES ((GFP_ZONEMASK + 1) / 2 + 1) /* Loner */
171#define GFP_ZONEMASK 0x07
172#define ZONES_SHIFT 2 /* ceil(log2(MAX_NR_ZONES)) */
173#else
174#define GFP_ZONETYPES ((0x07 + 1) / 2 + 1) /* Loner */
175/* Mask __GFP_HIGHMEM */
176#define GFP_ZONEMASK 0x05
177#define ZONES_SHIFT 2
178#endif
179
180#else
181#ifdef CONFIG_HIGHMEM
182
183#define GFP_ZONEMASK 0x03
184#define ZONES_SHIFT 2
185#define GFP_ZONETYPES 3
186
187#else 150#else
188 151#define ZONES_SHIFT 2
189#define GFP_ZONEMASK 0x01
190#define ZONES_SHIFT 1
191#define GFP_ZONETYPES 2
192
193#endif
194#endif 152#endif
195 153
196struct zone { 154struct zone {
@@ -360,7 +318,7 @@ struct zonelist {
360struct bootmem_data; 318struct bootmem_data;
361typedef struct pglist_data { 319typedef struct pglist_data {
362 struct zone node_zones[MAX_NR_ZONES]; 320 struct zone node_zones[MAX_NR_ZONES];
363 struct zonelist node_zonelists[GFP_ZONETYPES]; 321 struct zonelist node_zonelists[MAX_NR_ZONES];
364 int nr_zones; 322 int nr_zones;
365#ifdef CONFIG_FLAT_NODE_MEM_MAP 323#ifdef CONFIG_FLAT_NODE_MEM_MAP
366 struct page *node_mem_map; 324 struct page *node_mem_map;
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 7da4142ce960..c3429a710ab1 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1101,7 +1101,7 @@ static struct zonelist *zonelist_policy(gfp_t gfp, struct mempolicy *policy)
1101 case MPOL_BIND: 1101 case MPOL_BIND:
1102 /* Lower zones don't get a policy applied */ 1102 /* Lower zones don't get a policy applied */
1103 /* Careful: current->mems_allowed might have moved */ 1103 /* Careful: current->mems_allowed might have moved */
1104 if (highest_zone(gfp) >= policy_zone) 1104 if (gfp_zone(gfp) >= policy_zone)
1105 if (cpuset_zonelist_valid_mems_allowed(policy->v.zonelist)) 1105 if (cpuset_zonelist_valid_mems_allowed(policy->v.zonelist))
1106 return policy->v.zonelist; 1106 return policy->v.zonelist;
1107 /*FALL THROUGH*/ 1107 /*FALL THROUGH*/
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 9c44b9a39d30..208a6b03aa78 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1444,14 +1444,14 @@ static int __meminit find_next_best_node(int node, nodemask_t *used_node_mask)
1444 1444
1445static void __meminit build_zonelists(pg_data_t *pgdat) 1445static void __meminit build_zonelists(pg_data_t *pgdat)
1446{ 1446{
1447 int i, j, node, local_node; 1447 int j, node, local_node;
1448 enum zone_type i;
1448 int prev_node, load; 1449 int prev_node, load;
1449 struct zonelist *zonelist; 1450 struct zonelist *zonelist;
1450 nodemask_t used_mask; 1451 nodemask_t used_mask;
1451 enum zone_type k;
1452 1452
1453 /* initialize zonelists */ 1453 /* initialize zonelists */
1454 for (i = 0; i < GFP_ZONETYPES; i++) { 1454 for (i = 0; i < MAX_NR_ZONES; i++) {
1455 zonelist = pgdat->node_zonelists + i; 1455 zonelist = pgdat->node_zonelists + i;
1456 zonelist->zones[0] = NULL; 1456 zonelist->zones[0] = NULL;
1457 } 1457 }
@@ -1481,13 +1481,11 @@ static void __meminit build_zonelists(pg_data_t *pgdat)
1481 node_load[node] += load; 1481 node_load[node] += load;
1482 prev_node = node; 1482 prev_node = node;
1483 load--; 1483 load--;
1484 for (i = 0; i < GFP_ZONETYPES; i++) { 1484 for (i = 0; i < MAX_NR_ZONES; i++) {
1485 zonelist = pgdat->node_zonelists + i; 1485 zonelist = pgdat->node_zonelists + i;
1486 for (j = 0; zonelist->zones[j] != NULL; j++); 1486 for (j = 0; zonelist->zones[j] != NULL; j++);
1487 1487
1488 k = highest_zone(i); 1488 j = build_zonelists_node(NODE_DATA(node), zonelist, j, i);
1489
1490 j = build_zonelists_node(NODE_DATA(node), zonelist, j, k);
1491 zonelist->zones[j] = NULL; 1489 zonelist->zones[j] = NULL;
1492 } 1490 }
1493 } 1491 }
@@ -1497,19 +1495,16 @@ static void __meminit build_zonelists(pg_data_t *pgdat)
1497 1495
1498static void __meminit build_zonelists(pg_data_t *pgdat) 1496static void __meminit build_zonelists(pg_data_t *pgdat)
1499{ 1497{
1500 int i, node, local_node; 1498 int node, local_node;
1501 enum zone_type k; 1499 enum zone_type i,j;
1502 enum zone_type j;
1503 1500
1504 local_node = pgdat->node_id; 1501 local_node = pgdat->node_id;
1505 for (i = 0; i < GFP_ZONETYPES; i++) { 1502 for (i = 0; i < MAX_NR_ZONES; i++) {
1506 struct zonelist *zonelist; 1503 struct zonelist *zonelist;
1507 1504
1508 zonelist = pgdat->node_zonelists + i; 1505 zonelist = pgdat->node_zonelists + i;
1509 1506
1510 j = 0; 1507 j = build_zonelists_node(pgdat, zonelist, 0, i);
1511 k = highest_zone(i);
1512 j = build_zonelists_node(pgdat, zonelist, j, k);
1513 /* 1508 /*
1514 * Now we build the zonelist so that it contains the zones 1509 * Now we build the zonelist so that it contains the zones
1515 * of all the other nodes. 1510 * of all the other nodes.
@@ -1521,12 +1516,12 @@ static void __meminit build_zonelists(pg_data_t *pgdat)
1521 for (node = local_node + 1; node < MAX_NUMNODES; node++) { 1516 for (node = local_node + 1; node < MAX_NUMNODES; node++) {
1522 if (!node_online(node)) 1517 if (!node_online(node))
1523 continue; 1518 continue;
1524 j = build_zonelists_node(NODE_DATA(node), zonelist, j, k); 1519 j = build_zonelists_node(NODE_DATA(node), zonelist, j, i);
1525 } 1520 }
1526 for (node = 0; node < local_node; node++) { 1521 for (node = 0; node < local_node; node++) {
1527 if (!node_online(node)) 1522 if (!node_online(node))
1528 continue; 1523 continue;
1529 j = build_zonelists_node(NODE_DATA(node), zonelist, j, k); 1524 j = build_zonelists_node(NODE_DATA(node), zonelist, j, i);
1530 } 1525 }
1531 1526
1532 zonelist->zones[j] = NULL; 1527 zonelist->zones[j] = NULL;