aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTang Chen <tangchen@cn.fujitsu.com>2013-02-22 19:33:14 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-23 20:50:13 -0500
commit60a5a19e7419ba0bc22ed01b3285e8940b42944c (patch)
treeab50aec968bd3386c53c8611f9e0215910daa6bd
parent815121d2b5cd56f1757d4468dc3abadd06a0ed6b (diff)
memory-hotplug: remove sysfs file of node
Introduce 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. Signed-off-by: Wen Congyang <wency@cn.fujitsu.com> Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Jiang Liu <jiang.liu@huawei.com> Cc: Jianguo Wu <wujianguo@huawei.com> Cc: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Cc: Wu Jianguo <wujianguo@huawei.com> Cc: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: "H. Peter Anvin" <hpa@zytor.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/acpi/acpi_memhotplug.c8
-rw-r--r--include/linux/memory_hotplug.h2
-rw-r--r--mm/memory_hotplug.c58
3 files changed, 63 insertions, 5 deletions
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 034d3e72aa92..da1f82b445e0 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -280,9 +280,11 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
280 280
281static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device) 281static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
282{ 282{
283 int result = 0; 283 int result = 0, nid;
284 struct acpi_memory_info *info, *n; 284 struct acpi_memory_info *info, *n;
285 285
286 nid = acpi_get_node(mem_device->device->handle);
287
286 list_for_each_entry_safe(info, n, &mem_device->res_list, list) { 288 list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
287 if (info->failed) 289 if (info->failed)
288 /* The kernel does not use this memory block */ 290 /* The kernel does not use this memory block */
@@ -295,7 +297,9 @@ static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
295 */ 297 */
296 return -EBUSY; 298 return -EBUSY;
297 299
298 result = remove_memory(info->start_addr, info->length); 300 if (nid < 0)
301 nid = memory_add_physaddr_to_nid(info->start_addr);
302 result = remove_memory(nid, info->start_addr, info->length);
299 if (result) 303 if (result)
300 return result; 304 return result;
301 305
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 4d523fe75ba1..69903ccf549e 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -248,7 +248,7 @@ extern int arch_add_memory(int nid, u64 start, u64 size);
248extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages); 248extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages);
249extern int offline_memory_block(struct memory_block *mem); 249extern int offline_memory_block(struct memory_block *mem);
250extern bool is_memblock_offlined(struct memory_block *mem); 250extern bool is_memblock_offlined(struct memory_block *mem);
251extern int remove_memory(u64 start, u64 size); 251extern int remove_memory(int nid, u64 start, u64 size);
252extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn, 252extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
253 int nr_pages); 253 int nr_pages);
254extern void sparse_remove_one_section(struct zone *zone, struct mem_section *ms); 254extern void sparse_remove_one_section(struct zone *zone, struct mem_section *ms);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 3f792375f326..aea6374f435a 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -29,6 +29,7 @@
29#include <linux/suspend.h> 29#include <linux/suspend.h>
30#include <linux/mm_inline.h> 30#include <linux/mm_inline.h>
31#include <linux/firmware-map.h> 31#include <linux/firmware-map.h>
32#include <linux/stop_machine.h>
32 33
33#include <asm/tlbflush.h> 34#include <asm/tlbflush.h>
34 35
@@ -1679,7 +1680,58 @@ static int is_memblock_offlined_cb(struct memory_block *mem, void *arg)
1679 return ret; 1680 return ret;
1680} 1681}
1681 1682
1682int __ref remove_memory(u64 start, u64 size) 1683static int check_cpu_on_node(void *data)
1684{
1685 struct pglist_data *pgdat = data;
1686 int cpu;
1687
1688 for_each_present_cpu(cpu) {
1689 if (cpu_to_node(cpu) == pgdat->node_id)
1690 /*
1691 * the cpu on this node isn't removed, and we can't
1692 * offline this node.
1693 */
1694 return -EBUSY;
1695 }
1696
1697 return 0;
1698}
1699
1700/* offline the node if all memory sections of this node are removed */
1701static void try_offline_node(int nid)
1702{
1703 unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn;
1704 unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_spanned_pages;
1705 unsigned long pfn;
1706
1707 for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
1708 unsigned long section_nr = pfn_to_section_nr(pfn);
1709
1710 if (!present_section_nr(section_nr))
1711 continue;
1712
1713 if (pfn_to_nid(pfn) != nid)
1714 continue;
1715
1716 /*
1717 * some memory sections of this node are not removed, and we
1718 * can't offline node now.
1719 */
1720 return;
1721 }
1722
1723 if (stop_machine(check_cpu_on_node, NODE_DATA(nid), NULL))
1724 return;
1725
1726 /*
1727 * all memory/cpu of this node are removed, we can offline this
1728 * node now.
1729 */
1730 node_set_offline(nid);
1731 unregister_one_node(nid);
1732}
1733
1734int __ref remove_memory(int nid, u64 start, u64 size)
1683{ 1735{
1684 unsigned long start_pfn, end_pfn; 1736 unsigned long start_pfn, end_pfn;
1685 int ret = 0; 1737 int ret = 0;
@@ -1734,6 +1786,8 @@ repeat:
1734 1786
1735 arch_remove_memory(start, size); 1787 arch_remove_memory(start, size);
1736 1788
1789 try_offline_node(nid);
1790
1737 unlock_memory_hotplug(); 1791 unlock_memory_hotplug();
1738 1792
1739 return 0; 1793 return 0;
@@ -1743,7 +1797,7 @@ int offline_pages(unsigned long start_pfn, unsigned long nr_pages)
1743{ 1797{
1744 return -EINVAL; 1798 return -EINVAL;
1745} 1799}
1746int remove_memory(u64 start, u64 size) 1800int remove_memory(int nid, u64 start, u64 size)
1747{ 1801{
1748 return -EINVAL; 1802 return -EINVAL;
1749} 1803}