|
@@ -441,20 +441,6 @@ static void break_cow(struct rmap_item *rmap_item)
|
|
|
up_read(&mm->mmap_sem);
|
|
|
}
|
|
|
|
|
|
-static struct page *page_trans_compound_anon(struct page *page)
|
|
|
-{
|
|
|
- if (PageTransCompound(page)) {
|
|
|
- struct page *head = compound_head(page);
|
|
|
- /*
|
|
|
- * head may actually be splitted and freed from under
|
|
|
- * us but it's ok here.
|
|
|
- */
|
|
|
- if (PageAnon(head))
|
|
|
- return head;
|
|
|
- }
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
static struct page *get_mergeable_page(struct rmap_item *rmap_item)
|
|
|
{
|
|
|
struct mm_struct *mm = rmap_item->mm;
|
|
@@ -470,7 +456,7 @@ static struct page *get_mergeable_page(struct rmap_item *rmap_item)
|
|
|
page = follow_page(vma, addr, FOLL_GET);
|
|
|
if (IS_ERR_OR_NULL(page))
|
|
|
goto out;
|
|
|
- if (PageAnon(page) || page_trans_compound_anon(page)) {
|
|
|
+ if (PageAnon(page)) {
|
|
|
flush_anon_page(vma, page, addr);
|
|
|
flush_dcache_page(page);
|
|
|
} else {
|
|
@@ -975,33 +961,6 @@ out:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static int page_trans_compound_anon_split(struct page *page)
|
|
|
-{
|
|
|
- int ret = 0;
|
|
|
- struct page *transhuge_head = page_trans_compound_anon(page);
|
|
|
- if (transhuge_head) {
|
|
|
- /* Get the reference on the head to split it. */
|
|
|
- if (get_page_unless_zero(transhuge_head)) {
|
|
|
- /*
|
|
|
- * Recheck we got the reference while the head
|
|
|
- * was still anonymous.
|
|
|
- */
|
|
|
- if (PageAnon(transhuge_head))
|
|
|
- ret = split_huge_page(transhuge_head);
|
|
|
- else
|
|
|
- /*
|
|
|
- * Retry later if split_huge_page run
|
|
|
- * from under us.
|
|
|
- */
|
|
|
- ret = 1;
|
|
|
- put_page(transhuge_head);
|
|
|
- } else
|
|
|
- /* Retry later if split_huge_page run from under us. */
|
|
|
- ret = 1;
|
|
|
- }
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* try_to_merge_one_page - take two pages and merge them into one
|
|
|
* @vma: the vma that holds the pte pointing to page
|
|
@@ -1020,9 +979,6 @@ static int try_to_merge_one_page(struct vm_area_struct *vma,
|
|
|
if (page == kpage) /* ksm page forked */
|
|
|
return 0;
|
|
|
|
|
|
- if (PageTransCompound(page) && page_trans_compound_anon_split(page))
|
|
|
- goto out;
|
|
|
- BUG_ON(PageTransCompound(page));
|
|
|
if (!PageAnon(page))
|
|
|
goto out;
|
|
|
|
|
@@ -1035,6 +991,13 @@ static int try_to_merge_one_page(struct vm_area_struct *vma,
|
|
|
*/
|
|
|
if (!trylock_page(page))
|
|
|
goto out;
|
|
|
+
|
|
|
+ if (PageTransCompound(page)) {
|
|
|
+ err = split_huge_page(page);
|
|
|
+ if (err)
|
|
|
+ goto out_unlock;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* If this anonymous page is mapped only here, its pte may need
|
|
|
* to be write-protected. If it's mapped elsewhere, all of its
|
|
@@ -1065,6 +1028,7 @@ static int try_to_merge_one_page(struct vm_area_struct *vma,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+out_unlock:
|
|
|
unlock_page(page);
|
|
|
out:
|
|
|
return err;
|
|
@@ -1635,8 +1599,7 @@ next_mm:
|
|
|
cond_resched();
|
|
|
continue;
|
|
|
}
|
|
|
- if (PageAnon(*page) ||
|
|
|
- page_trans_compound_anon(*page)) {
|
|
|
+ if (PageAnon(*page)) {
|
|
|
flush_anon_page(vma, *page, ksm_scan.address);
|
|
|
flush_dcache_page(*page);
|
|
|
rmap_item = get_next_rmap_item(slot,
|