diff options
Diffstat (limited to 'mm/huge_memory.c')
-rw-r--r-- | mm/huge_memory.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 45eaae030628..2ed1a160a85b 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
@@ -1559,7 +1559,8 @@ static int __split_huge_page_splitting(struct page *page, | |||
1559 | return ret; | 1559 | return ret; |
1560 | } | 1560 | } |
1561 | 1561 | ||
1562 | static void __split_huge_page_refcount(struct page *page) | 1562 | static void __split_huge_page_refcount(struct page *page, |
1563 | struct list_head *list) | ||
1563 | { | 1564 | { |
1564 | int i; | 1565 | int i; |
1565 | struct zone *zone = page_zone(page); | 1566 | struct zone *zone = page_zone(page); |
@@ -1645,7 +1646,7 @@ static void __split_huge_page_refcount(struct page *page) | |||
1645 | BUG_ON(!PageDirty(page_tail)); | 1646 | BUG_ON(!PageDirty(page_tail)); |
1646 | BUG_ON(!PageSwapBacked(page_tail)); | 1647 | BUG_ON(!PageSwapBacked(page_tail)); |
1647 | 1648 | ||
1648 | lru_add_page_tail(page, page_tail, lruvec); | 1649 | lru_add_page_tail(page, page_tail, lruvec, list); |
1649 | } | 1650 | } |
1650 | atomic_sub(tail_count, &page->_count); | 1651 | atomic_sub(tail_count, &page->_count); |
1651 | BUG_ON(atomic_read(&page->_count) <= 0); | 1652 | BUG_ON(atomic_read(&page->_count) <= 0); |
@@ -1752,7 +1753,8 @@ static int __split_huge_page_map(struct page *page, | |||
1752 | 1753 | ||
1753 | /* must be called with anon_vma->root->rwsem held */ | 1754 | /* must be called with anon_vma->root->rwsem held */ |
1754 | static void __split_huge_page(struct page *page, | 1755 | static void __split_huge_page(struct page *page, |
1755 | struct anon_vma *anon_vma) | 1756 | struct anon_vma *anon_vma, |
1757 | struct list_head *list) | ||
1756 | { | 1758 | { |
1757 | int mapcount, mapcount2; | 1759 | int mapcount, mapcount2; |
1758 | pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); | 1760 | pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); |
@@ -1783,7 +1785,7 @@ static void __split_huge_page(struct page *page, | |||
1783 | mapcount, page_mapcount(page)); | 1785 | mapcount, page_mapcount(page)); |
1784 | BUG_ON(mapcount != page_mapcount(page)); | 1786 | BUG_ON(mapcount != page_mapcount(page)); |
1785 | 1787 | ||
1786 | __split_huge_page_refcount(page); | 1788 | __split_huge_page_refcount(page, list); |
1787 | 1789 | ||
1788 | mapcount2 = 0; | 1790 | mapcount2 = 0; |
1789 | anon_vma_interval_tree_foreach(avc, &anon_vma->rb_root, pgoff, pgoff) { | 1791 | anon_vma_interval_tree_foreach(avc, &anon_vma->rb_root, pgoff, pgoff) { |
@@ -1798,7 +1800,14 @@ static void __split_huge_page(struct page *page, | |||
1798 | BUG_ON(mapcount != mapcount2); | 1800 | BUG_ON(mapcount != mapcount2); |
1799 | } | 1801 | } |
1800 | 1802 | ||
1801 | int split_huge_page(struct page *page) | 1803 | /* |
1804 | * Split a hugepage into normal pages. This doesn't change the position of head | ||
1805 | * page. If @list is null, tail pages will be added to LRU list, otherwise, to | ||
1806 | * @list. Both head page and tail pages will inherit mapping, flags, and so on | ||
1807 | * from the hugepage. | ||
1808 | * Return 0 if the hugepage is split successfully otherwise return 1. | ||
1809 | */ | ||
1810 | int split_huge_page_to_list(struct page *page, struct list_head *list) | ||
1802 | { | 1811 | { |
1803 | struct anon_vma *anon_vma; | 1812 | struct anon_vma *anon_vma; |
1804 | int ret = 1; | 1813 | int ret = 1; |
@@ -1823,7 +1832,7 @@ int split_huge_page(struct page *page) | |||
1823 | goto out_unlock; | 1832 | goto out_unlock; |
1824 | 1833 | ||
1825 | BUG_ON(!PageSwapBacked(page)); | 1834 | BUG_ON(!PageSwapBacked(page)); |
1826 | __split_huge_page(page, anon_vma); | 1835 | __split_huge_page(page, anon_vma, list); |
1827 | count_vm_event(THP_SPLIT); | 1836 | count_vm_event(THP_SPLIT); |
1828 | 1837 | ||
1829 | BUG_ON(PageCompound(page)); | 1838 | BUG_ON(PageCompound(page)); |