[ 008/108] memory hotplug: fix section info double registration bug
3.2-stable review patch. If anyone has any objections, please let me know. -- From: qiuxishi commit f14851af0ebb32745c6c5a2e400aa0549f9d20df upstream. There may be a bug when registering section info. For example, on my Itanium platform, the pfn range of node0 includes the other nodes, so other nodes' section info will be double registered, and memmap's page count will equal to 3. node0: start_pfn=0x100,spanned_pfn=0x20fb00, present_pfn=0x7f8a3, => 0x000100-0x20fc00 node1: start_pfn=0x8, spanned_pfn=0x8, present_pfn=0x8, => 0x08-0x10 node2: start_pfn=0x10, spanned_pfn=0x8, present_pfn=0x8, => 0x10-0x18 node3: start_pfn=0x18, spanned_pfn=0x8, present_pfn=0x8, => 0x18-0x20 free_all_bootmem_node() register_page_bootmem_info_node() register_page_bootmem_info_section() When hot remove memory, we can't free the memmap's page because page_count() is 2 after put_page_bootmem(). sparse_remove_one_section() free_section_usemap() free_map_bootmem() put_page_bootmem() [a...@linux-foundation.org: add code comment] Signed-off-by: Xishi Qiu Signed-off-by: Jiang Liu Acked-by: Mel Gorman Cc: "Luck, Tony" Cc: Yasuaki Ishimatsu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Ben Hutchings --- mm/memory_hotplug.c | 16 ++-- 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 3ad25f9..6a5b90d 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -126,9 +126,6 @@ static void register_page_bootmem_info_section(unsigned long start_pfn) struct mem_section *ms; struct page *page, *memmap; - if (!pfn_valid(start_pfn)) - return; - section_nr = pfn_to_section_nr(start_pfn); ms = __nr_to_section(section_nr); @@ -187,9 +184,16 @@ void register_page_bootmem_info_node(struct pglist_data *pgdat) end_pfn = pfn + pgdat->node_spanned_pages; /* register_section info */ - for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) - register_page_bootmem_info_section(pfn); - + for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) { + /* +* Some platforms can assign the same pfn to multiple nodes - on +* node0 as well as nodeN. To avoid registering a pfn against +* multiple nodes we check that this pfn does not already +* reside in some other node. +*/ + if (pfn_valid(pfn) && (pfn_to_nid(pfn) == node)) + register_page_bootmem_info_section(pfn); + } } #endif /* !CONFIG_SPARSEMEM_VMEMMAP */ -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[ 008/108] memory hotplug: fix section info double registration bug
3.2-stable review patch. If anyone has any objections, please let me know. -- From: qiuxishi qiuxi...@gmail.com commit f14851af0ebb32745c6c5a2e400aa0549f9d20df upstream. There may be a bug when registering section info. For example, on my Itanium platform, the pfn range of node0 includes the other nodes, so other nodes' section info will be double registered, and memmap's page count will equal to 3. node0: start_pfn=0x100,spanned_pfn=0x20fb00, present_pfn=0x7f8a3, = 0x000100-0x20fc00 node1: start_pfn=0x8, spanned_pfn=0x8, present_pfn=0x8, = 0x08-0x10 node2: start_pfn=0x10, spanned_pfn=0x8, present_pfn=0x8, = 0x10-0x18 node3: start_pfn=0x18, spanned_pfn=0x8, present_pfn=0x8, = 0x18-0x20 free_all_bootmem_node() register_page_bootmem_info_node() register_page_bootmem_info_section() When hot remove memory, we can't free the memmap's page because page_count() is 2 after put_page_bootmem(). sparse_remove_one_section() free_section_usemap() free_map_bootmem() put_page_bootmem() [a...@linux-foundation.org: add code comment] Signed-off-by: Xishi Qiu qiuxi...@huawei.com Signed-off-by: Jiang Liu jiang@huawei.com Acked-by: Mel Gorman mgor...@suse.de Cc: Luck, Tony tony.l...@intel.com Cc: Yasuaki Ishimatsu isimatu.yasu...@jp.fujitsu.com Signed-off-by: Andrew Morton a...@linux-foundation.org Signed-off-by: Linus Torvalds torva...@linux-foundation.org Signed-off-by: Ben Hutchings b...@decadent.org.uk --- mm/memory_hotplug.c | 16 ++-- 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 3ad25f9..6a5b90d 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -126,9 +126,6 @@ static void register_page_bootmem_info_section(unsigned long start_pfn) struct mem_section *ms; struct page *page, *memmap; - if (!pfn_valid(start_pfn)) - return; - section_nr = pfn_to_section_nr(start_pfn); ms = __nr_to_section(section_nr); @@ -187,9 +184,16 @@ void register_page_bootmem_info_node(struct pglist_data *pgdat) end_pfn = pfn + pgdat-node_spanned_pages; /* register_section info */ - for (; pfn end_pfn; pfn += PAGES_PER_SECTION) - register_page_bootmem_info_section(pfn); - + for (; pfn end_pfn; pfn += PAGES_PER_SECTION) { + /* +* Some platforms can assign the same pfn to multiple nodes - on +* node0 as well as nodeN. To avoid registering a pfn against +* multiple nodes we check that this pfn does not already +* reside in some other node. +*/ + if (pfn_valid(pfn) (pfn_to_nid(pfn) == node)) + register_page_bootmem_info_section(pfn); + } } #endif /* !CONFIG_SPARSEMEM_VMEMMAP */ -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/