bridge: check brport attr show in brport_show
[pandora-kernel.git] / mm / mempolicy.c
index 388ac07..1ea67ad 100644 (file)
@@ -566,24 +566,23 @@ static inline int check_pgd_range(struct vm_area_struct *vma,
  * If pagelist != NULL then isolate pages from the LRU and
  * put them on the pagelist.
  */
-static struct vm_area_struct *
+static int
 check_range(struct mm_struct *mm, unsigned long start, unsigned long end,
                const nodemask_t *nodes, unsigned long flags, void *private)
 {
-       int err;
-       struct vm_area_struct *first, *vma, *prev;
-
+       int err = 0;
+       struct vm_area_struct *vma, *prev;
 
-       first = find_vma(mm, start);
-       if (!first)
-               return ERR_PTR(-EFAULT);
+       vma = find_vma(mm, start);
+       if (!vma)
+               return -EFAULT;
        prev = NULL;
-       for (vma = first; vma && vma->vm_start < end; vma = vma->vm_next) {
+       for (; vma && vma->vm_start < end; vma = vma->vm_next) {
                if (!(flags & MPOL_MF_DISCONTIG_OK)) {
                        if (!vma->vm_next && vma->vm_end < end)
-                               return ERR_PTR(-EFAULT);
+                               return -EFAULT;
                        if (prev && prev->vm_end < vma->vm_start)
-                               return ERR_PTR(-EFAULT);
+                               return -EFAULT;
                }
                if (!is_vm_hugetlb_page(vma) &&
                    ((flags & MPOL_MF_STRICT) ||
@@ -597,14 +596,12 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end,
                                start = vma->vm_start;
                        err = check_pgd_range(vma, start, endvma, nodes,
                                                flags, private);
-                       if (err) {
-                               first = ERR_PTR(err);
+                       if (err)
                                break;
-                       }
                }
                prev = vma;
        }
-       return first;
+       return err;
 }
 
 /*
@@ -888,11 +885,6 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
                *policy |= (pol->flags & MPOL_MODE_FLAGS);
        }
 
-       if (vma) {
-               up_read(&current->mm->mmap_sem);
-               vma = NULL;
-       }
-
        err = 0;
        if (nmask) {
                if (mpol_store_user_nodemask(pol)) {
@@ -1060,16 +1052,17 @@ out:
 
 /*
  * Allocate a new page for page migration based on vma policy.
- * Start assuming that page is mapped by vma pointed to by @private.
+ * Start by assuming the page is mapped by the same vma as contains @start.
  * Search forward from there, if not.  N.B., this assumes that the
  * list of pages handed to migrate_pages()--which is how we get here--
  * is in virtual address order.
  */
-static struct page *new_vma_page(struct page *page, unsigned long private, int **x)
+static struct page *new_page(struct page *page, unsigned long start, int **x)
 {
-       struct vm_area_struct *vma = (struct vm_area_struct *)private;
+       struct vm_area_struct *vma;
        unsigned long uninitialized_var(address);
 
+       vma = find_vma(current->mm, start);
        while (vma) {
                address = page_address_in_vma(page, vma);
                if (address != -EFAULT)
@@ -1095,7 +1088,7 @@ int do_migrate_pages(struct mm_struct *mm,
        return -ENOSYS;
 }
 
-static struct page *new_vma_page(struct page *page, unsigned long private, int **x)
+static struct page *new_page(struct page *page, unsigned long start, int **x)
 {
        return NULL;
 }
@@ -1105,7 +1098,6 @@ static long do_mbind(unsigned long start, unsigned long len,
                     unsigned short mode, unsigned short mode_flags,
                     nodemask_t *nmask, unsigned long flags)
 {
-       struct vm_area_struct *vma;
        struct mm_struct *mm = current->mm;
        struct mempolicy *new;
        unsigned long end;
@@ -1169,19 +1161,16 @@ static long do_mbind(unsigned long start, unsigned long len,
        if (err)
                goto mpol_out;
 
-       vma = check_range(mm, start, end, nmask,
+       err = check_range(mm, start, end, nmask,
                          flags | MPOL_MF_INVERT, &pagelist);
-
-       err = PTR_ERR(vma);
-       if (!IS_ERR(vma)) {
+       if (!err) {
                int nr_failed = 0;
 
                err = mbind_range(mm, start, end, new);
 
                if (!list_empty(&pagelist)) {
-                       nr_failed = migrate_pages(&pagelist, new_vma_page,
-                                               (unsigned long)vma,
-                                               false, true);
+                       nr_failed = migrate_pages(&pagelist, new_page,
+                                               start, false, true);
                        if (nr_failed)
                                putback_lru_pages(&pagelist);
                }
@@ -1340,12 +1329,9 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode,
                err = -ESRCH;
                goto out;
        }
-       mm = get_task_mm(task);
-       rcu_read_unlock();
+       get_task_struct(task);
 
        err = -EINVAL;
-       if (!mm)
-               goto out;
 
        /*
         * Check if this process has the right to modify the specified
@@ -1353,14 +1339,13 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode,
         * capabilities, superuser privileges or the same
         * userid as the target process.
         */
-       rcu_read_lock();
        tcred = __task_cred(task);
        if (cred->euid != tcred->suid && cred->euid != tcred->uid &&
            cred->uid  != tcred->suid && cred->uid  != tcred->uid &&
            !capable(CAP_SYS_NICE)) {
                rcu_read_unlock();
                err = -EPERM;
-               goto out;
+               goto out_put;
        }
        rcu_read_unlock();
 
@@ -1368,26 +1353,39 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode,
        /* Is the user allowed to access the target nodes? */
        if (!nodes_subset(*new, task_nodes) && !capable(CAP_SYS_NICE)) {
                err = -EPERM;
-               goto out;
+               goto out_put;
        }
 
        if (!nodes_subset(*new, node_states[N_HIGH_MEMORY])) {
                err = -EINVAL;
-               goto out;
+               goto out_put;
        }
 
        err = security_task_movememory(task);
        if (err)
+               goto out_put;
+
+       mm = get_task_mm(task);
+       put_task_struct(task);
+
+       if (!mm) {
+               err = -EINVAL;
                goto out;
+       }
 
        err = do_migrate_pages(mm, old, new,
                capable(CAP_SYS_NICE) ? MPOL_MF_MOVE_ALL : MPOL_MF_MOVE);
+
+       mmput(mm);
 out:
-       if (mm)
-               mmput(mm);
        NODEMASK_SCRATCH_FREE(scratch);
 
        return err;
+
+out_put:
+       put_task_struct(task);
+       goto out;
+
 }
 
 
@@ -1452,7 +1450,6 @@ asmlinkage long compat_sys_get_mempolicy(int __user *policy,
 asmlinkage long compat_sys_set_mempolicy(int mode, compat_ulong_t __user *nmask,
                                     compat_ulong_t maxnode)
 {
-       long err = 0;
        unsigned long __user *nm = NULL;
        unsigned long nr_bits, alloc_size;
        DECLARE_BITMAP(bm, MAX_NUMNODES);
@@ -1461,14 +1458,13 @@ asmlinkage long compat_sys_set_mempolicy(int mode, compat_ulong_t __user *nmask,
        alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
 
        if (nmask) {
-               err = compat_get_bitmap(bm, nmask, nr_bits);
+               if (compat_get_bitmap(bm, nmask, nr_bits))
+                       return -EFAULT;
                nm = compat_alloc_user_space(alloc_size);
-               err |= copy_to_user(nm, bm, alloc_size);
+               if (copy_to_user(nm, bm, alloc_size))
+                       return -EFAULT;
        }
 
-       if (err)
-               return -EFAULT;
-
        return sys_set_mempolicy(mode, nm, nr_bits+1);
 }
 
@@ -1476,7 +1472,6 @@ asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len,
                             compat_ulong_t mode, compat_ulong_t __user *nmask,
                             compat_ulong_t maxnode, compat_ulong_t flags)
 {
-       long err = 0;
        unsigned long __user *nm = NULL;
        unsigned long nr_bits, alloc_size;
        nodemask_t bm;
@@ -1485,14 +1480,13 @@ asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len,
        alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
 
        if (nmask) {
-               err = compat_get_bitmap(nodes_addr(bm), nmask, nr_bits);
+               if (compat_get_bitmap(nodes_addr(bm), nmask, nr_bits))
+                       return -EFAULT;
                nm = compat_alloc_user_space(alloc_size);
-               err |= copy_to_user(nm, nodes_addr(bm), alloc_size);
+               if (copy_to_user(nm, nodes_addr(bm), alloc_size))
+                       return -EFAULT;
        }
 
-       if (err)
-               return -EFAULT;
-
        return sys_mbind(start, len, mode, nm, nr_bits+1, flags);
 }
 
@@ -1607,8 +1601,14 @@ static unsigned interleave_nodes(struct mempolicy *policy)
  * task can change it's policy.  The system default policy requires no
  * such protection.
  */
-unsigned slab_node(struct mempolicy *policy)
+unsigned slab_node(void)
 {
+       struct mempolicy *policy;
+
+       if (in_interrupt())
+               return numa_node_id();
+
+       policy = current->mempolicy;
        if (!policy || policy->flags & MPOL_F_LOCAL)
                return numa_node_id();
 
@@ -1989,7 +1989,6 @@ struct mempolicy *__mpol_dup(struct mempolicy *old)
        } else
                *new = *old;
 
-       rcu_read_lock();
        if (current_cpuset_is_being_rebound()) {
                nodemask_t mems = cpuset_mems_allowed(current);
                if (new->flags & MPOL_F_REBINDING)
@@ -1997,7 +1996,6 @@ struct mempolicy *__mpol_dup(struct mempolicy *old)
                else
                        mpol_rebind_policy(new, &mems, MPOL_REBIND_ONCE);
        }
-       rcu_read_unlock();
        atomic_set(&new->refcnt, 1);
        return new;
 }