[RFC v9 PATCH 19/21] memory-hotplug: remove sysfs file of node
From: <hidden>
Date: 2012-09-05 09:45:08
Also in:
linux-acpi, linux-mm, linux-s390, linux-sh, lkml, sparclinux
Subsystem:
memory hot(un)plug, memory management, the rest · Maintainers:
David Hildenbrand, Oscar Salvador, Andrew Morton, Linus Torvalds
From: Wen Congyang <redacted> This patch introduces a new function try_offline_node() to remove sysfs file of node when all memory sections of this node are removed. If some memory sections of this node are not removed, this function does nothing. CC: David Rientjes <rientjes@google.com> CC: Jiang Liu <redacted> CC: Len Brown <redacted> CC: Benjamin Herrenschmidt <benh@kernel.crashing.org> CC: Paul Mackerras <redacted> CC: Christoph Lameter <redacted> Cc: Minchan Kim <redacted> CC: Andrew Morton <akpm@linux-foundation.org> CC: KOSAKI Motohiro <redacted> CC: Yasuaki Ishimatsu <redacted> Signed-off-by: Wen Congyang <redacted> --- mm/memory_hotplug.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 54 insertions(+), 0 deletions(-)
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index afda7e9..270c249 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c@@ -29,6 +29,7 @@ #include <linux/suspend.h> #include <linux/mm_inline.h> #include <linux/firmware-map.h> +#include <linux/stop_machine.h> #include <asm/tlbflush.h>
@@ -1285,6 +1286,57 @@ int offline_memory(u64 start, u64 size) return 0; } +static int check_cpu_on_node(void *data) +{ + struct pglist_data *pgdat = data; + int cpu; + + for_each_online_cpu(cpu) { + if (cpu_to_node(cpu) == pgdat->node_id) + /* + * the cpu on this node is onlined, and we can't + * offline this node. + */ + return -EBUSY; + } + + return 0; +} + +/* offline the node if all memory sections of this node are removed */ +static void try_offline_node(int nid) +{ + unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn; + unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_spanned_pages; + unsigned long pfn; + + for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) { + unsigned long section_nr = pfn_to_section_nr(pfn); + + if (!present_section_nr(section_nr)) + continue; + + if (pfn_to_nid(pfn) != nid) + continue; + + /* + * some memory sections of this node are not removed, and we + * can't offline node now. + */ + return; + } + + if (stop_machine(check_cpu_on_node, NODE_DATA(nid), NULL)) + return; + + /* + * all memory sections of this node are removed, we can offline this + * node now. + */ + node_set_offline(nid); + unregister_one_node(nid); +} + int __ref remove_memory(int nid, u64 start, u64 size) { int ret = 0;
@@ -1305,6 +1357,8 @@ int __ref remove_memory(int nid, u64 start, u64 size) firmware_map_remove(start, start + size, "System RAM"); arch_remove_memory(start, size); + + try_offline_node(nid); out: unlock_memory_hotplug(); return ret;
--
1.7.1