aboutsummaryrefslogtreecommitdiffstats
path: root/mm/huge_memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/huge_memory.c')
-rw-r--r--mm/huge_memory.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index f5f37630c54d..5723b551c023 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -18,6 +18,7 @@
18#include <linux/freezer.h> 18#include <linux/freezer.h>
19#include <linux/mman.h> 19#include <linux/mman.h>
20#include <linux/pagemap.h> 20#include <linux/pagemap.h>
21#include <linux/migrate.h>
21#include <asm/tlb.h> 22#include <asm/tlb.h>
22#include <asm/pgalloc.h> 23#include <asm/pgalloc.h>
23#include "internal.h" 24#include "internal.h"
@@ -1019,17 +1020,39 @@ out:
1019} 1020}
1020 1021
1021/* NUMA hinting page fault entry point for trans huge pmds */ 1022/* NUMA hinting page fault entry point for trans huge pmds */
1022int do_huge_pmd_numa_page(struct mm_struct *mm, unsigned long addr, 1023int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
1023 pmd_t pmd, pmd_t *pmdp) 1024 unsigned long addr, pmd_t pmd, pmd_t *pmdp)
1024{ 1025{
1025 struct page *page; 1026 struct page *page = NULL;
1026 unsigned long haddr = addr & HPAGE_PMD_MASK; 1027 unsigned long haddr = addr & HPAGE_PMD_MASK;
1028 int target_nid;
1027 1029
1028 spin_lock(&mm->page_table_lock); 1030 spin_lock(&mm->page_table_lock);
1029 if (unlikely(!pmd_same(pmd, *pmdp))) 1031 if (unlikely(!pmd_same(pmd, *pmdp)))
1030 goto out_unlock; 1032 goto out_unlock;
1031 1033
1032 page = pmd_page(pmd); 1034 page = pmd_page(pmd);
1035 get_page(page);
1036 spin_unlock(&mm->page_table_lock);
1037
1038 target_nid = mpol_misplaced(page, vma, haddr);
1039 if (target_nid == -1)
1040 goto clear_pmdnuma;
1041
1042 /*
1043 * Due to lacking code to migrate thp pages, we'll split
1044 * (which preserves the special PROT_NONE) and re-take the
1045 * fault on the normal pages.
1046 */
1047 split_huge_page(page);
1048 put_page(page);
1049 return 0;
1050
1051clear_pmdnuma:
1052 spin_lock(&mm->page_table_lock);
1053 if (unlikely(!pmd_same(pmd, *pmdp)))
1054 goto out_unlock;
1055
1033 pmd = pmd_mknonnuma(pmd); 1056 pmd = pmd_mknonnuma(pmd);
1034 set_pmd_at(mm, haddr, pmdp, pmd); 1057 set_pmd_at(mm, haddr, pmdp, pmd);
1035 VM_BUG_ON(pmd_numa(*pmdp)); 1058 VM_BUG_ON(pmd_numa(*pmdp));
@@ -1037,6 +1060,8 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, unsigned long addr,
1037 1060
1038out_unlock: 1061out_unlock:
1039 spin_unlock(&mm->page_table_lock); 1062 spin_unlock(&mm->page_table_lock);
1063 if (page)
1064 put_page(page);
1040 return 0; 1065 return 0;
1041} 1066}
1042 1067