aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory_hotplug.c
diff options
context:
space:
mode:
authorWen Congyang <wency@cn.fujitsu.com>2012-10-08 19:34:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-09 03:23:02 -0400
commite90bdb7f52f94204c78fb40b0804645defdebd71 (patch)
tree4acb09ecd1f98fd98408f18e816d075601585d2a /mm/memory_hotplug.c
parenta16cee10c7ab994546ed98d9abfd4de74050124a (diff)
memory-hotplug: update memory block's state and notify userspace
remove_memory() will be called when hot removing a memory device. But even if offlining memory, we cannot notice it. So the patch updates the memory block's state and sends notification to userspace. Additionally, the memory device may contain more than one memory block. If the memory block has been offlined, __offline_pages() will fail. So we should try to offline one memory block at a time. Thus remove_memory() also check each memory block's state. So there is no need to check the memory block's state before calling remove_memory(). Signed-off-by: Wen Congyang <wency@cn.fujitsu.com> Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Cc: David Rientjes <rientjes@google.com> Cc: Jiang Liu <liuj97@gmail.com> Cc: Len Brown <len.brown@intel.com> Cc: Christoph Lameter <cl@linux.com> Cc: Minchan Kim <minchan.kim@gmail.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/memory_hotplug.c')
-rw-r--r--mm/memory_hotplug.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index dfc0a6134c7c..7d0797475a47 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1014,11 +1014,42 @@ int offline_pages(unsigned long start_pfn, unsigned long nr_pages)
1014 1014
1015int remove_memory(u64 start, u64 size) 1015int remove_memory(u64 start, u64 size)
1016{ 1016{
1017 struct memory_block *mem = NULL;
1018 struct mem_section *section;
1017 unsigned long start_pfn, end_pfn; 1019 unsigned long start_pfn, end_pfn;
1020 unsigned long pfn, section_nr;
1021 int ret;
1018 1022
1019 start_pfn = PFN_DOWN(start); 1023 start_pfn = PFN_DOWN(start);
1020 end_pfn = start_pfn + PFN_DOWN(size); 1024 end_pfn = start_pfn + PFN_DOWN(size);
1021 return __offline_pages(start_pfn, end_pfn, 120 * HZ); 1025
1026 for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
1027 section_nr = pfn_to_section_nr(pfn);
1028 if (!present_section_nr(section_nr))
1029 continue;
1030
1031 section = __nr_to_section(section_nr);
1032 /* same memblock? */
1033 if (mem)
1034 if ((section_nr >= mem->start_section_nr) &&
1035 (section_nr <= mem->end_section_nr))
1036 continue;
1037
1038 mem = find_memory_block_hinted(section, mem);
1039 if (!mem)
1040 continue;
1041
1042 ret = offline_memory_block(mem);
1043 if (ret) {
1044 kobject_put(&mem->dev.kobj);
1045 return ret;
1046 }
1047 }
1048
1049 if (mem)
1050 kobject_put(&mem->dev.kobj);
1051
1052 return 0;
1022} 1053}
1023#else 1054#else
1024int offline_pages(unsigned long start_pfn, unsigned long nr_pages) 1055int offline_pages(unsigned long start_pfn, unsigned long nr_pages)