diff options
author | WANG Cong <xiyou.wangcong@gmail.com> | 2007-12-17 19:19:59 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-12-17 22:28:16 -0500 |
commit | bbd0682596f7a434467ee551fee18d5f0b818539 (patch) | |
tree | 3afd7cbb301125fc21799a5fd9a70c2b5d700f17 | |
parent | af0cd5a7c3cded50c25e98acd94912d17a0eb914 (diff) |
mm/sparse.c: improve the error handling for sparse_add_one_section()
Improve the error handling for mm/sparse.c::sparse_add_one_section(). And I
see no reason to check 'usemap' until holding the 'pgdat_resize_lock'.
[geoffrey.levand@am.sony.com: sparse_index_init() returns -EEXIST]
Cc: Christoph Lameter <clameter@sgi.com>
Acked-by: Dave Hansen <haveblue@us.ibm.com>
Cc: Rik van Riel <riel@redhat.com>
Acked-by: Yasunori Goto <y-goto@jp.fujitsu.com>
Cc: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: WANG Cong <xiyou.wangcong@gmail.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | mm/sparse.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/mm/sparse.c b/mm/sparse.c index d245e59048a8..a2183cb5d524 100644 --- a/mm/sparse.c +++ b/mm/sparse.c | |||
@@ -391,9 +391,17 @@ int sparse_add_one_section(struct zone *zone, unsigned long start_pfn, | |||
391 | * no locking for this, because it does its own | 391 | * no locking for this, because it does its own |
392 | * plus, it does a kmalloc | 392 | * plus, it does a kmalloc |
393 | */ | 393 | */ |
394 | sparse_index_init(section_nr, pgdat->node_id); | 394 | ret = sparse_index_init(section_nr, pgdat->node_id); |
395 | if (ret < 0 && ret != -EEXIST) | ||
396 | return ret; | ||
395 | memmap = kmalloc_section_memmap(section_nr, pgdat->node_id, nr_pages); | 397 | memmap = kmalloc_section_memmap(section_nr, pgdat->node_id, nr_pages); |
398 | if (!memmap) | ||
399 | return -ENOMEM; | ||
396 | usemap = __kmalloc_section_usemap(); | 400 | usemap = __kmalloc_section_usemap(); |
401 | if (!usemap) { | ||
402 | __kfree_section_memmap(memmap, nr_pages); | ||
403 | return -ENOMEM; | ||
404 | } | ||
397 | 405 | ||
398 | pgdat_resize_lock(pgdat, &flags); | 406 | pgdat_resize_lock(pgdat, &flags); |
399 | 407 | ||
@@ -403,18 +411,16 @@ int sparse_add_one_section(struct zone *zone, unsigned long start_pfn, | |||
403 | goto out; | 411 | goto out; |
404 | } | 412 | } |
405 | 413 | ||
406 | if (!usemap) { | ||
407 | ret = -ENOMEM; | ||
408 | goto out; | ||
409 | } | ||
410 | ms->section_mem_map |= SECTION_MARKED_PRESENT; | 414 | ms->section_mem_map |= SECTION_MARKED_PRESENT; |
411 | 415 | ||
412 | ret = sparse_init_one_section(ms, section_nr, memmap, usemap); | 416 | ret = sparse_init_one_section(ms, section_nr, memmap, usemap); |
413 | 417 | ||
414 | out: | 418 | out: |
415 | pgdat_resize_unlock(pgdat, &flags); | 419 | pgdat_resize_unlock(pgdat, &flags); |
416 | if (ret <= 0) | 420 | if (ret <= 0) { |
421 | kfree(usemap); | ||
417 | __kfree_section_memmap(memmap, nr_pages); | 422 | __kfree_section_memmap(memmap, nr_pages); |
423 | } | ||
418 | return ret; | 424 | return ret; |
419 | } | 425 | } |
420 | #endif | 426 | #endif |