We're going to use migration entries instead of compound_lock() to stabilize page refcounts. Setup and remove migration entries require page to be locked. Some of split_huge_page() callers already have the page locked. Let's require everybody to lock the page before calling split_huge_page(). Signed-off-by: Kirill A. Shutemov <kirill.shutemov@xxxxxxxxxxxxxxx> --- mm/huge_memory.c | 1 + mm/ksm.c | 6 ++++-- mm/memory-failure.c | 12 +++++++++--- mm/migrate.c | 8 ++++++-- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 3741f81e423e..f1d88b9059e2 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1846,6 +1846,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) BUG_ON(is_huge_zero_page(page)); BUG_ON(!PageAnon(page)); + BUG_ON(!PageLocked(page)); /* * The caller does not necessarily hold an mmap_sem that would prevent diff --git a/mm/ksm.c b/mm/ksm.c index 92182eeba87d..a8a88b0f6f62 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -987,9 +987,11 @@ static int page_trans_compound_anon_split(struct page *page) * Recheck we got the reference while the head * was still anonymous. */ - if (PageAnon(transhuge_head)) + if (PageAnon(transhuge_head)) { + lock_page(transhuge_head); ret = split_huge_page(transhuge_head); - else + unlock_page(transhuge_head); + } else /* * Retry later if split_huge_page run * from under us. diff --git a/mm/memory-failure.c b/mm/memory-failure.c index d487f8dc6d39..74c5aaddae85 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -950,7 +950,10 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, * enough * to be safe. */ if (!PageHuge(hpage) && PageAnon(hpage)) { - if (unlikely(split_huge_page(hpage))) { + lock_page(hpage); + ret = split_huge_page(hpage); + unlock_page(hpage); + if (unlikely(ret)) { /* * FIXME: if splitting THP is failed, it is * better to stop the following operation rather @@ -1694,10 +1697,13 @@ int soft_offline_page(struct page *page, int flags) return -EBUSY; } if (!PageHuge(page) && PageTransHuge(hpage)) { - if (PageAnon(hpage) && unlikely(split_huge_page(hpage))) { + lock_page(page); + ret = split_huge_page(hpage); + unlock_page(page); + if (unlikely(ret)) { pr_info("soft offline: %#lx: failed to split THP\n", pfn); - return -EBUSY; + return ret; } } diff --git a/mm/migrate.c b/mm/migrate.c index 01449826b914..91a67029bb18 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -920,9 +920,13 @@ static int unmap_and_move(new_page_t get_new_page, free_page_t put_new_page, goto out; } - if (unlikely(PageTransHuge(page))) - if (unlikely(split_huge_page(page))) + if (unlikely(PageTransHuge(page))) { + lock_page(page); + rc = split_huge_page(page); + unlock_page(page); + if (rc) goto out; + } rc = __unmap_and_move(page, newpage, force, mode); -- 2.1.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxx. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>