aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory_hotplug.c
diff options
context:
space:
mode:
authorYasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>2013-02-22 19:32:52 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-23 20:50:11 -0500
commit6677e3eaf4d78abd7b09133414c05dc3ec353e7f (patch)
tree62898a335513651e498d0ace2eb0f554d2ddc0bb /mm/memory_hotplug.c
parent993c1aad8f316dbafae6a0ec660ec846676838d6 (diff)
memory-hotplug: check whether all memory blocks are offlined or not when removing memory
We remove the memory like this: 1. lock memory hotplug 2. offline a memory block 3. unlock memory hotplug 4. repeat 1-3 to offline all memory blocks 5. lock memory hotplug 6. remove memory(TODO) 7. unlock memory hotplug All memory blocks must be offlined before removing memory. But we don't hold the lock in the whole operation. So we should check whether all memory blocks are offlined before step6. Otherwise, kernel maybe panicked. Offlining a memory block and removing a memory device can be two different operations. Users can just offline some memory blocks without removing the memory device. For this purpose, the kernel has held lock_memory_hotplug() in __offline_pages(). To reuse the code for memory hot-remove, we repeat step 1-3 to offline all the memory blocks, repeatedly lock and unlock memory hotplug, but not hold the memory hotplug lock in the whole operation. Signed-off-by: Wen Congyang <wency@cn.fujitsu.com> Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com> Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.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: 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>
Diffstat (limited to 'mm/memory_hotplug.c')
-rw-r--r--mm/memory_hotplug.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 6a82972aeae5..5d350f5c68e5 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1429,6 +1429,54 @@ repeat:
1429 goto repeat; 1429 goto repeat;
1430 } 1430 }
1431 1431
1432 lock_memory_hotplug();
1433
1434 /*
1435 * we have offlined all memory blocks like this:
1436 * 1. lock memory hotplug
1437 * 2. offline a memory block
1438 * 3. unlock memory hotplug
1439 *
1440 * repeat step1-3 to offline the memory block. All memory blocks
1441 * must be offlined before removing memory. But we don't hold the
1442 * lock in the whole operation. So we should check whether all
1443 * memory blocks are offlined.
1444 */
1445
1446 mem = NULL;
1447 for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
1448 section_nr = pfn_to_section_nr(pfn);
1449 if (!present_section_nr(section_nr))
1450 continue;
1451
1452 section = __nr_to_section(section_nr);
1453 /* same memblock? */
1454 if (mem)
1455 if ((section_nr >= mem->start_section_nr) &&
1456 (section_nr <= mem->end_section_nr))
1457 continue;
1458
1459 mem = find_memory_block_hinted(section, mem);
1460 if (!mem)
1461 continue;
1462
1463 ret = is_memblock_offlined(mem);
1464 if (!ret) {
1465 pr_warn("removing memory fails, because memory "
1466 "[%#010llx-%#010llx] is onlined\n",
1467 PFN_PHYS(section_nr_to_pfn(mem->start_section_nr)),
1468 PFN_PHYS(section_nr_to_pfn(mem->end_section_nr + 1)) - 1);
1469
1470 kobject_put(&mem->dev.kobj);
1471 unlock_memory_hotplug();
1472 return ret;
1473 }
1474 }
1475
1476 if (mem)
1477 kobject_put(&mem->dev.kobj);
1478 unlock_memory_hotplug();
1479
1432 return 0; 1480 return 0;
1433} 1481}
1434#else 1482#else