]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - mm/mprotect.c
mm/pkeys: generate pkey system call code only if ARCH_HAS_PKEYS is selected
[mirror_ubuntu-artful-kernel.git] / mm / mprotect.c
index 11936526b08b8c5f5c5d0454f6789008a0c6f313..cc2459c57f6080f8776cbc81c844137337bb775e 100644 (file)
@@ -69,11 +69,17 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
        pte_t *pte, oldpte;
        spinlock_t *ptl;
        unsigned long pages = 0;
+       int target_node = NUMA_NO_NODE;
 
        pte = lock_pte_protection(vma, pmd, addr, prot_numa, &ptl);
        if (!pte)
                return 0;
 
+       /* Get target node for single threaded private VMAs */
+       if (prot_numa && !(vma->vm_flags & VM_SHARED) &&
+           atomic_read(&vma->vm_mm->mm_users) == 1)
+               target_node = numa_node_id();
+
        arch_enter_lazy_mmu_mode();
        do {
                oldpte = *pte;
@@ -95,6 +101,13 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
                                /* Avoid TLB flush if possible */
                                if (pte_protnone(oldpte))
                                        continue;
+
+                               /*
+                                * Don't mess with PTEs if page is already on the node
+                                * a single-threaded process is running on.
+                                */
+                               if (target_node == page_to_nid(page))
+                                       continue;
                        }
 
                        ptent = ptep_modify_prot_start(mm, addr, pte);
@@ -163,7 +176,7 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
 
                if (pmd_trans_huge(*pmd) || pmd_devmap(*pmd)) {
                        if (next - addr != HPAGE_PMD_SIZE) {
-                               split_huge_pmd(vma, pmd, addr);
+                               __split_huge_pmd(vma, pmd, addr, false, NULL);
                                if (pmd_trans_unstable(pmd))
                                        continue;
                        } else {
@@ -484,6 +497,8 @@ SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len,
        return do_mprotect_pkey(start, len, prot, -1);
 }
 
+#ifdef CONFIG_ARCH_HAS_PKEYS
+
 SYSCALL_DEFINE4(pkey_mprotect, unsigned long, start, size_t, len,
                unsigned long, prot, int, pkey)
 {
@@ -534,3 +549,5 @@ SYSCALL_DEFINE1(pkey_free, int, pkey)
         */
        return ret;
 }
+
+#endif /* CONFIG_ARCH_HAS_PKEYS */