|
@@ -1559,7 +1559,8 @@ static int __split_huge_page_splitting(struct page *page,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static void __split_huge_page_refcount(struct page *page)
|
|
|
+static void __split_huge_page_refcount(struct page *page,
|
|
|
+ struct list_head *list)
|
|
|
{
|
|
|
int i;
|
|
|
struct zone *zone = page_zone(page);
|
|
@@ -1645,7 +1646,7 @@ static void __split_huge_page_refcount(struct page *page)
|
|
|
BUG_ON(!PageDirty(page_tail));
|
|
|
BUG_ON(!PageSwapBacked(page_tail));
|
|
|
|
|
|
- lru_add_page_tail(page, page_tail, lruvec);
|
|
|
+ lru_add_page_tail(page, page_tail, lruvec, list);
|
|
|
}
|
|
|
atomic_sub(tail_count, &page->_count);
|
|
|
BUG_ON(atomic_read(&page->_count) <= 0);
|
|
@@ -1752,7 +1753,8 @@ static int __split_huge_page_map(struct page *page,
|
|
|
|
|
|
/* must be called with anon_vma->root->rwsem held */
|
|
|
static void __split_huge_page(struct page *page,
|
|
|
- struct anon_vma *anon_vma)
|
|
|
+ struct anon_vma *anon_vma,
|
|
|
+ struct list_head *list)
|
|
|
{
|
|
|
int mapcount, mapcount2;
|
|
|
pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
|
|
@@ -1783,7 +1785,7 @@ static void __split_huge_page(struct page *page,
|
|
|
mapcount, page_mapcount(page));
|
|
|
BUG_ON(mapcount != page_mapcount(page));
|
|
|
|
|
|
- __split_huge_page_refcount(page);
|
|
|
+ __split_huge_page_refcount(page, list);
|
|
|
|
|
|
mapcount2 = 0;
|
|
|
anon_vma_interval_tree_foreach(avc, &anon_vma->rb_root, pgoff, pgoff) {
|
|
@@ -1798,7 +1800,14 @@ static void __split_huge_page(struct page *page,
|
|
|
BUG_ON(mapcount != mapcount2);
|
|
|
}
|
|
|
|
|
|
-int split_huge_page(struct page *page)
|
|
|
+/*
|
|
|
+ * Split a hugepage into normal pages. This doesn't change the position of head
|
|
|
+ * page. If @list is null, tail pages will be added to LRU list, otherwise, to
|
|
|
+ * @list. Both head page and tail pages will inherit mapping, flags, and so on
|
|
|
+ * from the hugepage.
|
|
|
+ * Return 0 if the hugepage is split successfully otherwise return 1.
|
|
|
+ */
|
|
|
+int split_huge_page_to_list(struct page *page, struct list_head *list)
|
|
|
{
|
|
|
struct anon_vma *anon_vma;
|
|
|
int ret = 1;
|
|
@@ -1823,7 +1832,7 @@ int split_huge_page(struct page *page)
|
|
|
goto out_unlock;
|
|
|
|
|
|
BUG_ON(!PageSwapBacked(page));
|
|
|
- __split_huge_page(page, anon_vma);
|
|
|
+ __split_huge_page(page, anon_vma, list);
|
|
|
count_vm_event(THP_SPLIT);
|
|
|
|
|
|
BUG_ON(PageCompound(page));
|