diff options
Diffstat (limited to 'mm/memory_hotplug.c')
-rw-r--r-- | mm/memory_hotplug.c | 50 |
1 files changed, 13 insertions, 37 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index d4b5f29906b9..c52aa05b106c 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -265,7 +265,7 @@ static int __meminit __add_section(int nid, unsigned long phys_start_pfn, | |||
265 | /* | 265 | /* |
266 | * Make all the pages reserved so that nobody will stumble over half | 266 | * Make all the pages reserved so that nobody will stumble over half |
267 | * initialized state. | 267 | * initialized state. |
268 | * FIXME: We also have to associate it with a node because pfn_to_node | 268 | * FIXME: We also have to associate it with a node because page_to_nid |
269 | * relies on having page with the proper node. | 269 | * relies on having page with the proper node. |
270 | */ | 270 | */ |
271 | for (i = 0; i < PAGES_PER_SECTION; i++) { | 271 | for (i = 0; i < PAGES_PER_SECTION; i++) { |
@@ -1590,11 +1590,11 @@ static void node_states_clear_node(int node, struct memory_notify *arg) | |||
1590 | } | 1590 | } |
1591 | 1591 | ||
1592 | static int __ref __offline_pages(unsigned long start_pfn, | 1592 | static int __ref __offline_pages(unsigned long start_pfn, |
1593 | unsigned long end_pfn, unsigned long timeout) | 1593 | unsigned long end_pfn) |
1594 | { | 1594 | { |
1595 | unsigned long pfn, nr_pages, expire; | 1595 | unsigned long pfn, nr_pages; |
1596 | long offlined_pages; | 1596 | long offlined_pages; |
1597 | int ret, drain, retry_max, node; | 1597 | int ret, node; |
1598 | unsigned long flags; | 1598 | unsigned long flags; |
1599 | unsigned long valid_start, valid_end; | 1599 | unsigned long valid_start, valid_end; |
1600 | struct zone *zone; | 1600 | struct zone *zone; |
@@ -1630,44 +1630,22 @@ static int __ref __offline_pages(unsigned long start_pfn, | |||
1630 | goto failed_removal; | 1630 | goto failed_removal; |
1631 | 1631 | ||
1632 | pfn = start_pfn; | 1632 | pfn = start_pfn; |
1633 | expire = jiffies + timeout; | ||
1634 | drain = 0; | ||
1635 | retry_max = 5; | ||
1636 | repeat: | 1633 | repeat: |
1637 | /* start memory hot removal */ | 1634 | /* start memory hot removal */ |
1638 | ret = -EAGAIN; | ||
1639 | if (time_after(jiffies, expire)) | ||
1640 | goto failed_removal; | ||
1641 | ret = -EINTR; | 1635 | ret = -EINTR; |
1642 | if (signal_pending(current)) | 1636 | if (signal_pending(current)) |
1643 | goto failed_removal; | 1637 | goto failed_removal; |
1644 | ret = 0; | 1638 | |
1645 | if (drain) { | 1639 | cond_resched(); |
1646 | lru_add_drain_all_cpuslocked(); | 1640 | lru_add_drain_all_cpuslocked(); |
1647 | cond_resched(); | 1641 | drain_all_pages(zone); |
1648 | drain_all_pages(zone); | ||
1649 | } | ||
1650 | 1642 | ||
1651 | pfn = scan_movable_pages(start_pfn, end_pfn); | 1643 | pfn = scan_movable_pages(start_pfn, end_pfn); |
1652 | if (pfn) { /* We have movable pages */ | 1644 | if (pfn) { /* We have movable pages */ |
1653 | ret = do_migrate_range(pfn, end_pfn); | 1645 | ret = do_migrate_range(pfn, end_pfn); |
1654 | if (!ret) { | 1646 | goto repeat; |
1655 | drain = 1; | ||
1656 | goto repeat; | ||
1657 | } else { | ||
1658 | if (ret < 0) | ||
1659 | if (--retry_max == 0) | ||
1660 | goto failed_removal; | ||
1661 | yield(); | ||
1662 | drain = 1; | ||
1663 | goto repeat; | ||
1664 | } | ||
1665 | } | 1647 | } |
1666 | /* drain all zone's lru pagevec, this is asynchronous... */ | 1648 | |
1667 | lru_add_drain_all_cpuslocked(); | ||
1668 | yield(); | ||
1669 | /* drain pcp pages, this is synchronous. */ | ||
1670 | drain_all_pages(zone); | ||
1671 | /* | 1649 | /* |
1672 | * dissolve free hugepages in the memory block before doing offlining | 1650 | * dissolve free hugepages in the memory block before doing offlining |
1673 | * actually in order to make hugetlbfs's object counting consistent. | 1651 | * actually in order to make hugetlbfs's object counting consistent. |
@@ -1677,10 +1655,8 @@ repeat: | |||
1677 | goto failed_removal; | 1655 | goto failed_removal; |
1678 | /* check again */ | 1656 | /* check again */ |
1679 | offlined_pages = check_pages_isolated(start_pfn, end_pfn); | 1657 | offlined_pages = check_pages_isolated(start_pfn, end_pfn); |
1680 | if (offlined_pages < 0) { | 1658 | if (offlined_pages < 0) |
1681 | ret = -EBUSY; | 1659 | goto repeat; |
1682 | goto failed_removal; | ||
1683 | } | ||
1684 | pr_info("Offlined Pages %ld\n", offlined_pages); | 1660 | pr_info("Offlined Pages %ld\n", offlined_pages); |
1685 | /* Ok, all of our target is isolated. | 1661 | /* Ok, all of our target is isolated. |
1686 | We cannot do rollback at this point. */ | 1662 | We cannot do rollback at this point. */ |
@@ -1728,7 +1704,7 @@ failed_removal: | |||
1728 | /* Must be protected by mem_hotplug_begin() or a device_lock */ | 1704 | /* Must be protected by mem_hotplug_begin() or a device_lock */ |
1729 | int offline_pages(unsigned long start_pfn, unsigned long nr_pages) | 1705 | int offline_pages(unsigned long start_pfn, unsigned long nr_pages) |
1730 | { | 1706 | { |
1731 | return __offline_pages(start_pfn, start_pfn + nr_pages, 120 * HZ); | 1707 | return __offline_pages(start_pfn, start_pfn + nr_pages); |
1732 | } | 1708 | } |
1733 | #endif /* CONFIG_MEMORY_HOTREMOVE */ | 1709 | #endif /* CONFIG_MEMORY_HOTREMOVE */ |
1734 | 1710 | ||