]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - mm/mempolicy.c
Merge branch 'for-4.18/wacom' into for-linus
[linux.git] / mm / mempolicy.c
index 32cba0332787f48dea47b5b09f9dac21c567ea84..9ac49ef17b4e1e5128f3db38e0a97bbc067ed1b9 100644 (file)
@@ -446,15 +446,6 @@ static int queue_pages_pmd(pmd_t *pmd, spinlock_t *ptl, unsigned long addr,
                __split_huge_pmd(walk->vma, pmd, addr, false, NULL);
                goto out;
        }
-       if (!thp_migration_supported()) {
-               get_page(page);
-               spin_unlock(ptl);
-               lock_page(page);
-               ret = split_huge_page(page);
-               unlock_page(page);
-               put_page(page);
-               goto out;
-       }
        if (!queue_pages_required(page, qp)) {
                ret = 1;
                goto unlock;
@@ -495,7 +486,7 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
 
        if (pmd_trans_unstable(pmd))
                return 0;
-retry:
+
        pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
        for (; addr != end; pte++, addr += PAGE_SIZE) {
                if (!pte_present(*pte))
@@ -511,22 +502,6 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
                        continue;
                if (!queue_pages_required(page, qp))
                        continue;
-               if (PageTransCompound(page) && !thp_migration_supported()) {
-                       get_page(page);
-                       pte_unmap_unlock(pte, ptl);
-                       lock_page(page);
-                       ret = split_huge_page(page);
-                       unlock_page(page);
-                       put_page(page);
-                       /* Failed to split -- skip. */
-                       if (ret) {
-                               pte = pte_offset_map_lock(walk->mm, pmd,
-                                               addr, &ptl);
-                               continue;
-                       }
-                       goto retry;
-               }
-
                migrate_page_add(page, qp->pagelist, flags);
        }
        pte_unmap_unlock(pte - 1, ptl);
@@ -942,12 +917,13 @@ static void migrate_page_add(struct page *page, struct list_head *pagelist,
        }
 }
 
-static struct page *new_node_page(struct page *page, unsigned long node, int **x)
+/* page allocation callback for NUMA node migration */
+struct page *alloc_new_node_page(struct page *page, unsigned long node)
 {
        if (PageHuge(page))
                return alloc_huge_page_node(page_hstate(compound_head(page)),
                                        node);
-       else if (thp_migration_supported() && PageTransHuge(page)) {
+       else if (PageTransHuge(page)) {
                struct page *thp;
 
                thp = alloc_pages_node(node,
@@ -986,7 +962,7 @@ static int migrate_to_node(struct mm_struct *mm, int source, int dest,
                        flags | MPOL_MF_DISCONTIG_OK, &pagelist);
 
        if (!list_empty(&pagelist)) {
-               err = migrate_pages(&pagelist, new_node_page, NULL, dest,
+               err = migrate_pages(&pagelist, alloc_new_node_page, NULL, dest,
                                        MIGRATE_SYNC, MR_SYSCALL);
                if (err)
                        putback_movable_pages(&pagelist);
@@ -1107,7 +1083,7 @@ int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
  * list of pages handed to migrate_pages()--which is how we get here--
  * is in virtual address order.
  */
-static struct page *new_page(struct page *page, unsigned long start, int **x)
+static struct page *new_page(struct page *page, unsigned long start)
 {
        struct vm_area_struct *vma;
        unsigned long uninitialized_var(address);
@@ -1123,7 +1099,7 @@ static struct page *new_page(struct page *page, unsigned long start, int **x)
        if (PageHuge(page)) {
                return alloc_huge_page_vma(page_hstate(compound_head(page)),
                                vma, address);
-       } else if (thp_migration_supported() && PageTransHuge(page)) {
+       } else if (PageTransHuge(page)) {
                struct page *thp;
 
                thp = alloc_hugepage_vma(GFP_TRANSHUGE, vma, address,
@@ -1152,7 +1128,7 @@ int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
        return -ENOSYS;
 }
 
-static struct page *new_page(struct page *page, unsigned long start, int **x)
+static struct page *new_page(struct page *page, unsigned long start)
 {
        return NULL;
 }
@@ -1336,9 +1312,9 @@ static int copy_nodes_to_user(unsigned long __user *mask, unsigned long maxnode,
        return copy_to_user(mask, nodes_addr(*nodes), copy) ? -EFAULT : 0;
 }
 
-SYSCALL_DEFINE6(mbind, unsigned long, start, unsigned long, len,
-               unsigned long, mode, const unsigned long __user *, nmask,
-               unsigned long, maxnode, unsigned, flags)
+static long kernel_mbind(unsigned long start, unsigned long len,
+                        unsigned long mode, const unsigned long __user *nmask,
+                        unsigned long maxnode, unsigned int flags)
 {
        nodemask_t nodes;
        int err;
@@ -1357,9 +1333,16 @@ SYSCALL_DEFINE6(mbind, unsigned long, start, unsigned long, len,
        return do_mbind(start, len, mode, mode_flags, &nodes, flags);
 }
 
+SYSCALL_DEFINE6(mbind, unsigned long, start, unsigned long, len,
+               unsigned long, mode, const unsigned long __user *, nmask,
+               unsigned long, maxnode, unsigned int, flags)
+{
+       return kernel_mbind(start, len, mode, nmask, maxnode, flags);
+}
+
 /* Set the process memory policy */
-SYSCALL_DEFINE3(set_mempolicy, int, mode, const unsigned long __user *, nmask,
-               unsigned long, maxnode)
+static long kernel_set_mempolicy(int mode, const unsigned long __user *nmask,
+                                unsigned long maxnode)
 {
        int err;
        nodemask_t nodes;
@@ -1377,9 +1360,15 @@ SYSCALL_DEFINE3(set_mempolicy, int, mode, const unsigned long __user *, nmask,
        return do_set_mempolicy(mode, flags, &nodes);
 }
 
-SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode,
-               const unsigned long __user *, old_nodes,
-               const unsigned long __user *, new_nodes)
+SYSCALL_DEFINE3(set_mempolicy, int, mode, const unsigned long __user *, nmask,
+               unsigned long, maxnode)
+{
+       return kernel_set_mempolicy(mode, nmask, maxnode);
+}
+
+static int kernel_migrate_pages(pid_t pid, unsigned long maxnode,
+                               const unsigned long __user *old_nodes,
+                               const unsigned long __user *new_nodes)
 {
        struct mm_struct *mm = NULL;
        struct task_struct *task;
@@ -1469,11 +1458,20 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode,
 
 }
 
+SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode,
+               const unsigned long __user *, old_nodes,
+               const unsigned long __user *, new_nodes)
+{
+       return kernel_migrate_pages(pid, maxnode, old_nodes, new_nodes);
+}
+
 
 /* Retrieve NUMA policy */
-SYSCALL_DEFINE5(get_mempolicy, int __user *, policy,
-               unsigned long __user *, nmask, unsigned long, maxnode,
-               unsigned long, addr, unsigned long, flags)
+static int kernel_get_mempolicy(int __user *policy,
+                               unsigned long __user *nmask,
+                               unsigned long maxnode,
+                               unsigned long addr,
+                               unsigned long flags)
 {
        int err;
        int uninitialized_var(pval);
@@ -1496,6 +1494,13 @@ SYSCALL_DEFINE5(get_mempolicy, int __user *, policy,
        return err;
 }
 
+SYSCALL_DEFINE5(get_mempolicy, int __user *, policy,
+               unsigned long __user *, nmask, unsigned long, maxnode,
+               unsigned long, addr, unsigned long, flags)
+{
+       return kernel_get_mempolicy(policy, nmask, maxnode, addr, flags);
+}
+
 #ifdef CONFIG_COMPAT
 
 COMPAT_SYSCALL_DEFINE5(get_mempolicy, int __user *, policy,
@@ -1514,7 +1519,7 @@ COMPAT_SYSCALL_DEFINE5(get_mempolicy, int __user *, policy,
        if (nmask)
                nm = compat_alloc_user_space(alloc_size);
 
-       err = sys_get_mempolicy(policy, nm, nr_bits+1, addr, flags);
+       err = kernel_get_mempolicy(policy, nm, nr_bits+1, addr, flags);
 
        if (!err && nmask) {
                unsigned long copy_size;
@@ -1546,7 +1551,7 @@ COMPAT_SYSCALL_DEFINE3(set_mempolicy, int, mode, compat_ulong_t __user *, nmask,
                        return -EFAULT;
        }
 
-       return sys_set_mempolicy(mode, nm, nr_bits+1);
+       return kernel_set_mempolicy(mode, nm, nr_bits+1);
 }
 
 COMPAT_SYSCALL_DEFINE6(mbind, compat_ulong_t, start, compat_ulong_t, len,
@@ -1568,10 +1573,43 @@ COMPAT_SYSCALL_DEFINE6(mbind, compat_ulong_t, start, compat_ulong_t, len,
                        return -EFAULT;
        }
 
-       return sys_mbind(start, len, mode, nm, nr_bits+1, flags);
+       return kernel_mbind(start, len, mode, nm, nr_bits+1, flags);
 }
 
-#endif
+COMPAT_SYSCALL_DEFINE4(migrate_pages, compat_pid_t, pid,
+                      compat_ulong_t, maxnode,
+                      const compat_ulong_t __user *, old_nodes,
+                      const compat_ulong_t __user *, new_nodes)
+{
+       unsigned long __user *old = NULL;
+       unsigned long __user *new = NULL;
+       nodemask_t tmp_mask;
+       unsigned long nr_bits;
+       unsigned long size;
+
+       nr_bits = min_t(unsigned long, maxnode - 1, MAX_NUMNODES);
+       size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
+       if (old_nodes) {
+               if (compat_get_bitmap(nodes_addr(tmp_mask), old_nodes, nr_bits))
+                       return -EFAULT;
+               old = compat_alloc_user_space(new_nodes ? size * 2 : size);
+               if (new_nodes)
+                       new = old + size / sizeof(unsigned long);
+               if (copy_to_user(old, nodes_addr(tmp_mask), size))
+                       return -EFAULT;
+       }
+       if (new_nodes) {
+               if (compat_get_bitmap(nodes_addr(tmp_mask), new_nodes, nr_bits))
+                       return -EFAULT;
+               if (new == NULL)
+                       new = compat_alloc_user_space(size);
+               if (copy_to_user(new, nodes_addr(tmp_mask), size))
+                       return -EFAULT;
+       }
+       return kernel_migrate_pages(pid, nr_bits + 1, old, new);
+}
+
+#endif /* CONFIG_COMPAT */
 
 struct mempolicy *__get_vma_policy(struct vm_area_struct *vma,
                                                unsigned long addr)