Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] sparsemem extreme: hotplug preparation

This splits up sparse_index_alloc() into two pieces. This is needed
because we'll allocate the memory for the second level in a different place
from where we actually consume it to keep the allocation from happening
underneath a lock

Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
Signed-off-by: Bob Picco <bob.picco@hp.com>
Cc: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Dave Hansen and committed by
Linus Torvalds
28ae55c9 3e347261

+45 -15
+1
include/linux/mmzone.h
··· 588 588 void sparse_init(void); 589 589 #else 590 590 #define sparse_init() do {} while (0) 591 + #define sparse_index_init(_sec, _nid) do {} while (0) 591 592 #endif /* CONFIG_SPARSEMEM */ 592 593 593 594 #ifdef CONFIG_NODES_SPAN_OTHER_NODES
+44 -15
mm/sparse.c
··· 6 6 #include <linux/mmzone.h> 7 7 #include <linux/bootmem.h> 8 8 #include <linux/module.h> 9 + #include <linux/spinlock.h> 9 10 #include <asm/dma.h> 10 11 11 12 /* ··· 23 22 #endif 24 23 EXPORT_SYMBOL(mem_section); 25 24 26 - static void sparse_alloc_root(unsigned long root, int nid) 27 - { 28 25 #ifdef CONFIG_SPARSEMEM_EXTREME 29 - mem_section[root] = alloc_bootmem_node(NODE_DATA(nid), PAGE_SIZE); 30 - #endif 31 - } 32 - 33 - static void sparse_index_init(unsigned long section, int nid) 26 + static struct mem_section *sparse_index_alloc(int nid) 34 27 { 35 - unsigned long root = SECTION_NR_TO_ROOT(section); 28 + struct mem_section *section = NULL; 29 + unsigned long array_size = SECTIONS_PER_ROOT * 30 + sizeof(struct mem_section); 36 31 37 - if (mem_section[root]) 38 - return; 32 + section = alloc_bootmem_node(NODE_DATA(nid), array_size); 39 33 40 - sparse_alloc_root(root, nid); 34 + if (section) 35 + memset(section, 0, array_size); 41 36 42 - if (mem_section[root]) 43 - memset(mem_section[root], 0, PAGE_SIZE); 44 - else 45 - panic("memory_present: NO MEMORY\n"); 37 + return section; 46 38 } 39 + 40 + static int sparse_index_init(unsigned long section_nr, int nid) 41 + { 42 + static spinlock_t index_init_lock = SPIN_LOCK_UNLOCKED; 43 + unsigned long root = SECTION_NR_TO_ROOT(section_nr); 44 + struct mem_section *section; 45 + int ret = 0; 46 + 47 + if (mem_section[root]) 48 + return -EEXIST; 49 + 50 + section = sparse_index_alloc(nid); 51 + /* 52 + * This lock keeps two different sections from 53 + * reallocating for the same index 54 + */ 55 + spin_lock(&index_init_lock); 56 + 57 + if (mem_section[root]) { 58 + ret = -EEXIST; 59 + goto out; 60 + } 61 + 62 + mem_section[root] = section; 63 + out: 64 + spin_unlock(&index_init_lock); 65 + return ret; 66 + } 67 + #else /* !SPARSEMEM_EXTREME */ 68 + static inline int sparse_index_init(unsigned long section_nr, int nid) 69 + { 70 + return 0; 71 + } 72 + #endif 73 + 47 74 /* Record a memory area against a node. */ 48 75 void memory_present(int nid, unsigned long start, unsigned long end) 49 76 {