X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=mm%2Fsparse.c;h=347249a4917afa922f4c8ae5d38fbfe81c189a5a;hb=d44ed4f86892e350f4b16a3489b7e7c1a9bb7ead;hp=b2b456bf0a5d03cb10ceb3c3cd63443040a47137;hpb=802f192e4a600f7ef84ca25c8b818c8830acef5a;p=linux-2.6 diff --git a/mm/sparse.c b/mm/sparse.c index b2b456bf0a..347249a491 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -6,6 +6,7 @@ #include #include #include +#include #include /* @@ -13,27 +14,63 @@ * * 1) mem_section - memory sections, mem_map's for valid memory */ -#ifdef CONFIG_ARCH_SPARSEMEM_EXTREME +#ifdef CONFIG_SPARSEMEM_EXTREME struct mem_section *mem_section[NR_SECTION_ROOTS] ____cacheline_maxaligned_in_smp; +#else +struct mem_section mem_section[NR_SECTION_ROOTS][SECTIONS_PER_ROOT] + ____cacheline_maxaligned_in_smp; +#endif +EXPORT_SYMBOL(mem_section); -static void sparse_index_init(unsigned long section, int nid) +#ifdef CONFIG_SPARSEMEM_EXTREME +static struct mem_section *sparse_index_alloc(int nid) { - unsigned long root = SECTION_TO_ROOT(section); + struct mem_section *section = NULL; + unsigned long array_size = SECTIONS_PER_ROOT * + sizeof(struct mem_section); + + section = alloc_bootmem_node(NODE_DATA(nid), array_size); + + if (section) + memset(section, 0, array_size); + + return section; +} + +static int sparse_index_init(unsigned long section_nr, int nid) +{ + static spinlock_t index_init_lock = SPIN_LOCK_UNLOCKED; + unsigned long root = SECTION_NR_TO_ROOT(section_nr); + struct mem_section *section; + int ret = 0; if (mem_section[root]) - return; - mem_section[root] = alloc_bootmem_node(NODE_DATA(nid), PAGE_SIZE); - if (mem_section[root]) - memset(mem_section[root], 0, PAGE_SIZE); - else - panic("memory_present: NO MEMORY\n"); + return -EEXIST; + + section = sparse_index_alloc(nid); + /* + * This lock keeps two different sections from + * reallocating for the same index + */ + spin_lock(&index_init_lock); + + if (mem_section[root]) { + ret = -EEXIST; + goto out; + } + + mem_section[root] = section; +out: + spin_unlock(&index_init_lock); + return ret; +} +#else /* !SPARSEMEM_EXTREME */ +static inline int sparse_index_init(unsigned long section_nr, int nid) +{ + return 0; } -#else -struct mem_section mem_section[NR_MEM_SECTIONS] - ____cacheline_maxaligned_in_smp; #endif -EXPORT_SYMBOL(mem_section); /* Record a memory area against a node. */ void memory_present(int nid, unsigned long start, unsigned long end)