diff options
author | Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> | 2016-01-15 19:57:43 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-15 20:56:32 -0500 |
commit | acc14dc4bd484f1fc8c227dd9fc2a1e592312d2b (patch) | |
tree | c7c15039ad08887ad1d17f0783e9e27442a1aa04 /mm | |
parent | 4aae8d1c051ea00b456da6811bc36d1f69de5445 (diff) |
mm: soft-offline: clean up soft_offline_page()
soft_offline_page() has some deeply indented code, that's the sign of
demand for cleanup. So let's do this. No functionality change.
Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: "Kirill A. Shutemov" <kirill@shutemov.name>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/memory-failure.c | 78 |
1 files changed, 47 insertions, 31 deletions
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 1b99403d76f2..2015c9a06cae 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
@@ -1684,6 +1684,49 @@ static int __soft_offline_page(struct page *page, int flags) | |||
1684 | return ret; | 1684 | return ret; |
1685 | } | 1685 | } |
1686 | 1686 | ||
1687 | static int soft_offline_in_use_page(struct page *page, int flags) | ||
1688 | { | ||
1689 | int ret; | ||
1690 | struct page *hpage = compound_head(page); | ||
1691 | |||
1692 | if (!PageHuge(page) && PageTransHuge(hpage)) { | ||
1693 | lock_page(hpage); | ||
1694 | ret = split_huge_page(hpage); | ||
1695 | unlock_page(hpage); | ||
1696 | if (unlikely(ret || PageTransCompound(page) || | ||
1697 | !PageAnon(page))) { | ||
1698 | pr_info("soft offline: %#lx: failed to split THP\n", | ||
1699 | page_to_pfn(page)); | ||
1700 | if (flags & MF_COUNT_INCREASED) | ||
1701 | put_hwpoison_page(hpage); | ||
1702 | return -EBUSY; | ||
1703 | } | ||
1704 | get_hwpoison_page(page); | ||
1705 | put_hwpoison_page(hpage); | ||
1706 | } | ||
1707 | |||
1708 | if (PageHuge(page)) | ||
1709 | ret = soft_offline_huge_page(page, flags); | ||
1710 | else | ||
1711 | ret = __soft_offline_page(page, flags); | ||
1712 | |||
1713 | return ret; | ||
1714 | } | ||
1715 | |||
1716 | static void soft_offline_free_page(struct page *page) | ||
1717 | { | ||
1718 | if (PageHuge(page)) { | ||
1719 | struct page *hpage = compound_head(page); | ||
1720 | |||
1721 | set_page_hwpoison_huge_page(hpage); | ||
1722 | if (!dequeue_hwpoisoned_huge_page(hpage)) | ||
1723 | num_poisoned_pages_add(1 << compound_order(hpage)); | ||
1724 | } else { | ||
1725 | if (!TestSetPageHWPoison(page)) | ||
1726 | num_poisoned_pages_inc(); | ||
1727 | } | ||
1728 | } | ||
1729 | |||
1687 | /** | 1730 | /** |
1688 | * soft_offline_page - Soft offline a page. | 1731 | * soft_offline_page - Soft offline a page. |
1689 | * @page: page to offline | 1732 | * @page: page to offline |
@@ -1710,7 +1753,6 @@ int soft_offline_page(struct page *page, int flags) | |||
1710 | { | 1753 | { |
1711 | int ret; | 1754 | int ret; |
1712 | unsigned long pfn = page_to_pfn(page); | 1755 | unsigned long pfn = page_to_pfn(page); |
1713 | struct page *hpage = compound_head(page); | ||
1714 | 1756 | ||
1715 | if (PageHWPoison(page)) { | 1757 | if (PageHWPoison(page)) { |
1716 | pr_info("soft offline: %#lx page already poisoned\n", pfn); | 1758 | pr_info("soft offline: %#lx page already poisoned\n", pfn); |
@@ -1723,36 +1765,10 @@ int soft_offline_page(struct page *page, int flags) | |||
1723 | ret = get_any_page(page, pfn, flags); | 1765 | ret = get_any_page(page, pfn, flags); |
1724 | put_online_mems(); | 1766 | put_online_mems(); |
1725 | 1767 | ||
1726 | if (ret > 0) { /* for in-use pages */ | 1768 | if (ret > 0) |
1727 | if (!PageHuge(page) && PageTransHuge(hpage)) { | 1769 | ret = soft_offline_in_use_page(page, flags); |
1728 | lock_page(hpage); | 1770 | else if (ret == 0) |
1729 | ret = split_huge_page(hpage); | 1771 | soft_offline_free_page(page); |
1730 | unlock_page(hpage); | ||
1731 | if (unlikely(ret || PageTransCompound(page) || | ||
1732 | !PageAnon(page))) { | ||
1733 | pr_info("soft offline: %#lx: failed to split THP\n", | ||
1734 | pfn); | ||
1735 | if (flags & MF_COUNT_INCREASED) | ||
1736 | put_hwpoison_page(hpage); | ||
1737 | return -EBUSY; | ||
1738 | } | ||
1739 | get_hwpoison_page(page); | ||
1740 | put_hwpoison_page(hpage); | ||
1741 | } | ||
1742 | 1772 | ||
1743 | if (PageHuge(page)) | ||
1744 | ret = soft_offline_huge_page(page, flags); | ||
1745 | else | ||
1746 | ret = __soft_offline_page(page, flags); | ||
1747 | } else if (ret == 0) { /* for free pages */ | ||
1748 | if (PageHuge(page)) { | ||
1749 | set_page_hwpoison_huge_page(hpage); | ||
1750 | if (!dequeue_hwpoisoned_huge_page(hpage)) | ||
1751 | num_poisoned_pages_add(1 << compound_order(hpage)); | ||
1752 | } else { | ||
1753 | if (!TestSetPageHWPoison(page)) | ||
1754 | num_poisoned_pages_inc(); | ||
1755 | } | ||
1756 | } | ||
1757 | return ret; | 1773 | return ret; |
1758 | } | 1774 | } |