>From e617e8c2034387cbed50bafa786cf83528dbe3df Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Sun, 30 Sep 2018 10:50:58 +0800 Subject: [PATCH 075/166] migrate: consolidate MPOL_MF_SW_YOUNG behaviors - if page already in target node: SetPageReferenced - otherwise: change_prot_numa Signed-off-by: Fengguang Wu --- arch/x86/kvm/Kconfig | 1 + mm/migrate.c | 65 +++++++++++++++++++++++++++++++--------------------- 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index 4c6dec47fac6..c103373536fc 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -100,6 +100,7 @@ config KVM_EPT_IDLE tristate "KVM EPT idle page tracking" depends on KVM_INTEL depends on PROC_PAGE_MONITOR + depends on NUMA_BALANCING ---help--- Provides support for walking EPT to get the A bits on Intel processors equipped with the VT extensions. diff --git a/mm/migrate.c b/mm/migrate.c index d933f6966601..d944f031c9ea 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -1500,6 +1500,8 @@ static int add_page_for_migration(struct mm_struct *mm, unsigned long addr, { struct vm_area_struct *vma; struct page *page; + unsigned long end; + unsigned int page_nid; unsigned int follflags; int err; bool migrate_all = flags & MPOL_MF_MOVE_ALL; @@ -1522,49 +1524,60 @@ static int add_page_for_migration(struct mm_struct *mm, unsigned long addr, if (!page) goto out; - err = 0; - if (page_to_nid(page) == node) - goto out_putpage; + page_nid = page_to_nid(page); err = -EACCES; if (page_mapcount(page) > 1 && !migrate_all) goto out_putpage; - if (flags & MPOL_MF_SW_YOUNG) { - unsigned long start, end; - unsigned long nr_pte_updates = 0; - - start = max(addr, vma->vm_start); - - /* TODO: if huge page */ - end = ALIGN(addr + (1 << PAGE_SHIFT), PAGE_SIZE); - end = min(end, vma->vm_end); - nr_pte_updates = change_prot_numa(vma, start, end); - - err = 0; - goto out_putpage; - } - + err = 0; if (PageHuge(page)) { - if (PageHead(page)) { - /* Check if the page is software young. */ - if (flags & MPOL_MF_SW_YOUNG) + if (!PageHead(page)) { + err = -EACCES; + goto out_putpage; + } + if (flags & MPOL_MF_SW_YOUNG) { + if (page_nid == node) SetPageReferenced(page); - isolate_huge_page(page, pagelist); - err = 0; + else if (PageAnon(page)) { + end = addr + (hpage_nr_pages(page) << PAGE_SHIFT); + if (end <= vma->vm_end) + change_prot_numa(vma, addr, end); + } + goto out_putpage; } + if (page_nid == node) + goto out_putpage; + isolate_huge_page(page, pagelist); } else { struct page *head; head = compound_head(page); + + if (flags & MPOL_MF_SW_YOUNG) { + if (page_nid == node) + SetPageReferenced(head); + else { + unsigned long size; + size = hpage_nr_pages(head) << PAGE_SHIFT; + end = addr + size; + if (unlikely(addr & (size - 1))) + err = -EXDEV; + else if (likely(end <= vma->vm_end)) + change_prot_numa(vma, addr, end); + else + err = -ERANGE; + } + goto out_putpage; + } + if (page_nid == node) + goto out_putpage; + err = isolate_lru_page(head); if (err) goto out_putpage; err = 0; - /* Check if the page is software young. */ - if (flags & MPOL_MF_SW_YOUNG) - SetPageReferenced(head); list_add_tail(&head->lru, pagelist); mod_node_page_state(page_pgdat(head), NR_ISOLATED_ANON + page_is_file_cache(head), -- 2.15.0