Commit dd942ae3 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[PATCH] Handle all and empty zones when setting up custom zonelists for mbind

The memory allocator doesn't like empty zones (which have an
uninitialized freelist), so a x86-64 system with a node fully
in GFP_DMA32 only would crash on mbind.

Fix that up by putting all possible zones as fallback into the zonelist
and skipping the empty ones.

In fact the code always enough allocated space for all zones,
but only used it for the highest. This change just uses all the
memory that was allocated before.

This should work fine for now, but whoever implements node hot removal
needs to fix this somewhere else too (or make sure zone datastructures
by itself never go away, only their memory)
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Acked-by: default avatarChristoph Lameter <clameter@sgi.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 759b650f
...@@ -132,19 +132,29 @@ static int mpol_check_policy(int mode, nodemask_t *nodes) ...@@ -132,19 +132,29 @@ static int mpol_check_policy(int mode, nodemask_t *nodes)
} }
return nodes_subset(*nodes, node_online_map) ? 0 : -EINVAL; return nodes_subset(*nodes, node_online_map) ? 0 : -EINVAL;
} }
/* Generate a custom zonelist for the BIND policy. */ /* Generate a custom zonelist for the BIND policy. */
static struct zonelist *bind_zonelist(nodemask_t *nodes) static struct zonelist *bind_zonelist(nodemask_t *nodes)
{ {
struct zonelist *zl; struct zonelist *zl;
int num, max, nd; int num, max, nd, k;
max = 1 + MAX_NR_ZONES * nodes_weight(*nodes); max = 1 + MAX_NR_ZONES * nodes_weight(*nodes);
zl = kmalloc(sizeof(void *) * max, GFP_KERNEL); zl = kmalloc(sizeof(struct zone *) * max, GFP_KERNEL);
if (!zl) if (!zl)
return NULL; return NULL;
num = 0; num = 0;
for_each_node_mask(nd, *nodes) /* First put in the highest zones from all nodes, then all the next
zl->zones[num++] = &NODE_DATA(nd)->node_zones[policy_zone]; lower zones etc. Avoid empty zones because the memory allocator
doesn't like them. If you implement node hot removal you
have to fix that. */
for (k = policy_zone; k >= 0; k--) {
for_each_node_mask(nd, *nodes) {
struct zone *z = &NODE_DATA(nd)->node_zones[k];
if (z->present_pages > 0)
zl->zones[num++] = z;
}
}
zl->zones[num] = NULL; zl->zones[num] = NULL;
return zl; return zl;
} }
......
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