We don't need to split THP page when MADV_FREE syscall is called. It could be done when VM decide really frees it so we could avoid unnecessary THP split. Signed-off-by: Minchan Kim <minchan@xxxxxxxxxx> --- mm/madvise.c | 20 +++++++++++++++++++- mm/rmap.c | 7 +++---- mm/vmscan.c | 28 ++++++++++++++++++---------- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/mm/madvise.c b/mm/madvise.c index a6aa7d4c4e02..77f13a99584c 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -272,7 +272,25 @@ static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr, pte_t *pte, ptent; struct page *page; - split_huge_page_pmd(vma, addr, pmd); + if (pmd_trans_huge_lock(pmd, vma, &ptl) == 1) { + struct page *page; + pmd_t orig_pmd; + + orig_pmd = pmdp_get_and_clear(mm, addr, pmd); + + /* No hugepage in swapcache */ + page = pmd_page(orig_pmd); + VM_BUG_ON_PAGE(PageSwapCache(page), page); + + orig_pmd = pmd_mkold(orig_pmd); + orig_pmd = pmd_mkclean(orig_pmd); + + set_pmd_at(mm, addr, pmd, orig_pmd); + tlb_remove_pmd_tlb_entry(tlb, pmd, addr); + spin_unlock(ptl); + return 0; + } + if (pmd_trans_unstable(pmd)) return 0; diff --git a/mm/rmap.c b/mm/rmap.c index a8e34596dc97..67e1c1859c1d 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -703,10 +703,9 @@ static int page_referenced_one(struct page *page, struct vm_area_struct *vma, if (pmdp_clear_flush_young_notify(vma, address, pmd)) referenced++; - /* - * In this implmentation, MADV_FREE doesn't support THP free - */ - dirty++; + if (pmd_dirty(*pmd)) + dirty++; + spin_unlock(ptl); } else { pte_t *pte; diff --git a/mm/vmscan.c b/mm/vmscan.c index d88413ccadcc..6557f0b36321 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -971,17 +971,25 @@ static unsigned long shrink_page_list(struct list_head *page_list, * Anonymous process memory has backing store? * Try to allocate it some swap space here. */ - if (PageAnon(page) && !PageSwapCache(page) && !freeable) { - if (!(sc->gfp_mask & __GFP_IO)) - goto keep_locked; - if (!add_to_swap(page, page_list)) - goto activate_locked; - may_enter_fs = 1; - - /* Adding to swap updated mapping */ - mapping = page_mapping(page); + if (PageAnon(page) && !PageSwapCache(page)) { + if (!freeable) { + if (!(sc->gfp_mask & __GFP_IO)) + goto keep_locked; + if (!add_to_swap(page, page_list)) + goto activate_locked; + may_enter_fs = 1; + /* Adding to swap updated mapping */ + mapping = page_mapping(page); + } else { + if (likely(!PageTransHuge(page))) + goto unmap; + /* try_to_unmap isn't aware of THP page */ + if (unlikely(split_huge_page_to_list(page, + page_list))) + goto keep_locked; + } } - +unmap: /* * The page is mapped into the page tables of one or more * processes. Try to unmap it here. -- 2.0.0 -- 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>