ALSA: control: Use xarray for faster lookups
[linux-2.6-microblaze.git] / mm / mempolicy.c
index 8c74107..d39b01f 100644 (file)
 #include <linux/swapops.h>
 
 #include <asm/tlbflush.h>
+#include <asm/tlb.h>
 #include <linux/uaccess.h>
 
 #include "internal.h"
@@ -350,7 +351,7 @@ static void mpol_rebind_preferred(struct mempolicy *pol,
  */
 static void mpol_rebind_policy(struct mempolicy *pol, const nodemask_t *newmask)
 {
-       if (!pol)
+       if (!pol || pol->mode == MPOL_LOCAL)
                return;
        if (!mpol_store_user_nodemask(pol) &&
            nodes_equal(pol->w.cpuset_mems_allowed, *newmask))
@@ -440,12 +441,11 @@ static inline bool queue_pages_required(struct page *page,
 }
 
 /*
- * queue_pages_pmd() has four possible return values:
+ * queue_pages_pmd() has three possible return values:
  * 0 - pages are placed on the right node or queued successfully, or
  *     special page is met, i.e. huge zero page.
  * 1 - there is unmovable page, and MPOL_MF_MOVE* & MPOL_MF_STRICT were
  *     specified.
- * 2 - THP was split.
  * -EIO - is migration entry or only MPOL_MF_STRICT was specified and an
  *        existing page was already on a node that does not follow the
  *        policy.
@@ -507,18 +507,13 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
        struct page *page;
        struct queue_pages *qp = walk->private;
        unsigned long flags = qp->flags;
-       int ret;
        bool has_unmovable = false;
        pte_t *pte, *mapped_pte;
        spinlock_t *ptl;
 
        ptl = pmd_trans_huge_lock(pmd, vma);
-       if (ptl) {
-               ret = queue_pages_pmd(pmd, ptl, addr, end, walk);
-               if (ret != 2)
-                       return ret;
-       }
-       /* THP was split, fall through to pte walk */
+       if (ptl)
+               return queue_pages_pmd(pmd, ptl, addr, end, walk);
 
        if (pmd_trans_unstable(pmd))
                return 0;
@@ -636,12 +631,18 @@ unlock:
 unsigned long change_prot_numa(struct vm_area_struct *vma,
                        unsigned long addr, unsigned long end)
 {
+       struct mmu_gather tlb;
        int nr_updated;
 
-       nr_updated = change_protection(vma, addr, end, PAGE_NONE, MM_CP_PROT_NUMA);
+       tlb_gather_mmu(&tlb, vma->vm_mm);
+
+       nr_updated = change_protection(&tlb, vma, addr, end, PAGE_NONE,
+                                      MM_CP_PROT_NUMA);
        if (nr_updated)
                count_vm_numa_events(NUMA_PTE_UPDATES, nr_updated);
 
+       tlb_finish_mmu(&tlb);
+
        return nr_updated;
 }
 #else
@@ -2135,44 +2136,55 @@ static struct page *alloc_pages_preferred_many(gfp_t gfp, unsigned int order,
 }
 
 /**
- * alloc_pages_vma - Allocate a page for a VMA.
+ * vma_alloc_folio - Allocate a folio for a VMA.
  * @gfp: GFP flags.
- * @order: Order of the GFP allocation.
+ * @order: Order of the folio.
  * @vma: Pointer to VMA or NULL if not available.
  * @addr: Virtual address of the allocation.  Must be inside @vma.
  * @hugepage: For hugepages try only the preferred node if possible.
  *
- * Allocate a page for a specific address in @vma, using the appropriate
+ * Allocate a folio for a specific address in @vma, using the appropriate
  * NUMA policy.  When @vma is not NULL the caller must hold the mmap_lock
  * of the mm_struct of the VMA to prevent it from going away.  Should be
- * used for all allocations for pages that will be mapped into user space.
+ * used for all allocations for folios that will be mapped into user space.
  *
- * Return: The page on success or NULL if allocation fails.
+ * Return: The folio on success or NULL if allocation fails.
  */
-struct page *alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
+struct folio *vma_alloc_folio(gfp_t gfp, int order, struct vm_area_struct *vma,
                unsigned long addr, bool hugepage)
 {
        struct mempolicy *pol;
        int node = numa_node_id();
-       struct page *page;
+       struct folio *folio;
        int preferred_nid;
        nodemask_t *nmask;
 
        pol = get_vma_policy(vma, addr);
 
        if (pol->mode == MPOL_INTERLEAVE) {
+               struct page *page;
                unsigned nid;
 
                nid = interleave_nid(pol, vma, addr, PAGE_SHIFT + order);
                mpol_cond_put(pol);
+               gfp |= __GFP_COMP;
                page = alloc_page_interleave(gfp, order, nid);
+               if (page && order > 1)
+                       prep_transhuge_page(page);
+               folio = (struct folio *)page;
                goto out;
        }
 
        if (pol->mode == MPOL_PREFERRED_MANY) {
+               struct page *page;
+
                node = policy_node(gfp, pol, node);
+               gfp |= __GFP_COMP;
                page = alloc_pages_preferred_many(gfp, order, node, pol);
                mpol_cond_put(pol);
+               if (page && order > 1)
+                       prep_transhuge_page(page);
+               folio = (struct folio *)page;
                goto out;
        }
 
@@ -2199,8 +2211,8 @@ struct page *alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
                         * First, try to allocate THP only on local node, but
                         * don't reclaim unnecessarily, just compact.
                         */
-                       page = __alloc_pages_node(hpage_node,
-                               gfp | __GFP_THISNODE | __GFP_NORETRY, order);
+                       folio = __folio_alloc_node(gfp | __GFP_THISNODE |
+                                       __GFP_NORETRY, order, hpage_node);
 
                        /*
                         * If hugepage allocations are configured to always
@@ -2208,8 +2220,9 @@ struct page *alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
                         * to prefer hugepage backing, retry allowing remote
                         * memory with both reclaim and compact as well.
                         */
-                       if (!page && (gfp & __GFP_DIRECT_RECLAIM))
-                               page = __alloc_pages(gfp, order, hpage_node, nmask);
+                       if (!folio && (gfp & __GFP_DIRECT_RECLAIM))
+                               folio = __folio_alloc(gfp, order, hpage_node,
+                                                     nmask);
 
                        goto out;
                }
@@ -2217,25 +2230,12 @@ struct page *alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
 
        nmask = policy_nodemask(gfp, pol);
        preferred_nid = policy_node(gfp, pol, node);
-       page = __alloc_pages(gfp, order, preferred_nid, nmask);
+       folio = __folio_alloc(gfp, order, preferred_nid, nmask);
        mpol_cond_put(pol);
 out:
-       return page;
-}
-EXPORT_SYMBOL(alloc_pages_vma);
-
-struct folio *vma_alloc_folio(gfp_t gfp, int order, struct vm_area_struct *vma,
-               unsigned long addr, bool hugepage)
-{
-       struct folio *folio;
-
-       folio = (struct folio *)alloc_pages_vma(gfp, order, vma, addr,
-                       hugepage);
-       if (folio && order > 1)
-               prep_transhuge_page(&folio->page);
-
        return folio;
 }
+EXPORT_SYMBOL(vma_alloc_folio);
 
 /**
  * alloc_pages - Allocate pages.