diff options
author | KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> | 2007-02-20 16:57:49 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-20 20:10:13 -0500 |
commit | 8af5e2eb3cc4450ffba9496c875beac41bf4f4f8 (patch) | |
tree | d15c56e8add1b53d5ed4d5dcb5d1f016d8f2b1c9 /mm/mempolicy.c | |
parent | b446b60e4eb5e5457120c4728ada871b1209c1d0 (diff) |
[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>
Diffstat (limited to 'mm/mempolicy.c')
-rw-r--r-- | mm/mempolicy.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 259a706bd83e..cf2a5381030a 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -144,7 +144,7 @@ static struct zonelist *bind_zonelist(nodemask_t *nodes) | |||
144 | max++; /* space for zlcache_ptr (see mmzone.h) */ | 144 | max++; /* space for zlcache_ptr (see mmzone.h) */ |
145 | zl = kmalloc(sizeof(struct zone *) * max, GFP_KERNEL); | 145 | zl = kmalloc(sizeof(struct zone *) * max, GFP_KERNEL); |
146 | if (!zl) | 146 | if (!zl) |
147 | return NULL; | 147 | return ERR_PTR(-ENOMEM); |
148 | zl->zlcache_ptr = NULL; | 148 | zl->zlcache_ptr = NULL; |
149 | num = 0; | 149 | num = 0; |
150 | /* First put in the highest zones from all nodes, then all the next | 150 | /* 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 | break; | 162 | break; |
163 | k--; | 163 | k--; |
164 | } | 164 | } |
165 | if (num == 0) { | ||
166 | kfree(zl); | ||
167 | return ERR_PTR(-EINVAL); | ||
168 | } | ||
165 | zl->zones[num] = NULL; | 169 | zl->zones[num] = NULL; |
166 | return zl; | 170 | return zl; |
167 | } | 171 | } |
@@ -193,9 +197,10 @@ static struct mempolicy *mpol_new(int mode, nodemask_t *nodes) | |||
193 | break; | 197 | break; |
194 | case MPOL_BIND: | 198 | case MPOL_BIND: |
195 | policy->v.zonelist = bind_zonelist(nodes); | 199 | policy->v.zonelist = bind_zonelist(nodes); |
196 | if (policy->v.zonelist == NULL) { | 200 | if (IS_ERR(policy->v.zonelist)) { |
201 | void *error_code = policy->v.zonelist; | ||
197 | kmem_cache_free(policy_cache, policy); | 202 | kmem_cache_free(policy_cache, policy); |
198 | return ERR_PTR(-ENOMEM); | 203 | return error_code; |
199 | } | 204 | } |
200 | break; | 205 | break; |
201 | } | 206 | } |
@@ -1667,7 +1672,7 @@ void mpol_rebind_policy(struct mempolicy *pol, const nodemask_t *newmask) | |||
1667 | * then zonelist_policy() will "FALL THROUGH" to MPOL_DEFAULT. | 1672 | * then zonelist_policy() will "FALL THROUGH" to MPOL_DEFAULT. |
1668 | */ | 1673 | */ |
1669 | 1674 | ||
1670 | if (zonelist) { | 1675 | if (!IS_ERR(zonelist)) { |
1671 | /* Good - got mem - substitute new zonelist */ | 1676 | /* Good - got mem - substitute new zonelist */ |
1672 | kfree(pol->v.zonelist); | 1677 | kfree(pol->v.zonelist); |
1673 | pol->v.zonelist = zonelist; | 1678 | pol->v.zonelist = zonelist; |