diff options
author | Christoph Lameter <clameter@sgi.com> | 2006-09-26 02:31:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-26 11:48:47 -0400 |
commit | 19655d3487001d7df0e10e9cbfc27c758b77c2b5 (patch) | |
tree | 8d0aaa216bd32bd64e3a9652fd34d40bdb9d1075 | |
parent | 2f6726e54a9410e2e4cee864947c05e954051916 (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.h | 12 | ||||
-rw-r--r-- | include/linux/mmzone.h | 52 | ||||
-rw-r--r-- | mm/mempolicy.c | 2 | ||||
-rw-r--r-- | mm/page_alloc.c | 27 |
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 | ||
81 | static inline int gfp_zone(gfp_t gfp) | 78 | static 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 | |||
88 | static 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 | ||
196 | struct zone { | 154 | struct zone { |
@@ -360,7 +318,7 @@ struct zonelist { | |||
360 | struct bootmem_data; | 318 | struct bootmem_data; |
361 | typedef struct pglist_data { | 319 | typedef 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 | ||
1445 | static void __meminit build_zonelists(pg_data_t *pgdat) | 1445 | static 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 | ||
1498 | static void __meminit build_zonelists(pg_data_t *pgdat) | 1496 | static 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; |