Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
[sfrench/cifs-2.6.git] / mm / sparse.c
index e06f514fe04faa748c5e50e3f4cb25789d977238..f6a43c09c322cdb39077392ec1c77e9904c52d82 100644 (file)
@@ -83,6 +83,8 @@ static int __meminit sparse_index_init(unsigned long section_nr, int nid)
                return -EEXIST;
 
        section = sparse_index_alloc(nid);
+       if (!section)
+               return -ENOMEM;
        /*
         * This lock keeps two different sections from
         * reallocating for the same index
@@ -235,7 +237,7 @@ static unsigned long *__kmalloc_section_usemap(void)
 }
 #endif /* CONFIG_MEMORY_HOTPLUG */
 
-static unsigned long *sparse_early_usemap_alloc(unsigned long pnum)
+static unsigned long *__init sparse_early_usemap_alloc(unsigned long pnum)
 {
        unsigned long *usemap;
        struct mem_section *ms = __nr_to_section(pnum);
@@ -351,17 +353,9 @@ static inline struct page *kmalloc_section_memmap(unsigned long pnum, int nid,
        return __kmalloc_section_memmap(nr_pages);
 }
 
-static int vaddr_in_vmalloc_area(void *addr)
-{
-       if (addr >= (void *)VMALLOC_START &&
-           addr < (void *)VMALLOC_END)
-               return 1;
-       return 0;
-}
-
 static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
 {
-       if (vaddr_in_vmalloc_area(memmap))
+       if (is_vmalloc_addr(memmap))
                vfree(memmap);
        else
                free_pages((unsigned long)memmap,
@@ -389,9 +383,17 @@ int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
         * no locking for this, because it does its own
         * plus, it does a kmalloc
         */
-       sparse_index_init(section_nr, pgdat->node_id);
+       ret = sparse_index_init(section_nr, pgdat->node_id);
+       if (ret < 0 && ret != -EEXIST)
+               return ret;
        memmap = kmalloc_section_memmap(section_nr, pgdat->node_id, nr_pages);
+       if (!memmap)
+               return -ENOMEM;
        usemap = __kmalloc_section_usemap();
+       if (!usemap) {
+               __kfree_section_memmap(memmap, nr_pages);
+               return -ENOMEM;
+       }
 
        pgdat_resize_lock(pgdat, &flags);
 
@@ -401,18 +403,16 @@ int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
                goto out;
        }
 
-       if (!usemap) {
-               ret = -ENOMEM;
-               goto out;
-       }
        ms->section_mem_map |= SECTION_MARKED_PRESENT;
 
        ret = sparse_init_one_section(ms, section_nr, memmap, usemap);
 
 out:
        pgdat_resize_unlock(pgdat, &flags);
-       if (ret <= 0)
+       if (ret <= 0) {
+               kfree(usemap);
                __kfree_section_memmap(memmap, nr_pages);
+       }
        return ret;
 }
 #endif