Merge branch 'late/board' into devel-late
[pandora-kernel.git] / mm / mempolicy.c
index b195691..f15c1b2 100644 (file)
@@ -390,7 +390,7 @@ static void mpol_rebind_policy(struct mempolicy *pol, const nodemask_t *newmask,
 {
        if (!pol)
                return;
-       if (!mpol_store_user_nodemask(pol) && step == 0 &&
+       if (!mpol_store_user_nodemask(pol) && step == MPOL_REBIND_ONCE &&
            nodes_equal(pol->w.cpuset_mems_allowed, *newmask))
                return;
 
@@ -607,27 +607,6 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end,
        return first;
 }
 
-/* Apply policy to a single VMA */
-static int policy_vma(struct vm_area_struct *vma, struct mempolicy *new)
-{
-       int err = 0;
-       struct mempolicy *old = vma->vm_policy;
-
-       pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
-                vma->vm_start, vma->vm_end, vma->vm_pgoff,
-                vma->vm_ops, vma->vm_file,
-                vma->vm_ops ? vma->vm_ops->set_policy : NULL);
-
-       if (vma->vm_ops && vma->vm_ops->set_policy)
-               err = vma->vm_ops->set_policy(vma, new);
-       if (!err) {
-               mpol_get(new);
-               vma->vm_policy = new;
-               mpol_put(old);
-       }
-       return err;
-}
-
 /* Step 2: apply policy to a range and do splits. */
 static int mbind_range(struct mm_struct *mm, unsigned long start,
                       unsigned long end, struct mempolicy *new_pol)
@@ -676,9 +655,23 @@ static int mbind_range(struct mm_struct *mm, unsigned long start,
                        if (err)
                                goto out;
                }
-               err = policy_vma(vma, new_pol);
-               if (err)
-                       goto out;
+
+               /*
+                * Apply policy to a single VMA. The reference counting of
+                * policy for vma_policy linkages has already been handled by
+                * vma_merge and split_vma as necessary. If this is a shared
+                * policy then ->set_policy will increment the reference count
+                * for an sp node.
+                */
+               pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
+                       vma->vm_start, vma->vm_end, vma->vm_pgoff,
+                       vma->vm_ops, vma->vm_file,
+                       vma->vm_ops ? vma->vm_ops->set_policy : NULL);
+               if (vma->vm_ops && vma->vm_ops->set_policy) {
+                       err = vma->vm_ops->set_policy(vma, new_pol);
+                       if (err)
+                               goto out;
+               }
        }
 
  out:
@@ -957,8 +950,8 @@ static int migrate_to_node(struct mm_struct *mm, int source, int dest,
  *
  * Returns the number of page that could not be moved.
  */
-int do_migrate_pages(struct mm_struct *mm,
-       const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags)
+int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
+                    const nodemask_t *to, int flags)
 {
        int busy = 0;
        int err;
@@ -970,7 +963,7 @@ int do_migrate_pages(struct mm_struct *mm,
 
        down_read(&mm->mmap_sem);
 
-       err = migrate_vmas(mm, from_nodes, to_nodes, flags);
+       err = migrate_vmas(mm, from, to, flags);
        if (err)
                goto out;
 
@@ -1005,14 +998,34 @@ int do_migrate_pages(struct mm_struct *mm,
         * moved to an empty node, then there is nothing left worth migrating.
         */
 
-       tmp = *from_nodes;
+       tmp = *from;
        while (!nodes_empty(tmp)) {
                int s,d;
                int source = -1;
                int dest = 0;
 
                for_each_node_mask(s, tmp) {
-                       d = node_remap(s, *from_nodes, *to_nodes);
+
+                       /*
+                        * do_migrate_pages() tries to maintain the relative
+                        * node relationship of the pages established between
+                        * threads and memory areas.
+                         *
+                        * However if the number of source nodes is not equal to
+                        * the number of destination nodes we can not preserve
+                        * this node relative relationship.  In that case, skip
+                        * copying memory from a node that is in the destination
+                        * mask.
+                        *
+                        * Example: [2,3,4] -> [3,4,5] moves everything.
+                        *          [0-7] - > [3,4,5] moves only 0,1,2,6,7.
+                        */
+
+                       if ((nodes_weight(*from) != nodes_weight(*to)) &&
+                                               (node_isset(s, *to)))
+                               continue;
+
+                       d = node_remap(s, *from, *to);
                        if (s == d)
                                continue;
 
@@ -1072,8 +1085,8 @@ static void migrate_page_add(struct page *page, struct list_head *pagelist,
 {
 }
 
-int do_migrate_pages(struct mm_struct *mm,
-       const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags)
+int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
+                    const nodemask_t *to, int flags)
 {
        return -ENOSYS;
 }
@@ -1334,8 +1347,8 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode,
         * userid as the target process.
         */
        tcred = __task_cred(task);
-       if (cred->euid != tcred->suid && cred->euid != tcred->uid &&
-           cred->uid  != tcred->suid && cred->uid  != tcred->uid &&
+       if (!uid_eq(cred->euid, tcred->suid) && !uid_eq(cred->euid, tcred->uid) &&
+           !uid_eq(cred->uid,  tcred->suid) && !uid_eq(cred->uid,  tcred->uid) &&
            !capable(CAP_SYS_NICE)) {
                rcu_read_unlock();
                err = -EPERM;