Commit 9e19e93b authored by Andy Whitcroft's avatar Andy Whitcroft Committed by Linus Torvalds

[PATCH] fix GFP zone modifier interators

For each node there are a defined list of MAX_NR_ZONES zones.  These are
selected as a result of the __GFP_DMA and __GFP_HIGHMEM zone modifier flags
being passed to the memory allocator as part of the GFP mask.  Each node
has a set of zone lists, node_zonelists, which defines the list and order
of zones to scan for each flag combination.  When initialising these lists
we iterate over modifier combinations 0 ..  MAX_NR_ZONES.  However, this is
only correct when there are at most ZONES_SHIFT flags.  If another flag is
introduced zonelists for it would not be initialised.

This patch introduces GFP_ZONETYPES (based on GFP_ZONEMASK) as a bound for
the number of modifier combinations.
Signed-off-by: default avatarAndy Whitcroft <apw@shadowen.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent e7411c12
...@@ -81,7 +81,34 @@ struct per_cpu_pageset { ...@@ -81,7 +81,34 @@ struct per_cpu_pageset {
#define MAX_NR_ZONES 3 /* Sync this with ZONES_SHIFT */ #define MAX_NR_ZONES 3 /* Sync this with ZONES_SHIFT */
#define ZONES_SHIFT 2 /* ceil(log2(MAX_NR_ZONES)) */ #define ZONES_SHIFT 2 /* ceil(log2(MAX_NR_ZONES)) */
/*
* When a memory allocation must conform to specific limitations (such
* as being suitable for DMA) the caller will pass in hints to the
* allocator in the gfp_mask, in the zone modifier bits. These bits
* are used to select a priority ordered list of memory zones which
* match the requested limits. GFP_ZONEMASK defines which bits within
* the gfp_mask should be considered as zone modifiers. Each valid
* combination of the zone modifier bits has a corresponding list
* of zones (in node_zonelists). Thus for two zone modifiers there
* will be a maximum of 4 (2 ** 2) zonelists, for 3 modifiers there will
* be 8 (2 ** 3) zonelists. GFP_ZONETYPES defines the number of possible
* combinations of zone modifiers in "zone modifier space".
*/
#define GFP_ZONEMASK 0x03 #define GFP_ZONEMASK 0x03
/*
* As an optimisation any zone modifier bits which are only valid when
* no other zone modifier bits are set (loners) should be placed in
* the highest order bits of this field. This allows us to reduce the
* extent of the zonelists thus saving space. For example in the case
* of three zone modifier bits, we could require up to eight zonelists.
* If the left most zone modifier is a "loner" then the highest valid
* zonelist would be four allowing us to allocate only five zonelists.
* Use the first form when the left most bit is not a "loner", otherwise
* use the second.
*/
/* #define GFP_ZONETYPES (GFP_ZONEMASK + 1) */ /* Non-loner */
#define GFP_ZONETYPES ((GFP_ZONEMASK + 1) / 2 + 1) /* Loner */
/* /*
* On machines where it is needed (eg PCs) we divide physical memory * On machines where it is needed (eg PCs) we divide physical memory
...@@ -237,7 +264,7 @@ struct zonelist { ...@@ -237,7 +264,7 @@ struct zonelist {
struct bootmem_data; struct bootmem_data;
typedef struct pglist_data { typedef struct pglist_data {
struct zone node_zones[MAX_NR_ZONES]; struct zone node_zones[MAX_NR_ZONES];
struct zonelist node_zonelists[MAX_NR_ZONES]; struct zonelist node_zonelists[GFP_ZONETYPES];
int nr_zones; int nr_zones;
struct page *node_mem_map; struct page *node_mem_map;
struct bootmem_data *bdata; struct bootmem_data *bdata;
......
...@@ -1235,7 +1235,7 @@ static void __init build_zonelists(pg_data_t *pgdat) ...@@ -1235,7 +1235,7 @@ static void __init build_zonelists(pg_data_t *pgdat)
DECLARE_BITMAP(used_mask, MAX_NUMNODES); DECLARE_BITMAP(used_mask, MAX_NUMNODES);
/* initialize zonelists */ /* initialize zonelists */
for (i = 0; i < MAX_NR_ZONES; i++) { for (i = 0; i < GFP_ZONETYPES; i++) {
zonelist = pgdat->node_zonelists + i; zonelist = pgdat->node_zonelists + i;
memset(zonelist, 0, sizeof(*zonelist)); memset(zonelist, 0, sizeof(*zonelist));
zonelist->zones[0] = NULL; zonelist->zones[0] = NULL;
...@@ -1257,7 +1257,7 @@ static void __init build_zonelists(pg_data_t *pgdat) ...@@ -1257,7 +1257,7 @@ static void __init build_zonelists(pg_data_t *pgdat)
node_load[node] += load; node_load[node] += load;
prev_node = node; prev_node = node;
load--; load--;
for (i = 0; i < MAX_NR_ZONES; i++) { for (i = 0; i < GFP_ZONETYPES; i++) {
zonelist = pgdat->node_zonelists + i; zonelist = pgdat->node_zonelists + i;
for (j = 0; zonelist->zones[j] != NULL; j++); for (j = 0; zonelist->zones[j] != NULL; j++);
...@@ -1280,7 +1280,7 @@ static void __init build_zonelists(pg_data_t *pgdat) ...@@ -1280,7 +1280,7 @@ static void __init build_zonelists(pg_data_t *pgdat)
int i, j, k, node, local_node; int i, j, k, node, local_node;
local_node = pgdat->node_id; local_node = pgdat->node_id;
for (i = 0; i < MAX_NR_ZONES; i++) { for (i = 0; i < GFP_ZONETYPES; i++) {
struct zonelist *zonelist; struct zonelist *zonelist;
zonelist = pgdat->node_zonelists + i; zonelist = pgdat->node_zonelists + i;
...@@ -1840,7 +1840,7 @@ static void setup_per_zone_protection(void) ...@@ -1840,7 +1840,7 @@ static void setup_per_zone_protection(void)
* For each of the different allocation types: * For each of the different allocation types:
* GFP_DMA -> GFP_KERNEL -> GFP_HIGHMEM * GFP_DMA -> GFP_KERNEL -> GFP_HIGHMEM
*/ */
for (i = 0; i < MAX_NR_ZONES; i++) { for (i = 0; i < GFP_ZONETYPES; i++) {
/* /*
* For each of the zones: * For each of the zones:
* ZONE_HIGHMEM -> ZONE_NORMAL -> ZONE_DMA * ZONE_HIGHMEM -> ZONE_NORMAL -> ZONE_DMA
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment