[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: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Acked-by: Andi Kleen <ak@suse.de> Cc: Christoph Lameter <clameter@sgi.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
b446b60e4e
commit
8af5e2eb3c
|
@ -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)
|
||||||
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)
|
||||||
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)
|
||||||
* 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;
|
||||||
|
|
Loading…
Reference in New Issue