aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory_hotplug.c
diff options
context:
space:
mode:
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