Commit 8af5e2eb authored by KAMEZAWA Hiroyuki's avatar KAMEZAWA Hiroyuki Committed by Linus Torvalds

[PATCH] fix mempolicy's check on a system with memory-less-node

bind_zonelist() can create zero-length zonelist if there is a
memory-less-node.  This patch checks the length of zonelist.  If length is
0, returns -EINVAL.

tested on ia64/NUMA with memory-less-node.
Signed-off-by: default avatarKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Acked-by: default avatarAndi Kleen <ak@suse.de>
Cc: Christoph Lameter <clameter@sgi.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent b446b60e
...@@ -144,7 +144,7 @@ static struct zonelist *bind_zonelist(nodemask_t *nodes) ...@@ -144,7 +144,7 @@ static struct zonelist *bind_zonelist(nodemask_t *nodes)
max++; /* space for zlcache_ptr (see mmzone.h) */ max++; /* space for zlcache_ptr (see mmzone.h) */
zl = kmalloc(sizeof(struct zone *) * max, GFP_KERNEL); zl = kmalloc(sizeof(struct zone *) * max, GFP_KERNEL);
if (!zl) if (!zl)
return NULL; return ERR_PTR(-ENOMEM);
zl->zlcache_ptr = NULL; zl->zlcache_ptr = NULL;
num = 0; num = 0;
/* First put in the highest zones from all nodes, then all the next /* First put in the highest zones from all nodes, then all the next
...@@ -162,6 +162,10 @@ static struct zonelist *bind_zonelist(nodemask_t *nodes) ...@@ -162,6 +162,10 @@ static struct zonelist *bind_zonelist(nodemask_t *nodes)
break; break;
k--; k--;
} }
if (num == 0) {
kfree(zl);
return ERR_PTR(-EINVAL);
}
zl->zones[num] = NULL; zl->zones[num] = NULL;
return zl; return zl;
} }
...@@ -193,9 +197,10 @@ static struct mempolicy *mpol_new(int mode, nodemask_t *nodes) ...@@ -193,9 +197,10 @@ static struct mempolicy *mpol_new(int mode, nodemask_t *nodes)
break; break;
case MPOL_BIND: case MPOL_BIND:
policy->v.zonelist = bind_zonelist(nodes); policy->v.zonelist = bind_zonelist(nodes);
if (policy->v.zonelist == NULL) { if (IS_ERR(policy->v.zonelist)) {
void *error_code = policy->v.zonelist;
kmem_cache_free(policy_cache, policy); kmem_cache_free(policy_cache, policy);
return ERR_PTR(-ENOMEM); return error_code;
} }
break; break;
} }
...@@ -1667,7 +1672,7 @@ void mpol_rebind_policy(struct mempolicy *pol, const nodemask_t *newmask) ...@@ -1667,7 +1672,7 @@ void mpol_rebind_policy(struct mempolicy *pol, const nodemask_t *newmask)
* then zonelist_policy() will "FALL THROUGH" to MPOL_DEFAULT. * then zonelist_policy() will "FALL THROUGH" to MPOL_DEFAULT.
*/ */
if (zonelist) { if (!IS_ERR(zonelist)) {
/* Good - got mem - substitute new zonelist */ /* Good - got mem - substitute new zonelist */
kfree(pol->v.zonelist); kfree(pol->v.zonelist);
pol->v.zonelist = zonelist; pol->v.zonelist = zonelist;
......
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