memory-hotplug: try to offline the memory twice to avoid dependence
authorWen Congyang <wency@cn.fujitsu.com>
Sat, 23 Feb 2013 00:32:50 +0000 (16:32 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 24 Feb 2013 01:50:11 +0000 (17:50 -0800)
memory can't be offlined when CONFIG_MEMCG is selected.  For example:
there is a memory device on node 1.  The address range is [1G, 1.5G).
You will find 4 new directories memory8, memory9, memory10, and memory11
under the directory /sys/devices/system/memory/.

If CONFIG_MEMCG is selected, we will allocate memory to store page
cgroup when we online pages.  When we online memory8, the memory stored
page cgroup is not provided by this memory device.  But when we online
memory9, the memory stored page cgroup may be provided by memory8.  So
we can't offline memory8 now.  We should offline the memory in the
reversed order.

When the memory device is hotremoved, we will auto offline memory
provided by this memory device.  But we don't know which memory is
onlined first, so offlining memory may fail.  In such case, iterate
twice to offline the memory.  1st iterate: offline every non primary
memory block.  2nd iterate: offline primary (i.e.  first added) memory
block.

This idea is suggested by KOSAKI Motohiro.

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>
mm/memory_hotplug.c

index 302291429953f53f740c89075f5bd54509f8cc1f..6a82972aeae59e2c23700b4e88951a29fb521746 100644 (file)
@@ -1387,10 +1387,13 @@ int remove_memory(u64 start, u64 size)
        unsigned long start_pfn, end_pfn;
        unsigned long pfn, section_nr;
        int ret;
+       int return_on_error = 0;
+       int retry = 0;
 
        start_pfn = PFN_DOWN(start);
        end_pfn = start_pfn + PFN_DOWN(size);
 
+repeat:
        for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
                section_nr = pfn_to_section_nr(pfn);
                if (!present_section_nr(section_nr))
@@ -1409,14 +1412,23 @@ int remove_memory(u64 start, u64 size)
 
                ret = offline_memory_block(mem);
                if (ret) {
-                       kobject_put(&mem->dev.kobj);
-                       return ret;
+                       if (return_on_error) {
+                               kobject_put(&mem->dev.kobj);
+                               return ret;
+                       } else {
+                               retry = 1;
+                       }
                }
        }
 
        if (mem)
                kobject_put(&mem->dev.kobj);
 
+       if (retry) {
+               return_on_error = 1;
+               goto repeat;
+       }
+
        return 0;
 }
 #else