[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <506E451E.1050403@jp.fujitsu.com>
Date: Fri, 5 Oct 2012 11:25:34 +0900
From: Yasuaki Ishimatsu <isimatu.yasuaki@...fujitsu.com>
To: <x86@...nel.org>, <linux-mm@...ck.org>,
<linux-kernel@...r.kernel.org>, <linuxppc-dev@...ts.ozlabs.org>,
<linux-acpi@...r.kernel.org>, <linux-s390@...r.kernel.org>,
<linux-sh@...r.kernel.org>, <linux-ia64@...r.kernel.org>,
<cmetcalf@...era.com>, <sparclinux@...r.kernel.org>
CC: Yasuaki Ishimatsu <isimatu.yasuaki@...fujitsu.com>,
<rientjes@...gle.com>, <liuj97@...il.com>, <len.brown@...el.com>,
<cl@...ux.com>, <minchan.kim@...il.com>,
<akpm@...ux-foundation.org>, <kosaki.motohiro@...fujitsu.com>,
<wency@...fujitsu.com>
Subject: [PATCH 1/10] memory-hotplug : check whether memory is offline or
not when removing memory
When calling remove_memory(), the memory should be offline. If the function
is used to online memory, kernel panic may occur.
So the patch checks whether memory is offline or not.
CC: David Rientjes <rientjes@...gle.com>
CC: Jiang Liu <liuj97@...il.com>
CC: Len Brown <len.brown@...el.com>
CC: Christoph Lameter <cl@...ux.com>
Cc: Minchan Kim <minchan.kim@...il.com>
CC: Andrew Morton <akpm@...ux-foundation.org>
CC: KOSAKI Motohiro <kosaki.motohiro@...fujitsu.com>
Signed-off-by: Wen Congyang <wency@...fujitsu.com>
Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@...fujitsu.com>
---
drivers/base/memory.c | 39 +++++++++++++++++++++++++++++++++++++++
include/linux/memory.h | 5 +++++
mm/memory_hotplug.c | 17 +++++++++++++++--
3 files changed, 59 insertions(+), 2 deletions(-)
Index: linux-3.6/drivers/base/memory.c
===================================================================
--- linux-3.6.orig/drivers/base/memory.c 2012-10-04 14:22:57.000000000 +0900
+++ linux-3.6/drivers/base/memory.c 2012-10-04 14:45:46.653585860 +0900
@@ -70,6 +70,45 @@ void unregister_memory_isolate_notifier(
}
EXPORT_SYMBOL(unregister_memory_isolate_notifier);
+bool is_memblk_offline(unsigned long start, unsigned long size)
+{
+ struct memory_block *mem = NULL;
+ struct mem_section *section;
+ unsigned long start_pfn, end_pfn;
+ unsigned long pfn, section_nr;
+
+ start_pfn = PFN_DOWN(start);
+ end_pfn = PFN_UP(start + size);
+
+ for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+ section_nr = pfn_to_section_nr(pfn);
+ if (!present_section_nr(section_nr))
+ continue;
+
+ section = __nr_to_section(section_nr);
+ /* same memblock? */
+ if (mem)
+ if ((section_nr >= mem->start_section_nr) &&
+ (section_nr <= mem->end_section_nr))
+ continue;
+
+ mem = find_memory_block_hinted(section, mem);
+ if (!mem)
+ continue;
+ if (mem->state == MEM_OFFLINE)
+ continue;
+
+ kobject_put(&mem->dev.kobj);
+ return false;
+ }
+
+ if (mem)
+ kobject_put(&mem->dev.kobj);
+
+ return true;
+}
+EXPORT_SYMBOL(is_memblk_offline);
+
/*
* register_memory - Setup a sysfs device for a memory block
*/
Index: linux-3.6/include/linux/memory.h
===================================================================
--- linux-3.6.orig/include/linux/memory.h 2012-10-02 18:00:22.000000000 +0900
+++ linux-3.6/include/linux/memory.h 2012-10-04 14:44:40.902581028 +0900
@@ -106,6 +106,10 @@ static inline int memory_isolate_notify(
{
return 0;
}
+static inline bool is_memblk_offline(unsigned long start, unsigned long size)
+{
+ return false;
+}
#else
extern int register_memory_notifier(struct notifier_block *nb);
extern void unregister_memory_notifier(struct notifier_block *nb);
@@ -120,6 +124,7 @@ extern int memory_isolate_notify(unsigne
extern struct memory_block *find_memory_block_hinted(struct mem_section *,
struct memory_block *);
extern struct memory_block *find_memory_block(struct mem_section *);
+extern bool is_memblk_offline(unsigned long start, unsigned long size);
#define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT)
enum mem_add_context { BOOT, HOTPLUG };
#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
Index: linux-3.6/mm/memory_hotplug.c
===================================================================
--- linux-3.6.orig/mm/memory_hotplug.c 2012-10-04 14:31:08.000000000 +0900
+++ linux-3.6/mm/memory_hotplug.c 2012-10-04 14:58:22.449687986 +0900
@@ -1045,8 +1045,21 @@ int offline_memory(u64 start, u64 size)
int remove_memory(int nid, u64 start, u64 size)
{
- /* It is not implemented yet*/
- return 0;
+ int ret = 0;
+ lock_memory_hotplug();
+ /*
+ * The memory might become online by other task, even if you offine it.
+ * So we check whether the memory has been onlined or not.
+ */
+ if (!is_memblk_offline(start, size)) {
+ pr_warn("memory removing [mem %#010llx-%#010llx] failed, "
+ "because the memmory range is online\n",
+ start, start + size);
+ ret = -EAGAIN;
+ }
+
+ unlock_memory_hotplug();
+ return ret;
}
EXPORT_SYMBOL_GPL(remove_memory);
#else
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists