mm/page_alloc: make pcpu_drain_mutex and pcpu_drain static
[linux-2.6-microblaze.git] / mm / mempolicy.c
index 58e3dfa..48ba972 100644 (file)
@@ -127,6 +127,32 @@ static struct mempolicy default_policy = {
 
 static struct mempolicy preferred_node_policy[MAX_NUMNODES];
 
+/**
+ * numa_map_to_online_node - Find closest online node
+ * @nid: Node id to start the search
+ *
+ * Lookup the next closest node by distance if @nid is not online.
+ */
+int numa_map_to_online_node(int node)
+{
+       int min_dist = INT_MAX, dist, n, min_node;
+
+       if (node == NUMA_NO_NODE || node_online(node))
+               return node;
+
+       min_node = node;
+       for_each_online_node(n) {
+               dist = node_distance(node, n);
+               if (dist < min_dist) {
+                       min_dist = dist;
+                       min_node = n;
+               }
+       }
+
+       return min_node;
+}
+EXPORT_SYMBOL_GPL(numa_map_to_online_node);
+
 struct mempolicy *get_task_policy(struct task_struct *p)
 {
        struct mempolicy *pol = p->mempolicy;
@@ -442,6 +468,7 @@ static inline bool queue_pages_required(struct page *page,
  */
 static int queue_pages_pmd(pmd_t *pmd, spinlock_t *ptl, unsigned long addr,
                                unsigned long end, struct mm_walk *walk)
+       __releases(ptl)
 {
        int ret = 0;
        struct page *page;
@@ -627,7 +654,7 @@ unsigned long change_prot_numa(struct vm_area_struct *vma,
 {
        int nr_updated;
 
-       nr_updated = change_protection(vma, addr, end, PAGE_NONE, 0, 1);
+       nr_updated = change_protection(vma, addr, end, PAGE_NONE, MM_CP_PROT_NUMA);
        if (nr_updated)
                count_vm_numa_events(NUMA_PTE_UPDATES, nr_updated);
 
@@ -650,7 +677,7 @@ static int queue_pages_test_walk(unsigned long start, unsigned long end,
        unsigned long flags = qp->flags;
 
        /* range check first */
-       VM_BUG_ON((vma->vm_start > start) || (vma->vm_end < end));
+       VM_BUG_ON_VMA((vma->vm_start > start) || (vma->vm_end < end), vma);
 
        if (!qp->first) {
                qp->first = vma;
@@ -678,8 +705,7 @@ static int queue_pages_test_walk(unsigned long start, unsigned long end,
 
        if (flags & MPOL_MF_LAZY) {
                /* Similar to task_numa_work, skip inaccessible VMAs */
-               if (!is_vm_hugetlb_page(vma) &&
-                       (vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)) &&
+               if (!is_vm_hugetlb_page(vma) && vma_is_accessible(vma) &&
                        !(vma->vm_flags & VM_MIXEDMAP))
                        change_prot_numa(vma, start, endvma);
                return 1;
@@ -881,7 +907,6 @@ static void get_policy_nodemask(struct mempolicy *p, nodemask_t *nodes)
 
        switch (p->mode) {
        case MPOL_BIND:
-               /* Fall through */
        case MPOL_INTERLEAVE:
                *nodes = p->v.nodes;
                break;
@@ -897,12 +922,15 @@ static void get_policy_nodemask(struct mempolicy *p, nodemask_t *nodes)
 
 static int lookup_node(struct mm_struct *mm, unsigned long addr)
 {
-       struct page *p;
+       struct page *p = NULL;
        int err;
 
        int locked = 1;
        err = get_user_pages_locked(addr & PAGE_MASK, 1, 0, &p, &locked);
-       if (err >= 0) {
+       if (err == 0) {
+               /* E.g. GUP interrupted by fatal signal */
+               err = -EFAULT;
+       } else if (err > 0) {
                err = page_to_nid(p);
                put_page(p);
        }
@@ -1023,7 +1051,7 @@ static int migrate_page_add(struct page *page, struct list_head *pagelist,
                if (!isolate_lru_page(head)) {
                        list_add_tail(&head->lru, pagelist);
                        mod_node_page_state(page_pgdat(head),
-                               NR_ISOLATED_ANON + page_is_file_cache(head),
+                               NR_ISOLATED_ANON + page_is_file_lru(head),
                                hpage_nr_pages(head));
                } else if (flags & MPOL_MF_STRICT) {
                        /*
@@ -2066,7 +2094,6 @@ bool init_nodemask_of_mempolicy(nodemask_t *mask)
                break;
 
        case MPOL_BIND:
-               /* Fall through */
        case MPOL_INTERLEAVE:
                *mask =  mempolicy->v.nodes;
                break;
@@ -2333,7 +2360,6 @@ bool __mpol_equal(struct mempolicy *a, struct mempolicy *b)
 
        switch (a->mode) {
        case MPOL_BIND:
-               /* Fall through */
        case MPOL_INTERLEAVE:
                return !!nodes_equal(a->v.nodes, b->v.nodes);
        case MPOL_PREFERRED:
@@ -2898,7 +2924,9 @@ int mpol_parse_str(char *str, struct mempolicy **mpol)
        switch (mode) {
        case MPOL_PREFERRED:
                /*
-                * Insist on a nodelist of one node only
+                * Insist on a nodelist of one node only, although later
+                * we use first_node(nodes) to grab a single node, so here
+                * nodelist (or nodes) cannot be empty.
                 */
                if (nodelist) {
                        char *rest = nodelist;
@@ -2906,6 +2934,8 @@ int mpol_parse_str(char *str, struct mempolicy **mpol)
                                rest++;
                        if (*rest)
                                goto out;
+                       if (nodes_empty(nodes))
+                               goto out;
                }
                break;
        case MPOL_INTERLEAVE: