Commit 993c1aad8f316dbafae6a0ec660ec846676838d6

Authored by Wen Congyang
Committed by Linus Torvalds
1 parent a864b9d06c

memory-hotplug: try to offline the memory twice to avoid dependence

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>

Showing 1 changed file with 14 additions and 2 deletions Side-by-side Diff

... ... @@ -1387,10 +1387,13 @@
1387 1387 unsigned long start_pfn, end_pfn;
1388 1388 unsigned long pfn, section_nr;
1389 1389 int ret;
  1390 + int return_on_error = 0;
  1391 + int retry = 0;
1390 1392  
1391 1393 start_pfn = PFN_DOWN(start);
1392 1394 end_pfn = start_pfn + PFN_DOWN(size);
1393 1395  
  1396 +repeat:
1394 1397 for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
1395 1398 section_nr = pfn_to_section_nr(pfn);
1396 1399 if (!present_section_nr(section_nr))
1397 1400  
... ... @@ -1409,13 +1412,22 @@
1409 1412  
1410 1413 ret = offline_memory_block(mem);
1411 1414 if (ret) {
1412   - kobject_put(&mem->dev.kobj);
1413   - return ret;
  1415 + if (return_on_error) {
  1416 + kobject_put(&mem->dev.kobj);
  1417 + return ret;
  1418 + } else {
  1419 + retry = 1;
  1420 + }
1414 1421 }
1415 1422 }
1416 1423  
1417 1424 if (mem)
1418 1425 kobject_put(&mem->dev.kobj);
  1426 +
  1427 + if (retry) {
  1428 + return_on_error = 1;
  1429 + goto repeat;
  1430 + }
1419 1431  
1420 1432 return 0;
1421 1433 }