Merge tag 'vfs-6.7.iomap' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[linux-2.6-microblaze.git] / mm / mempolicy.c
index e52e3a0..10a590e 100644 (file)
@@ -25,7 +25,7 @@
  *                to the last. It would be better if bind would truly restrict
  *                the allocation to memory nodes instead
  *
- * preferred       Try a specific node first before normal fallback.
+ * preferred      Try a specific node first before normal fallback.
  *                As a special case NUMA_NO_NODE here means do the allocation
  *                on the local CPU. This is normally identical to default,
  *                but useful to set in a VMA when you have a non default
@@ -52,7 +52,7 @@
  * on systems with highmem kernel lowmem allocation don't get policied.
  * Same with GFP_DMA allocations.
  *
- * For shmfs/tmpfs/hugetlbfs shared memory the policy is shared between
+ * For shmem/tmpfs shared memory the policy is shared between
  * all users and remembered even when nobody has memory mapped.
  */
 
 
 /* Internal flags */
 #define MPOL_MF_DISCONTIG_OK (MPOL_MF_INTERNAL << 0)   /* Skip checks for continuous vmas */
-#define MPOL_MF_INVERT (MPOL_MF_INTERNAL << 1)         /* Invert check for nodemask */
+#define MPOL_MF_INVERT       (MPOL_MF_INTERNAL << 1)   /* Invert check for nodemask */
+#define MPOL_MF_WRLOCK       (MPOL_MF_INTERNAL << 2)   /* Write-lock walked vmas */
 
 static struct kmem_cache *policy_cache;
 static struct kmem_cache *sn_cache;
@@ -267,9 +268,6 @@ static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags,
 {
        struct mempolicy *policy;
 
-       pr_debug("setting mode %d flags %d nodes[0] %lx\n",
-                mode, flags, nodes ? nodes_addr(*nodes)[0] : NUMA_NO_NODE);
-
        if (mode == MPOL_DEFAULT) {
                if (nodes && !nodes_empty(*nodes))
                        return ERR_PTR(-EINVAL);
@@ -297,6 +295,7 @@ static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags,
                        return ERR_PTR(-EINVAL);
        } else if (nodes_empty(*nodes))
                return ERR_PTR(-EINVAL);
+
        policy = kmem_cache_alloc(policy_cache, GFP_KERNEL);
        if (!policy)
                return ERR_PTR(-ENOMEM);
@@ -309,11 +308,11 @@ static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags,
 }
 
 /* Slow path of a mpol destructor. */
-void __mpol_put(struct mempolicy *p)
+void __mpol_put(struct mempolicy *pol)
 {
-       if (!atomic_dec_and_test(&p->refcnt))
+       if (!atomic_dec_and_test(&pol->refcnt))
                return;
-       kmem_cache_free(policy_cache, p);
+       kmem_cache_free(policy_cache, pol);
 }
 
 static void mpol_rebind_default(struct mempolicy *pol, const nodemask_t *nodes)
@@ -370,7 +369,6 @@ static void mpol_rebind_policy(struct mempolicy *pol, const nodemask_t *newmask)
  *
  * Called with task's alloc_lock held.
  */
-
 void mpol_rebind_task(struct task_struct *tsk, const nodemask_t *new)
 {
        mpol_rebind_policy(tsk->mempolicy, new);
@@ -381,7 +379,6 @@ void mpol_rebind_task(struct task_struct *tsk, const nodemask_t *new)
  *
  * Call holding a reference to mm.  Takes mm->mmap_lock during call.
  */
-
 void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new)
 {
        struct vm_area_struct *vma;
@@ -420,8 +417,25 @@ static const struct mempolicy_operations mpol_ops[MPOL_MAX] = {
        },
 };
 
-static int migrate_folio_add(struct folio *folio, struct list_head *foliolist,
+static bool migrate_folio_add(struct folio *folio, struct list_head *foliolist,
                                unsigned long flags);
+static nodemask_t *policy_nodemask(gfp_t gfp, struct mempolicy *pol,
+                               pgoff_t ilx, int *nid);
+
+static bool strictly_unmovable(unsigned long flags)
+{
+       /*
+        * STRICT without MOVE flags lets do_mbind() fail immediately with -EIO
+        * if any misplaced page is found.
+        */
+       return (flags & (MPOL_MF_STRICT | MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) ==
+                        MPOL_MF_STRICT;
+}
+
+struct migration_mpol {                /* for alloc_migration_target_by_mpol() */
+       struct mempolicy *pol;
+       pgoff_t ilx;
+};
 
 struct queue_pages {
        struct list_head *pagelist;
@@ -430,7 +444,8 @@ struct queue_pages {
        unsigned long start;
        unsigned long end;
        struct vm_area_struct *first;
-       bool has_unmovable;
+       struct folio *large;            /* note last large folio encountered */
+       long nr_failed;                 /* could not be isolated at this time */
 };
 
 /*
@@ -448,61 +463,37 @@ static inline bool queue_folio_required(struct folio *folio,
        return node_isset(nid, *qp->nmask) == !(flags & MPOL_MF_INVERT);
 }
 
-/*
- * queue_folios_pmd() has three possible return values:
- * 0 - folios are placed on the right node or queued successfully, or
- *     special page is met, i.e. zero page, or unmovable page is found
- *     but continue walking (indicated by queue_pages.has_unmovable).
- * -EIO - is migration entry or only MPOL_MF_STRICT was specified and an
- *        existing folio was already on a node that does not follow the
- *        policy.
- */
-static int queue_folios_pmd(pmd_t *pmd, spinlock_t *ptl, unsigned long addr,
-                               unsigned long end, struct mm_walk *walk)
-       __releases(ptl)
+static void queue_folios_pmd(pmd_t *pmd, struct mm_walk *walk)
 {
-       int ret = 0;
        struct folio *folio;
        struct queue_pages *qp = walk->private;
-       unsigned long flags;
 
        if (unlikely(is_pmd_migration_entry(*pmd))) {
-               ret = -EIO;
-               goto unlock;
+               qp->nr_failed++;
+               return;
        }
        folio = pfn_folio(pmd_pfn(*pmd));
        if (is_huge_zero_page(&folio->page)) {
                walk->action = ACTION_CONTINUE;
-               goto unlock;
+               return;
        }
        if (!queue_folio_required(folio, qp))
-               goto unlock;
-
-       flags = qp->flags;
-       /* go to folio migration */
-       if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) {
-               if (!vma_migratable(walk->vma) ||
-                   migrate_folio_add(folio, qp->pagelist, flags)) {
-                       qp->has_unmovable = true;
-                       goto unlock;
-               }
-       } else
-               ret = -EIO;
-unlock:
-       spin_unlock(ptl);
-       return ret;
+               return;
+       if (!(qp->flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) ||
+           !vma_migratable(walk->vma) ||
+           !migrate_folio_add(folio, qp->pagelist, qp->flags))
+               qp->nr_failed++;
 }
 
 /*
- * Scan through pages checking if pages follow certain conditions,
- * and move them to the pagelist if they do.
+ * Scan through folios, checking if they satisfy the required conditions,
+ * moving them from LRU to local pagelist for migration if they do (or not).
  *
- * queue_folios_pte_range() has three possible return values:
- * 0 - folios are placed on the right node or queued successfully, or
- *     special page is met, i.e. zero page, or unmovable page is found
- *     but continue walking (indicated by queue_pages.has_unmovable).
- * -EIO - only MPOL_MF_STRICT was specified and an existing folio was already
- *        on a node that does not follow the policy.
+ * queue_folios_pte_range() has two possible return values:
+ * 0 - continue walking to scan for more, even if an existing folio on the
+ *     wrong node could not be isolated and queued for migration.
+ * -EIO - only MPOL_MF_STRICT was specified, without MPOL_MF_MOVE or ..._ALL,
+ *        and an existing folio was on a node that does not follow the policy.
  */
 static int queue_folios_pte_range(pmd_t *pmd, unsigned long addr,
                        unsigned long end, struct mm_walk *walk)
@@ -516,8 +507,11 @@ static int queue_folios_pte_range(pmd_t *pmd, unsigned long addr,
        spinlock_t *ptl;
 
        ptl = pmd_trans_huge_lock(pmd, vma);
-       if (ptl)
-               return queue_folios_pmd(pmd, ptl, addr, end, walk);
+       if (ptl) {
+               queue_folios_pmd(pmd, walk);
+               spin_unlock(ptl);
+               goto out;
+       }
 
        mapped_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
        if (!pte) {
@@ -526,8 +520,13 @@ static int queue_folios_pte_range(pmd_t *pmd, unsigned long addr,
        }
        for (; addr != end; pte++, addr += PAGE_SIZE) {
                ptent = ptep_get(pte);
-               if (!pte_present(ptent))
+               if (pte_none(ptent))
+                       continue;
+               if (!pte_present(ptent)) {
+                       if (is_migration_entry(pte_to_swp_entry(ptent)))
+                               qp->nr_failed++;
                        continue;
+               }
                folio = vm_normal_folio(vma, addr, ptent);
                if (!folio || folio_is_zone_device(folio))
                        continue;
@@ -539,95 +538,87 @@ static int queue_folios_pte_range(pmd_t *pmd, unsigned long addr,
                        continue;
                if (!queue_folio_required(folio, qp))
                        continue;
-               if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) {
-                       /*
-                        * MPOL_MF_STRICT must be specified if we get here.
-                        * Continue walking vmas due to MPOL_MF_MOVE* flags.
-                        */
-                       if (!vma_migratable(vma))
-                               qp->has_unmovable = true;
-
+               if (folio_test_large(folio)) {
                        /*
-                        * Do not abort immediately since there may be
-                        * temporary off LRU pages in the range.  Still
-                        * need migrate other LRU pages.
+                        * A large folio can only be isolated from LRU once,
+                        * but may be mapped by many PTEs (and Copy-On-Write may
+                        * intersperse PTEs of other, order 0, folios).  This is
+                        * a common case, so don't mistake it for failure (but
+                        * there can be other cases of multi-mapped pages which
+                        * this quick check does not help to filter out - and a
+                        * search of the pagelist might grow to be prohibitive).
+                        *
+                        * migrate_pages(&pagelist) returns nr_failed folios, so
+                        * check "large" now so that queue_pages_range() returns
+                        * a comparable nr_failed folios.  This does imply that
+                        * if folio could not be isolated for some racy reason
+                        * at its first PTE, later PTEs will not give it another
+                        * chance of isolation; but keeps the accounting simple.
                         */
-                       if (migrate_folio_add(folio, qp->pagelist, flags))
-                               qp->has_unmovable = true;
-               } else
-                       break;
+                       if (folio == qp->large)
+                               continue;
+                       qp->large = folio;
+               }
+               if (!(flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) ||
+                   !vma_migratable(vma) ||
+                   !migrate_folio_add(folio, qp->pagelist, flags)) {
+                       qp->nr_failed++;
+                       if (strictly_unmovable(flags))
+                               break;
+               }
        }
        pte_unmap_unlock(mapped_pte, ptl);
        cond_resched();
-
-       return addr != end ? -EIO : 0;
+out:
+       if (qp->nr_failed && strictly_unmovable(flags))
+               return -EIO;
+       return 0;
 }
 
 static int queue_folios_hugetlb(pte_t *pte, unsigned long hmask,
                               unsigned long addr, unsigned long end,
                               struct mm_walk *walk)
 {
-       int ret = 0;
 #ifdef CONFIG_HUGETLB_PAGE
        struct queue_pages *qp = walk->private;
-       unsigned long flags = (qp->flags & MPOL_MF_VALID);
+       unsigned long flags = qp->flags;
        struct folio *folio;
        spinlock_t *ptl;
        pte_t entry;
 
        ptl = huge_pte_lock(hstate_vma(walk->vma), walk->mm, pte);
        entry = huge_ptep_get(pte);
-       if (!pte_present(entry))
+       if (!pte_present(entry)) {
+               if (unlikely(is_hugetlb_entry_migration(entry)))
+                       qp->nr_failed++;
                goto unlock;
+       }
        folio = pfn_folio(pte_pfn(entry));
        if (!queue_folio_required(folio, qp))
                goto unlock;
-
-       if (flags == MPOL_MF_STRICT) {
-               /*
-                * STRICT alone means only detecting misplaced folio and no
-                * need to further check other vma.
-                */
-               ret = -EIO;
+       if (!(flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) ||
+           !vma_migratable(walk->vma)) {
+               qp->nr_failed++;
                goto unlock;
        }
-
-       if (!vma_migratable(walk->vma)) {
-               /*
-                * Must be STRICT with MOVE*, otherwise .test_walk() have
-                * stopped walking current vma.
-                * Detecting misplaced folio but allow migrating folios which
-                * have been queued.
-                */
-               qp->has_unmovable = true;
-               goto unlock;
-       }
-
        /*
-        * With MPOL_MF_MOVE, we try to migrate only unshared folios. If it
-        * is shared it is likely not worth migrating.
+        * Unless MPOL_MF_MOVE_ALL, we try to avoid migrating a shared folio.
+        * Choosing not to migrate a shared folio is not counted as a failure.
         *
         * To check if the folio is shared, ideally we want to make sure
         * every page is mapped to the same process. Doing that is very
-        * expensive, so check the estimated mapcount of the folio instead.
+        * expensive, so check the estimated sharers of the folio instead.
         */
-       if (flags & (MPOL_MF_MOVE_ALL) ||
-           (flags & MPOL_MF_MOVE && folio_estimated_sharers(folio) == 1 &&
-            !hugetlb_pmd_shared(pte))) {
-               if (!isolate_hugetlb(folio, qp->pagelist) &&
-                       (flags & MPOL_MF_STRICT))
-                       /*
-                        * Failed to isolate folio but allow migrating pages
-                        * which have been queued.
-                        */
-                       qp->has_unmovable = true;
-       }
+       if ((flags & MPOL_MF_MOVE_ALL) ||
+           (folio_estimated_sharers(folio) == 1 && !hugetlb_pmd_shared(pte)))
+               if (!isolate_hugetlb(folio, qp->pagelist))
+                       qp->nr_failed++;
 unlock:
        spin_unlock(ptl);
-#else
-       BUG();
+       if (qp->nr_failed && strictly_unmovable(flags))
+               return -EIO;
 #endif
-       return ret;
+       return 0;
 }
 
 #ifdef CONFIG_NUMA_BALANCING
@@ -656,12 +647,6 @@ unsigned long change_prot_numa(struct vm_area_struct *vma,
 
        return nr_updated;
 }
-#else
-static unsigned long change_prot_numa(struct vm_area_struct *vma,
-                       unsigned long addr, unsigned long end)
-{
-       return 0;
-}
 #endif /* CONFIG_NUMA_BALANCING */
 
 static int queue_pages_test_walk(unsigned long start, unsigned long end,
@@ -700,16 +685,11 @@ static int queue_pages_test_walk(unsigned long start, unsigned long end,
        if (endvma > end)
                endvma = end;
 
-       if (flags & MPOL_MF_LAZY) {
-               /* Similar to task_numa_work, skip inaccessible VMAs */
-               if (!is_vm_hugetlb_page(vma) && vma_is_accessible(vma) &&
-                       !(vma->vm_flags & VM_MIXEDMAP))
-                       change_prot_numa(vma, start, endvma);
-               return 1;
-       }
-
-       /* queue pages from current vma */
-       if (flags & MPOL_MF_VALID)
+       /*
+        * Check page nodes, and queue pages to move, in the current vma.
+        * But if no moving, and no strict checking, the scan can be skipped.
+        */
+       if (flags & (MPOL_MF_STRICT | MPOL_MF_MOVE | MPOL_MF_MOVE_ALL))
                return 0;
        return 1;
 }
@@ -731,22 +711,21 @@ static const struct mm_walk_ops queue_pages_lock_vma_walk_ops = {
 /*
  * Walk through page tables and collect pages to be migrated.
  *
- * If pages found in a given range are on a set of nodes (determined by
- * @nodes and @flags,) it's isolated and queued to the pagelist which is
- * passed via @private.
+ * If pages found in a given range are not on the required set of @nodes,
+ * and migration is allowed, they are isolated and queued to @pagelist.
  *
- * queue_pages_range() has three possible return values:
- * 1 - there is unmovable page, but MPOL_MF_MOVE* & MPOL_MF_STRICT were
- *     specified.
- * 0 - queue pages successfully or no misplaced page.
- * errno - i.e. misplaced pages with MPOL_MF_STRICT specified (-EIO) or
- *         memory range specified by nodemask and maxnode points outside
- *         your accessible address space (-EFAULT)
+ * queue_pages_range() may return:
+ * 0 - all pages already on the right node, or successfully queued for moving
+ *     (or neither strict checking nor moving requested: only range checking).
+ * >0 - this number of misplaced folios could not be queued for moving
+ *      (a hugetlbfs page or a transparent huge page being counted as 1).
+ * -EIO - a misplaced page found, when MPOL_MF_STRICT specified without MOVEs.
+ * -EFAULT - a hole in the memory range, when MPOL_MF_DISCONTIG_OK unspecified.
  */
-static int
+static long
 queue_pages_range(struct mm_struct *mm, unsigned long start, unsigned long end,
                nodemask_t *nodes, unsigned long flags,
-               struct list_head *pagelist, bool lock_vma)
+               struct list_head *pagelist)
 {
        int err;
        struct queue_pages qp = {
@@ -756,20 +735,17 @@ queue_pages_range(struct mm_struct *mm, unsigned long start, unsigned long end,
                .start = start,
                .end = end,
                .first = NULL,
-               .has_unmovable = false,
        };
-       const struct mm_walk_ops *ops = lock_vma ?
+       const struct mm_walk_ops *ops = (flags & MPOL_MF_WRLOCK) ?
                        &queue_pages_lock_vma_walk_ops : &queue_pages_walk_ops;
 
        err = walk_page_range(mm, start, end, ops, &qp);
 
-       if (qp.has_unmovable)
-               err = 1;
        if (!qp.first)
                /* whole range in hole */
                err = -EFAULT;
 
-       return err;
+       return err ? : qp.nr_failed;
 }
 
 /*
@@ -777,7 +753,7 @@ queue_pages_range(struct mm_struct *mm, unsigned long start, unsigned long end,
  * This must be called with the mmap_lock held for writing.
  */
 static int vma_replace_policy(struct vm_area_struct *vma,
-                                               struct mempolicy *pol)
+                               struct mempolicy *pol)
 {
        int err;
        struct mempolicy *old;
@@ -785,11 +761,6 @@ static int vma_replace_policy(struct vm_area_struct *vma,
 
        vma_assert_write_locked(vma);
 
-       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);
-
        new = mpol_dup(pol);
        if (IS_ERR(new))
                return PTR_ERR(new);
@@ -815,10 +786,7 @@ static int mbind_range(struct vma_iterator *vmi, struct vm_area_struct *vma,
                struct vm_area_struct **prev, unsigned long start,
                unsigned long end, struct mempolicy *new_pol)
 {
-       struct vm_area_struct *merged;
        unsigned long vmstart, vmend;
-       pgoff_t pgoff;
-       int err;
 
        vmend = min(end, vma->vm_end);
        if (start > vma->vm_start) {
@@ -828,31 +796,14 @@ static int mbind_range(struct vma_iterator *vmi, struct vm_area_struct *vma,
                vmstart = vma->vm_start;
        }
 
-       if (mpol_equal(vma_policy(vma), new_pol)) {
+       if (mpol_equal(vma->vm_policy, new_pol)) {
                *prev = vma;
                return 0;
        }
 
-       pgoff = vma->vm_pgoff + ((vmstart - vma->vm_start) >> PAGE_SHIFT);
-       merged = vma_merge(vmi, vma->vm_mm, *prev, vmstart, vmend, vma->vm_flags,
-                        vma->anon_vma, vma->vm_file, pgoff, new_pol,
-                        vma->vm_userfaultfd_ctx, anon_vma_name(vma));
-       if (merged) {
-               *prev = merged;
-               return vma_replace_policy(merged, new_pol);
-       }
-
-       if (vma->vm_start != vmstart) {
-               err = split_vma(vmi, vma, vmstart, 1);
-               if (err)
-                       return err;
-       }
-
-       if (vma->vm_end != vmend) {
-               err = split_vma(vmi, vma, vmend, 0);
-               if (err)
-                       return err;
-       }
+       vma =  vma_modify_policy(vmi, *prev, vma, vmstart, vmend, new_pol);
+       if (IS_ERR(vma))
+               return PTR_ERR(vma);
 
        *prev = vma;
        return vma_replace_policy(vma, new_pol);
@@ -900,18 +851,18 @@ out:
  *
  * Called with task's alloc_lock held
  */
-static void get_policy_nodemask(struct mempolicy *p, nodemask_t *nodes)
+static void get_policy_nodemask(struct mempolicy *pol, nodemask_t *nodes)
 {
        nodes_clear(*nodes);
-       if (p == &default_policy)
+       if (pol == &default_policy)
                return;
 
-       switch (p->mode) {
+       switch (pol->mode) {
        case MPOL_BIND:
        case MPOL_INTERLEAVE:
        case MPOL_PREFERRED:
        case MPOL_PREFERRED_MANY:
-               *nodes = p->nodes;
+               *nodes = pol->nodes;
                break;
        case MPOL_LOCAL:
                /* return empty node mask for local allocation */
@@ -958,6 +909,7 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
        }
 
        if (flags & MPOL_F_ADDR) {
+               pgoff_t ilx;            /* ignored here */
                /*
                 * Do NOT fall back to task policy if the
                 * vma/shared policy at addr is NULL.  We
@@ -969,10 +921,7 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
                        mmap_read_unlock(mm);
                        return -EFAULT;
                }
-               if (vma->vm_ops && vma->vm_ops->get_policy)
-                       pol = vma->vm_ops->get_policy(vma, addr);
-               else
-                       pol = vma->vm_policy;
+               pol = __get_vma_policy(vma, addr, &ilx);
        } else if (addr)
                return -EINVAL;
 
@@ -1032,16 +981,16 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
 }
 
 #ifdef CONFIG_MIGRATION
-static int migrate_folio_add(struct folio *folio, struct list_head *foliolist,
+static bool migrate_folio_add(struct folio *folio, struct list_head *foliolist,
                                unsigned long flags)
 {
        /*
-        * We try to migrate only unshared folios. If it is shared it
-        * is likely not worth migrating.
+        * Unless MPOL_MF_MOVE_ALL, we try to avoid migrating a shared folio.
+        * Choosing not to migrate a shared folio is not counted as a failure.
         *
         * To check if the folio is shared, ideally we want to make sure
         * every page is mapped to the same process. Doing that is very
-        * expensive, so check the estimated mapcount of the folio instead.
+        * expensive, so check the estimated sharers of the folio instead.
         */
        if ((flags & MPOL_MF_MOVE_ALL) || folio_estimated_sharers(folio) == 1) {
                if (folio_isolate_lru(folio)) {
@@ -1049,32 +998,31 @@ static int migrate_folio_add(struct folio *folio, struct list_head *foliolist,
                        node_stat_mod_folio(folio,
                                NR_ISOLATED_ANON + folio_is_file_lru(folio),
                                folio_nr_pages(folio));
-               } else if (flags & MPOL_MF_STRICT) {
+               } else {
                        /*
                         * Non-movable folio may reach here.  And, there may be
                         * temporary off LRU folios or non-LRU movable folios.
                         * Treat them as unmovable folios since they can't be
-                        * isolated, so they can't be moved at the moment.  It
-                        * should return -EIO for this case too.
+                        * isolated, so they can't be moved at the moment.
                         */
-                       return -EIO;
+                       return false;
                }
        }
-
-       return 0;
+       return true;
 }
 
 /*
  * Migrate pages from one node to a target node.
  * Returns error or the number of pages not migrated.
  */
-static int migrate_to_node(struct mm_struct *mm, int source, int dest,
-                          int flags)
+static long migrate_to_node(struct mm_struct *mm, int source, int dest,
+                           int flags)
 {
        nodemask_t nmask;
        struct vm_area_struct *vma;
        LIST_HEAD(pagelist);
-       int err = 0;
+       long nr_failed;
+       long err = 0;
        struct migration_target_control mtc = {
                .nid = dest,
                .gfp_mask = GFP_HIGHUSER_MOVABLE | __GFP_THISNODE,
@@ -1083,23 +1031,30 @@ static int migrate_to_node(struct mm_struct *mm, int source, int dest,
        nodes_clear(nmask);
        node_set(source, nmask);
 
+       VM_BUG_ON(!(flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)));
+
+       mmap_read_lock(mm);
+       vma = find_vma(mm, 0);
+
        /*
-        * This does not "check" the range but isolates all pages that
+        * This does not migrate the range, but isolates all pages that
         * need migration.  Between passing in the full user address
-        * space range and MPOL_MF_DISCONTIG_OK, this call can not fail.
+        * space range and MPOL_MF_DISCONTIG_OK, this call cannot fail,
+        * but passes back the count of pages which could not be isolated.
         */
-       vma = find_vma(mm, 0);
-       VM_BUG_ON(!(flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)));
-       queue_pages_range(mm, vma->vm_start, mm->task_size, &nmask,
-                       flags | MPOL_MF_DISCONTIG_OK, &pagelist, false);
+       nr_failed = queue_pages_range(mm, vma->vm_start, mm->task_size, &nmask,
+                                     flags | MPOL_MF_DISCONTIG_OK, &pagelist);
+       mmap_read_unlock(mm);
 
        if (!list_empty(&pagelist)) {
                err = migrate_pages(&pagelist, alloc_migration_target, NULL,
-                               (unsigned long)&mtc, MIGRATE_SYNC, MR_SYSCALL, NULL);
+                       (unsigned long)&mtc, MIGRATE_SYNC, MR_SYSCALL, NULL);
                if (err)
                        putback_movable_pages(&pagelist);
        }
 
+       if (err >= 0)
+               err += nr_failed;
        return err;
 }
 
@@ -1112,14 +1067,12 @@ static int migrate_to_node(struct mm_struct *mm, int source, int dest,
 int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
                     const nodemask_t *to, int flags)
 {
-       int busy = 0;
-       int err = 0;
+       long nr_failed = 0;
+       long err = 0;
        nodemask_t tmp;
 
        lru_cache_disable();
 
-       mmap_read_lock(mm);
-
        /*
         * Find a 'source' bit set in 'tmp' whose corresponding 'dest'
         * bit in 'to' is not also set in 'tmp'.  Clear the found 'source'
@@ -1195,59 +1148,58 @@ int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
                node_clear(source, tmp);
                err = migrate_to_node(mm, source, dest, flags);
                if (err > 0)
-                       busy += err;
+                       nr_failed += err;
                if (err < 0)
                        break;
        }
-       mmap_read_unlock(mm);
 
        lru_cache_enable();
        if (err < 0)
                return err;
-       return busy;
-
+       return (nr_failed < INT_MAX) ? nr_failed : INT_MAX;
 }
 
 /*
- * Allocate a new page for page migration based on vma policy.
- * 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.
+ * Allocate a new folio for page migration, according to NUMA mempolicy.
  */
-static struct folio *new_folio(struct folio *src, unsigned long start)
+static struct folio *alloc_migration_target_by_mpol(struct folio *src,
+                                                   unsigned long private)
 {
-       struct vm_area_struct *vma;
-       unsigned long address;
-       VMA_ITERATOR(vmi, current->mm, start);
-       gfp_t gfp = GFP_HIGHUSER_MOVABLE | __GFP_RETRY_MAYFAIL;
+       struct migration_mpol *mmpol = (struct migration_mpol *)private;
+       struct mempolicy *pol = mmpol->pol;
+       pgoff_t ilx = mmpol->ilx;
+       struct page *page;
+       unsigned int order;
+       int nid = numa_node_id();
+       gfp_t gfp;
 
-       for_each_vma(vmi, vma) {
-               address = page_address_in_vma(&src->page, vma);
-               if (address != -EFAULT)
-                       break;
-       }
+       order = folio_order(src);
+       ilx += src->index >> order;
 
        if (folio_test_hugetlb(src)) {
-               return alloc_hugetlb_folio_vma(folio_hstate(src),
-                               vma, address);
+               nodemask_t *nodemask;
+               struct hstate *h;
+
+               h = folio_hstate(src);
+               gfp = htlb_alloc_mask(h);
+               nodemask = policy_nodemask(gfp, pol, ilx, &nid);
+               return alloc_hugetlb_folio_nodemask(h, nid, nodemask, gfp);
        }
 
        if (folio_test_large(src))
                gfp = GFP_TRANSHUGE;
+       else
+               gfp = GFP_HIGHUSER_MOVABLE | __GFP_RETRY_MAYFAIL | __GFP_COMP;
 
-       /*
-        * if !vma, vma_alloc_folio() will use task or system default policy
-        */
-       return vma_alloc_folio(gfp, folio_order(src), vma, address,
-                       folio_test_large(src));
+       page = alloc_pages_mpol(gfp, order, pol, ilx, nid);
+       return page_rmappable_folio(page);
 }
 #else
 
-static int migrate_folio_add(struct folio *folio, struct list_head *foliolist,
+static bool migrate_folio_add(struct folio *folio, struct list_head *foliolist,
                                unsigned long flags)
 {
-       return -EIO;
+       return false;
 }
 
 int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
@@ -1256,7 +1208,8 @@ int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
        return -ENOSYS;
 }
 
-static struct folio *new_folio(struct folio *src, unsigned long start)
+static struct folio *alloc_migration_target_by_mpol(struct folio *src,
+                                                   unsigned long private)
 {
        return NULL;
 }
@@ -1269,10 +1222,11 @@ static long do_mbind(unsigned long start, unsigned long len,
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma, *prev;
        struct vma_iterator vmi;
+       struct migration_mpol mmpol;
        struct mempolicy *new;
        unsigned long end;
-       int err;
-       int ret;
+       long err;
+       long nr_failed;
        LIST_HEAD(pagelist);
 
        if (flags & ~(unsigned long)MPOL_MF_VALID)
@@ -1298,9 +1252,6 @@ static long do_mbind(unsigned long start, unsigned long len,
        if (IS_ERR(new))
                return PTR_ERR(new);
 
-       if (flags & MPOL_MF_LAZY)
-               new->flags |= MPOL_F_MOF;
-
        /*
         * If we are using the default policy then operation
         * on discontinuous address spaces is okay after all
@@ -1308,14 +1259,8 @@ static long do_mbind(unsigned long start, unsigned long len,
        if (!new)
                flags |= MPOL_MF_DISCONTIG_OK;
 
-       pr_debug("mbind %lx-%lx mode:%d flags:%d nodes:%lx\n",
-                start, start + len, mode, mode_flags,
-                nmask ? nodes_addr(*nmask)[0] : NUMA_NO_NODE);
-
-       if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) {
-
+       if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL))
                lru_cache_disable();
-       }
        {
                NODEMASK_SCRATCH(scratch);
                if (scratch) {
@@ -1331,45 +1276,81 @@ static long do_mbind(unsigned long start, unsigned long len,
                goto mpol_out;
 
        /*
-        * Lock the VMAs before scanning for pages to migrate, to ensure we don't
-        * miss a concurrently inserted page.
+        * Lock the VMAs before scanning for pages to migrate,
+        * to ensure we don't miss a concurrently inserted page.
         */
-       ret = queue_pages_range(mm, start, end, nmask,
-                         flags | MPOL_MF_INVERT, &pagelist, true);
+       nr_failed = queue_pages_range(mm, start, end, nmask,
+                       flags | MPOL_MF_INVERT | MPOL_MF_WRLOCK, &pagelist);
 
-       if (ret < 0) {
-               err = ret;
-               goto up_out;
-       }
-
-       vma_iter_init(&vmi, mm, start);
-       prev = vma_prev(&vmi);
-       for_each_vma_range(vmi, vma, end) {
-               err = mbind_range(&vmi, vma, &prev, start, end, new);
-               if (err)
-                       break;
+       if (nr_failed < 0) {
+               err = nr_failed;
+               nr_failed = 0;
+       } else {
+               vma_iter_init(&vmi, mm, start);
+               prev = vma_prev(&vmi);
+               for_each_vma_range(vmi, vma, end) {
+                       err = mbind_range(&vmi, vma, &prev, start, end, new);
+                       if (err)
+                               break;
+               }
        }
 
-       if (!err) {
-               int nr_failed = 0;
-
-               if (!list_empty(&pagelist)) {
-                       WARN_ON_ONCE(flags & MPOL_MF_LAZY);
-                       nr_failed = migrate_pages(&pagelist, new_folio, NULL,
-                               start, MIGRATE_SYNC, MR_MEMPOLICY_MBIND, NULL);
-                       if (nr_failed)
-                               putback_movable_pages(&pagelist);
+       if (!err && !list_empty(&pagelist)) {
+               /* Convert MPOL_DEFAULT's NULL to task or default policy */
+               if (!new) {
+                       new = get_task_policy(current);
+                       mpol_get(new);
                }
+               mmpol.pol = new;
+               mmpol.ilx = 0;
 
-               if (((ret > 0) || nr_failed) && (flags & MPOL_MF_STRICT))
-                       err = -EIO;
-       } else {
-up_out:
-               if (!list_empty(&pagelist))
-                       putback_movable_pages(&pagelist);
+               /*
+                * In the interleaved case, attempt to allocate on exactly the
+                * targeted nodes, for the first VMA to be migrated; for later
+                * VMAs, the nodes will still be interleaved from the targeted
+                * nodemask, but one by one may be selected differently.
+                */
+               if (new->mode == MPOL_INTERLEAVE) {
+                       struct page *page;
+                       unsigned int order;
+                       unsigned long addr = -EFAULT;
+
+                       list_for_each_entry(page, &pagelist, lru) {
+                               if (!PageKsm(page))
+                                       break;
+                       }
+                       if (!list_entry_is_head(page, &pagelist, lru)) {
+                               vma_iter_init(&vmi, mm, start);
+                               for_each_vma_range(vmi, vma, end) {
+                                       addr = page_address_in_vma(page, vma);
+                                       if (addr != -EFAULT)
+                                               break;
+                               }
+                       }
+                       if (addr != -EFAULT) {
+                               order = compound_order(page);
+                               /* We already know the pol, but not the ilx */
+                               mpol_cond_put(get_vma_policy(vma, addr, order,
+                                                            &mmpol.ilx));
+                               /* Set base from which to increment by index */
+                               mmpol.ilx -= page->index >> order;
+                       }
+               }
        }
 
        mmap_write_unlock(mm);
+
+       if (!err && !list_empty(&pagelist)) {
+               nr_failed |= migrate_pages(&pagelist,
+                               alloc_migration_target_by_mpol, NULL,
+                               (unsigned long)&mmpol, MIGRATE_SYNC,
+                               MR_MEMPOLICY_MBIND, NULL);
+       }
+
+       if (nr_failed && (flags & MPOL_MF_STRICT))
+               err = -EIO;
+       if (!list_empty(&pagelist))
+               putback_movable_pages(&pagelist);
 mpol_out:
        mpol_put(new);
        if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL))
@@ -1690,7 +1671,6 @@ out:
 out_put:
        put_task_struct(task);
        goto out;
-
 }
 
 SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode,
@@ -1700,7 +1680,6 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode,
        return kernel_migrate_pages(pid, maxnode, old_nodes, new_nodes);
 }
 
-
 /* Retrieve NUMA policy */
 static int kernel_get_mempolicy(int __user *policy,
                                unsigned long __user *nmask,
@@ -1767,34 +1746,19 @@ bool vma_migratable(struct vm_area_struct *vma)
 }
 
 struct mempolicy *__get_vma_policy(struct vm_area_struct *vma,
-                                               unsigned long addr)
+                                  unsigned long addr, pgoff_t *ilx)
 {
-       struct mempolicy *pol = NULL;
-
-       if (vma) {
-               if (vma->vm_ops && vma->vm_ops->get_policy) {
-                       pol = vma->vm_ops->get_policy(vma, addr);
-               } else if (vma->vm_policy) {
-                       pol = vma->vm_policy;
-
-                       /*
-                        * shmem_alloc_page() passes MPOL_F_SHARED policy with
-                        * a pseudo vma whose vma->vm_ops=NULL. Take a reference
-                        * count on these policies which will be dropped by
-                        * mpol_cond_put() later
-                        */
-                       if (mpol_needs_cond_ref(pol))
-                               mpol_get(pol);
-               }
-       }
-
-       return pol;
+       *ilx = 0;
+       return (vma->vm_ops && vma->vm_ops->get_policy) ?
+               vma->vm_ops->get_policy(vma, addr, ilx) : vma->vm_policy;
 }
 
 /*
- * get_vma_policy(@vma, @addr)
+ * get_vma_policy(@vma, @addr, @order, @ilx)
  * @vma: virtual memory area whose policy is sought
  * @addr: address in @vma for shared policy lookup
+ * @order: 0, or appropriate huge_page_order for interleaving
+ * @ilx: interleave index (output), for use only when MPOL_INTERLEAVE
  *
  * Returns effective policy for a VMA at specified address.
  * Falls back to current->mempolicy or system default policy, as necessary.
@@ -1803,14 +1767,18 @@ struct mempolicy *__get_vma_policy(struct vm_area_struct *vma,
  * freeing by another task.  It is the caller's responsibility to free the
  * extra reference for shared policies.
  */
-static struct mempolicy *get_vma_policy(struct vm_area_struct *vma,
-                                               unsigned long addr)
+struct mempolicy *get_vma_policy(struct vm_area_struct *vma,
+                                unsigned long addr, int order, pgoff_t *ilx)
 {
-       struct mempolicy *pol = __get_vma_policy(vma, addr);
+       struct mempolicy *pol;
 
+       pol = __get_vma_policy(vma, addr, ilx);
        if (!pol)
                pol = get_task_policy(current);
-
+       if (pol->mode == MPOL_INTERLEAVE) {
+               *ilx += vma->vm_pgoff >> order;
+               *ilx += (addr - vma->vm_start) >> (PAGE_SHIFT + order);
+       }
        return pol;
 }
 
@@ -1820,8 +1788,9 @@ bool vma_policy_mof(struct vm_area_struct *vma)
 
        if (vma->vm_ops && vma->vm_ops->get_policy) {
                bool ret = false;
+               pgoff_t ilx;            /* ignored here */
 
-               pol = vma->vm_ops->get_policy(vma, vma->vm_start);
+               pol = vma->vm_ops->get_policy(vma, vma->vm_start, &ilx);
                if (pol && (pol->flags & MPOL_F_MOF))
                        ret = true;
                mpol_cond_put(pol);
@@ -1856,64 +1825,15 @@ bool apply_policy_zone(struct mempolicy *policy, enum zone_type zone)
        return zone >= dynamic_policy_zone;
 }
 
-/*
- * Return a nodemask representing a mempolicy for filtering nodes for
- * page allocation
- */
-nodemask_t *policy_nodemask(gfp_t gfp, struct mempolicy *policy)
-{
-       int mode = policy->mode;
-
-       /* Lower zones don't get a nodemask applied for MPOL_BIND */
-       if (unlikely(mode == MPOL_BIND) &&
-               apply_policy_zone(policy, gfp_zone(gfp)) &&
-               cpuset_nodemask_valid_mems_allowed(&policy->nodes))
-               return &policy->nodes;
-
-       if (mode == MPOL_PREFERRED_MANY)
-               return &policy->nodes;
-
-       return NULL;
-}
-
-/*
- * Return the  preferred node id for 'prefer' mempolicy, and return
- * the given id for all other policies.
- *
- * policy_node() is always coupled with policy_nodemask(), which
- * secures the nodemask limit for 'bind' and 'prefer-many' policy.
- */
-static int policy_node(gfp_t gfp, struct mempolicy *policy, int nd)
-{
-       if (policy->mode == MPOL_PREFERRED) {
-               nd = first_node(policy->nodes);
-       } else {
-               /*
-                * __GFP_THISNODE shouldn't even be used with the bind policy
-                * because we might easily break the expectation to stay on the
-                * requested node and not break the policy.
-                */
-               WARN_ON_ONCE(policy->mode == MPOL_BIND && (gfp & __GFP_THISNODE));
-       }
-
-       if ((policy->mode == MPOL_BIND ||
-            policy->mode == MPOL_PREFERRED_MANY) &&
-           policy->home_node != NUMA_NO_NODE)
-               return policy->home_node;
-
-       return nd;
-}
-
 /* Do dynamic interleaving for a process */
-static unsigned interleave_nodes(struct mempolicy *policy)
+static unsigned int interleave_nodes(struct mempolicy *policy)
 {
-       unsigned next;
-       struct task_struct *me = current;
+       unsigned int nid;
 
-       next = next_node_in(me->il_prev, policy->nodes);
-       if (next < MAX_NUMNODES)
-               me->il_prev = next;
-       return next;
+       nid = next_node_in(current->il_prev, policy->nodes);
+       if (nid < MAX_NUMNODES)
+               current->il_prev = nid;
+       return nid;
 }
 
 /*
@@ -1964,11 +1884,11 @@ unsigned int mempolicy_slab_node(void)
 }
 
 /*
- * Do static interleaving for a VMA with known offset @n.  Returns the n'th
- * node in pol->nodes (starting from n=0), wrapping around if n exceeds the
- * number of present nodes.
+ * Do static interleaving for interleave index @ilx.  Returns the ilx'th
+ * node in pol->nodes (starting from ilx=0), wrapping around if ilx
+ * exceeds the number of present nodes.
  */
-static unsigned offset_il_node(struct mempolicy *pol, unsigned long n)
+static unsigned int interleave_nid(struct mempolicy *pol, pgoff_t ilx)
 {
        nodemask_t nodemask = pol->nodes;
        unsigned int target, nnodes;
@@ -1986,33 +1906,54 @@ static unsigned offset_il_node(struct mempolicy *pol, unsigned long n)
        nnodes = nodes_weight(nodemask);
        if (!nnodes)
                return numa_node_id();
-       target = (unsigned int)n % nnodes;
+       target = ilx % nnodes;
        nid = first_node(nodemask);
        for (i = 0; i < target; i++)
                nid = next_node(nid, nodemask);
        return nid;
 }
 
-/* Determine a node number for interleave */
-static inline unsigned interleave_nid(struct mempolicy *pol,
-                struct vm_area_struct *vma, unsigned long addr, int shift)
+/*
+ * Return a nodemask representing a mempolicy for filtering nodes for
+ * page allocation, together with preferred node id (or the input node id).
+ */
+static nodemask_t *policy_nodemask(gfp_t gfp, struct mempolicy *pol,
+                                  pgoff_t ilx, int *nid)
 {
-       if (vma) {
-               unsigned long off;
+       nodemask_t *nodemask = NULL;
 
+       switch (pol->mode) {
+       case MPOL_PREFERRED:
+               /* Override input node id */
+               *nid = first_node(pol->nodes);
+               break;
+       case MPOL_PREFERRED_MANY:
+               nodemask = &pol->nodes;
+               if (pol->home_node != NUMA_NO_NODE)
+                       *nid = pol->home_node;
+               break;
+       case MPOL_BIND:
+               /* Restrict to nodemask (but not on lower zones) */
+               if (apply_policy_zone(pol, gfp_zone(gfp)) &&
+                   cpuset_nodemask_valid_mems_allowed(&pol->nodes))
+                       nodemask = &pol->nodes;
+               if (pol->home_node != NUMA_NO_NODE)
+                       *nid = pol->home_node;
                /*
-                * for small pages, there is no difference between
-                * shift and PAGE_SHIFT, so the bit-shift is safe.
-                * for huge pages, since vm_pgoff is in units of small
-                * pages, we need to shift off the always 0 bits to get
-                * a useful offset.
+                * __GFP_THISNODE shouldn't even be used with the bind policy
+                * because we might easily break the expectation to stay on the
+                * requested node and not break the policy.
                 */
-               BUG_ON(shift < PAGE_SHIFT);
-               off = vma->vm_pgoff >> (shift - PAGE_SHIFT);
-               off += (addr - vma->vm_start) >> shift;
-               return offset_il_node(pol, off);
-       } else
-               return interleave_nodes(pol);
+               WARN_ON_ONCE(gfp & __GFP_THISNODE);
+               break;
+       case MPOL_INTERLEAVE:
+               /* Override input node id */
+               *nid = (ilx == NO_INTERLEAVE_INDEX) ?
+                       interleave_nodes(pol) : interleave_nid(pol, ilx);
+               break;
+       }
+
+       return nodemask;
 }
 
 #ifdef CONFIG_HUGETLBFS
@@ -2028,27 +1969,16 @@ static inline unsigned interleave_nid(struct mempolicy *pol,
  * to the struct mempolicy for conditional unref after allocation.
  * If the effective policy is 'bind' or 'prefer-many', returns a pointer
  * to the mempolicy's @nodemask for filtering the zonelist.
- *
- * Must be protected by read_mems_allowed_begin()
  */
 int huge_node(struct vm_area_struct *vma, unsigned long addr, gfp_t gfp_flags,
-                               struct mempolicy **mpol, nodemask_t **nodemask)
+               struct mempolicy **mpol, nodemask_t **nodemask)
 {
+       pgoff_t ilx;
        int nid;
-       int mode;
-
-       *mpol = get_vma_policy(vma, addr);
-       *nodemask = NULL;
-       mode = (*mpol)->mode;
 
-       if (unlikely(mode == MPOL_INTERLEAVE)) {
-               nid = interleave_nid(*mpol, vma, addr,
-                                       huge_page_shift(hstate_vma(vma)));
-       } else {
-               nid = policy_node(gfp_flags, *mpol, numa_node_id());
-               if (mode == MPOL_BIND || mode == MPOL_PREFERRED_MANY)
-                       *nodemask = &(*mpol)->nodes;
-       }
+       nid = numa_node_id();
+       *mpol = get_vma_policy(vma, addr, hstate_vma(vma)->order, &ilx);
+       *nodemask = policy_nodemask(gfp_flags, *mpol, ilx, &nid);
        return nid;
 }
 
@@ -2126,27 +2056,8 @@ bool mempolicy_in_oom_domain(struct task_struct *tsk,
        return ret;
 }
 
-/* Allocate a page in interleaved policy.
-   Own path because it needs to do special accounting. */
-static struct page *alloc_page_interleave(gfp_t gfp, unsigned order,
-                                       unsigned nid)
-{
-       struct page *page;
-
-       page = __alloc_pages(gfp, order, nid, NULL);
-       /* skip NUMA_INTERLEAVE_HIT counter update if numa stats is disabled */
-       if (!static_branch_likely(&vm_numa_stat_key))
-               return page;
-       if (page && page_to_nid(page) == nid) {
-               preempt_disable();
-               __count_numa_event(page_zone(page), NUMA_INTERLEAVE_HIT);
-               preempt_enable();
-       }
-       return page;
-}
-
 static struct page *alloc_pages_preferred_many(gfp_t gfp, unsigned int order,
-                                               int nid, struct mempolicy *pol)
+                                               int nid, nodemask_t *nodemask)
 {
        struct page *page;
        gfp_t preferred_gfp;
@@ -2159,7 +2070,7 @@ static struct page *alloc_pages_preferred_many(gfp_t gfp, unsigned int order,
         */
        preferred_gfp = gfp | __GFP_NOWARN;
        preferred_gfp &= ~(__GFP_DIRECT_RECLAIM | __GFP_NOFAIL);
-       page = __alloc_pages(preferred_gfp, order, nid, &pol->nodes);
+       page = __alloc_pages(preferred_gfp, order, nid, nodemask);
        if (!page)
                page = __alloc_pages(gfp, order, nid, NULL);
 
@@ -2167,61 +2078,29 @@ static struct page *alloc_pages_preferred_many(gfp_t gfp, unsigned int order,
 }
 
 /**
- * vma_alloc_folio - Allocate a folio for a VMA.
+ * alloc_pages_mpol - Allocate pages according to NUMA mempolicy.
  * @gfp: GFP flags.
- * @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.
+ * @order: Order of the page allocation.
+ * @pol: Pointer to the NUMA mempolicy.
+ * @ilx: Index for interleave mempolicy (also distinguishes alloc_pages()).
+ * @nid: Preferred node (usually numa_node_id() but @mpol may override it).
  *
- * 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 folios that will be mapped into user space.
- *
- * Return: The folio on success or NULL if allocation fails.
+ * Return: The page on success or NULL if allocation fails.
  */
-struct folio *vma_alloc_folio(gfp_t gfp, int order, struct vm_area_struct *vma,
-               unsigned long addr, bool hugepage)
+struct page *alloc_pages_mpol(gfp_t gfp, unsigned int order,
+               struct mempolicy *pol, pgoff_t ilx, int nid)
 {
-       struct mempolicy *pol;
-       int node = numa_node_id();
-       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);
-               folio = (struct folio *)page;
-               if (folio && order > 1)
-                       folio_prep_large_rmappable(folio);
-               goto out;
-       }
-
-       if (pol->mode == MPOL_PREFERRED_MANY) {
-               struct page *page;
+       nodemask_t *nodemask;
+       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);
-               folio = (struct folio *)page;
-               if (folio && order > 1)
-                       folio_prep_large_rmappable(folio);
-               goto out;
-       }
+       nodemask = policy_nodemask(gfp, pol, ilx, &nid);
 
-       if (unlikely(IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && hugepage)) {
-               int hpage_node = node;
+       if (pol->mode == MPOL_PREFERRED_MANY)
+               return alloc_pages_preferred_many(gfp, order, nid, nodemask);
 
+       if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) &&
+           /* filter "hugepage" allocation, unless from alloc_pages() */
+           order == HPAGE_PMD_ORDER && ilx != NO_INTERLEAVE_INDEX) {
                /*
                 * For hugepage allocation and non-interleave policy which
                 * allows the current node (or other explicitly preferred
@@ -2232,39 +2111,68 @@ struct folio *vma_alloc_folio(gfp_t gfp, int order, struct vm_area_struct *vma,
                 * If the policy is interleave or does not allow the current
                 * node in its nodemask, we allocate the standard way.
                 */
-               if (pol->mode == MPOL_PREFERRED)
-                       hpage_node = first_node(pol->nodes);
-
-               nmask = policy_nodemask(gfp, pol);
-               if (!nmask || node_isset(hpage_node, *nmask)) {
-                       mpol_cond_put(pol);
+               if (pol->mode != MPOL_INTERLEAVE &&
+                   (!nodemask || node_isset(nid, *nodemask))) {
                        /*
                         * First, try to allocate THP only on local node, but
                         * don't reclaim unnecessarily, just compact.
                         */
-                       folio = __folio_alloc_node(gfp | __GFP_THISNODE |
-                                       __GFP_NORETRY, order, hpage_node);
-
+                       page = __alloc_pages_node(nid,
+                               gfp | __GFP_THISNODE | __GFP_NORETRY, order);
+                       if (page || !(gfp & __GFP_DIRECT_RECLAIM))
+                               return page;
                        /*
                         * If hugepage allocations are configured to always
                         * synchronous compact or the vma has been madvised
                         * to prefer hugepage backing, retry allowing remote
                         * memory with both reclaim and compact as well.
                         */
-                       if (!folio && (gfp & __GFP_DIRECT_RECLAIM))
-                               folio = __folio_alloc(gfp, order, hpage_node,
-                                                     nmask);
+               }
+       }
 
-                       goto out;
+       page = __alloc_pages(gfp, order, nid, nodemask);
+
+       if (unlikely(pol->mode == MPOL_INTERLEAVE) && page) {
+               /* skip NUMA_INTERLEAVE_HIT update if numa stats is disabled */
+               if (static_branch_likely(&vm_numa_stat_key) &&
+                   page_to_nid(page) == nid) {
+                       preempt_disable();
+                       __count_numa_event(page_zone(page), NUMA_INTERLEAVE_HIT);
+                       preempt_enable();
                }
        }
 
-       nmask = policy_nodemask(gfp, pol);
-       preferred_nid = policy_node(gfp, pol, node);
-       folio = __folio_alloc(gfp, order, preferred_nid, nmask);
+       return page;
+}
+
+/**
+ * vma_alloc_folio - Allocate a folio for a VMA.
+ * @gfp: GFP flags.
+ * @order: Order of the folio.
+ * @vma: Pointer to VMA.
+ * @addr: Virtual address of the allocation.  Must be inside @vma.
+ * @hugepage: Unused (was: For hugepages try only preferred node if possible).
+ *
+ * Allocate a folio for a specific address in @vma, using the appropriate
+ * NUMA policy.  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 folios that will be mapped into user space, excepting hugetlbfs, and
+ * excepting where direct use of alloc_pages_mpol() is more appropriate.
+ *
+ * Return: The folio on success or NULL if allocation fails.
+ */
+struct folio *vma_alloc_folio(gfp_t gfp, int order, struct vm_area_struct *vma,
+               unsigned long addr, bool hugepage)
+{
+       struct mempolicy *pol;
+       pgoff_t ilx;
+       struct page *page;
+
+       pol = get_vma_policy(vma, addr, order, &ilx);
+       page = alloc_pages_mpol(gfp | __GFP_COMP, order,
+                               pol, ilx, numa_node_id());
        mpol_cond_put(pol);
-out:
-       return folio;
+       return page_rmappable_folio(page);
 }
 EXPORT_SYMBOL(vma_alloc_folio);
 
@@ -2282,40 +2190,25 @@ EXPORT_SYMBOL(vma_alloc_folio);
  * flags are used.
  * Return: The page on success or NULL if allocation fails.
  */
-struct page *alloc_pages(gfp_t gfp, unsigned order)
+struct page *alloc_pages(gfp_t gfp, unsigned int order)
 {
        struct mempolicy *pol = &default_policy;
-       struct page *page;
-
-       if (!in_interrupt() && !(gfp & __GFP_THISNODE))
-               pol = get_task_policy(current);
 
        /*
         * No reference counting needed for current->mempolicy
         * nor system default_policy
         */
-       if (pol->mode == MPOL_INTERLEAVE)
-               page = alloc_page_interleave(gfp, order, interleave_nodes(pol));
-       else if (pol->mode == MPOL_PREFERRED_MANY)
-               page = alloc_pages_preferred_many(gfp, order,
-                                 policy_node(gfp, pol, numa_node_id()), pol);
-       else
-               page = __alloc_pages(gfp, order,
-                               policy_node(gfp, pol, numa_node_id()),
-                               policy_nodemask(gfp, pol));
+       if (!in_interrupt() && !(gfp & __GFP_THISNODE))
+               pol = get_task_policy(current);
 
-       return page;
+       return alloc_pages_mpol(gfp, order,
+                               pol, NO_INTERLEAVE_INDEX, numa_node_id());
 }
 EXPORT_SYMBOL(alloc_pages);
 
-struct folio *folio_alloc(gfp_t gfp, unsigned order)
+struct folio *folio_alloc(gfp_t gfp, unsigned int order)
 {
-       struct page *page = alloc_pages(gfp | __GFP_COMP, order);
-       struct folio *folio = (struct folio *)page;
-
-       if (folio && order > 1)
-               folio_prep_large_rmappable(folio);
-       return folio;
+       return page_rmappable_folio(alloc_pages(gfp | __GFP_COMP, order));
 }
 EXPORT_SYMBOL(folio_alloc);
 
@@ -2384,6 +2277,8 @@ unsigned long alloc_pages_bulk_array_mempolicy(gfp_t gfp,
                unsigned long nr_pages, struct page **page_array)
 {
        struct mempolicy *pol = &default_policy;
+       nodemask_t *nodemask;
+       int nid;
 
        if (!in_interrupt() && !(gfp & __GFP_THISNODE))
                pol = get_task_policy(current);
@@ -2396,14 +2291,15 @@ unsigned long alloc_pages_bulk_array_mempolicy(gfp_t gfp,
                return alloc_pages_bulk_array_preferred_many(gfp,
                                numa_node_id(), pol, nr_pages, page_array);
 
-       return __alloc_pages_bulk(gfp, policy_node(gfp, pol, numa_node_id()),
-                                 policy_nodemask(gfp, pol), nr_pages, NULL,
-                                 page_array);
+       nid = numa_node_id();
+       nodemask = policy_nodemask(gfp, pol, NO_INTERLEAVE_INDEX, &nid);
+       return __alloc_pages_bulk(gfp, nid, nodemask,
+                                 nr_pages, NULL, page_array);
 }
 
 int vma_dup_policy(struct vm_area_struct *src, struct vm_area_struct *dst)
 {
-       struct mempolicy *pol = mpol_dup(vma_policy(src));
+       struct mempolicy *pol = mpol_dup(src->vm_policy);
 
        if (IS_ERR(pol))
                return PTR_ERR(pol);
@@ -2488,8 +2384,8 @@ bool __mpol_equal(struct mempolicy *a, struct mempolicy *b)
  * lookup first element intersecting start-end.  Caller holds sp->lock for
  * reading or for writing
  */
-static struct sp_node *
-sp_lookup(struct shared_policy *sp, unsigned long start, unsigned long end)
+static struct sp_node *sp_lookup(struct shared_policy *sp,
+                                       pgoff_t start, pgoff_t end)
 {
        struct rb_node *n = sp->root.rb_node;
 
@@ -2540,13 +2436,11 @@ static void sp_insert(struct shared_policy *sp, struct sp_node *new)
        }
        rb_link_node(&new->nd, parent, p);
        rb_insert_color(&new->nd, &sp->root);
-       pr_debug("inserting %lx-%lx: %d\n", new->start, new->end,
-                new->policy ? new->policy->mode : 0);
 }
 
 /* Find shared policy intersecting idx */
-struct mempolicy *
-mpol_shared_policy_lookup(struct shared_policy *sp, unsigned long idx)
+struct mempolicy *mpol_shared_policy_lookup(struct shared_policy *sp,
+                                               pgoff_t idx)
 {
        struct mempolicy *pol = NULL;
        struct sp_node *sn;
@@ -2570,39 +2464,38 @@ static void sp_free(struct sp_node *n)
 }
 
 /**
- * mpol_misplaced - check whether current page node is valid in policy
+ * mpol_misplaced - check whether current folio node is valid in policy
  *
- * @page: page to be checked
- * @vma: vm area where page mapped
- * @addr: virtual address where page mapped
+ * @folio: folio to be checked
+ * @vma: vm area where folio mapped
+ * @addr: virtual address in @vma for shared policy lookup and interleave policy
  *
- * Lookup current policy node id for vma,addr and "compare to" page's
+ * Lookup current policy node id for vma,addr and "compare to" folio's
  * node id.  Policy determination "mimics" alloc_page_vma().
  * Called from fault path where we know the vma and faulting address.
  *
  * Return: NUMA_NO_NODE if the page is in a node that is valid for this
- * policy, or a suitable node ID to allocate a replacement page from.
+ * policy, or a suitable node ID to allocate a replacement folio from.
  */
-int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long addr)
+int mpol_misplaced(struct folio *folio, struct vm_area_struct *vma,
+                  unsigned long addr)
 {
        struct mempolicy *pol;
+       pgoff_t ilx;
        struct zoneref *z;
-       int curnid = page_to_nid(page);
-       unsigned long pgoff;
+       int curnid = folio_nid(folio);
        int thiscpu = raw_smp_processor_id();
        int thisnid = cpu_to_node(thiscpu);
        int polnid = NUMA_NO_NODE;
        int ret = NUMA_NO_NODE;
 
-       pol = get_vma_policy(vma, addr);
+       pol = get_vma_policy(vma, addr, folio_order(folio), &ilx);
        if (!(pol->flags & MPOL_F_MOF))
                goto out;
 
        switch (pol->mode) {
        case MPOL_INTERLEAVE:
-               pgoff = vma->vm_pgoff;
-               pgoff += (addr - vma->vm_start) >> PAGE_SHIFT;
-               polnid = offset_il_node(pol, pgoff);
+               polnid = interleave_nid(pol, ilx);
                break;
 
        case MPOL_PREFERRED:
@@ -2643,11 +2536,12 @@ int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long
                BUG();
        }
 
-       /* Migrate the page towards the node whose CPU is referencing it */
+       /* Migrate the folio towards the node whose CPU is referencing it */
        if (pol->flags & MPOL_F_MORON) {
                polnid = thisnid;
 
-               if (!should_numa_migrate_memory(current, page, curnid, thiscpu))
+               if (!should_numa_migrate_memory(current, folio, curnid,
+                                               thiscpu))
                        goto out;
        }
 
@@ -2678,7 +2572,6 @@ void mpol_put_task_policy(struct task_struct *task)
 
 static void sp_delete(struct shared_policy *sp, struct sp_node *n)
 {
-       pr_debug("deleting %lx-l%lx\n", n->start, n->end);
        rb_erase(&n->nd, &sp->root);
        sp_free(n);
 }
@@ -2713,8 +2606,8 @@ static struct sp_node *sp_alloc(unsigned long start, unsigned long end,
 }
 
 /* Replace a policy range. */
-static int shared_policy_replace(struct shared_policy *sp, unsigned long start,
-                                unsigned long end, struct sp_node *new)
+static int shared_policy_replace(struct shared_policy *sp, pgoff_t start,
+                                pgoff_t end, struct sp_node *new)
 {
        struct sp_node *n;
        struct sp_node *n_new = NULL;
@@ -2797,30 +2690,30 @@ void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol)
        rwlock_init(&sp->lock);
 
        if (mpol) {
-               struct vm_area_struct pvma;
-               struct mempolicy *new;
+               struct sp_node *sn;
+               struct mempolicy *npol;
                NODEMASK_SCRATCH(scratch);
 
                if (!scratch)
                        goto put_mpol;
-               /* contextualize the tmpfs mount point mempolicy */
-               new = mpol_new(mpol->mode, mpol->flags, &mpol->w.user_nodemask);
-               if (IS_ERR(new))
+
+               /* contextualize the tmpfs mount point mempolicy to this file */
+               npol = mpol_new(mpol->mode, mpol->flags, &mpol->w.user_nodemask);
+               if (IS_ERR(npol))
                        goto free_scratch; /* no valid nodemask intersection */
 
                task_lock(current);
-               ret = mpol_set_nodemask(new, &mpol->w.user_nodemask, scratch);
+               ret = mpol_set_nodemask(npol, &mpol->w.user_nodemask, scratch);
                task_unlock(current);
                if (ret)
-                       goto put_new;
-
-               /* Create pseudo-vma that contains just the policy */
-               vma_init(&pvma, NULL);
-               pvma.vm_end = TASK_SIZE;        /* policy covers entire file */
-               mpol_set_shared_policy(sp, &pvma, new); /* adds ref */
-
-put_new:
-               mpol_put(new);                  /* drop initial ref */
+                       goto put_npol;
+
+               /* alloc node covering entire file; adds ref to file's npol */
+               sn = sp_alloc(0, MAX_LFS_FILESIZE >> PAGE_SHIFT, npol);
+               if (sn)
+                       sp_insert(sp, sn);
+put_npol:
+               mpol_put(npol); /* drop initial ref on file's npol */
 free_scratch:
                NODEMASK_SCRATCH_FREE(scratch);
 put_mpol:
@@ -2828,46 +2721,40 @@ put_mpol:
        }
 }
 
-int mpol_set_shared_policy(struct shared_policy *info,
-                       struct vm_area_struct *vma, struct mempolicy *npol)
+int mpol_set_shared_policy(struct shared_policy *sp,
+                       struct vm_area_struct *vma, struct mempolicy *pol)
 {
        int err;
        struct sp_node *new = NULL;
        unsigned long sz = vma_pages(vma);
 
-       pr_debug("set_shared_policy %lx sz %lu %d %d %lx\n",
-                vma->vm_pgoff,
-                sz, npol ? npol->mode : -1,
-                npol ? npol->flags : -1,
-                npol ? nodes_addr(npol->nodes)[0] : NUMA_NO_NODE);
-
-       if (npol) {
-               new = sp_alloc(vma->vm_pgoff, vma->vm_pgoff + sz, npol);
+       if (pol) {
+               new = sp_alloc(vma->vm_pgoff, vma->vm_pgoff + sz, pol);
                if (!new)
                        return -ENOMEM;
        }
-       err = shared_policy_replace(info, vma->vm_pgoff, vma->vm_pgoff+sz, new);
+       err = shared_policy_replace(sp, vma->vm_pgoff, vma->vm_pgoff + sz, new);
        if (err && new)
                sp_free(new);
        return err;
 }
 
 /* Free a backing policy store on inode delete. */
-void mpol_free_shared_policy(struct shared_policy *p)
+void mpol_free_shared_policy(struct shared_policy *sp)
 {
        struct sp_node *n;
        struct rb_node *next;
 
-       if (!p->root.rb_node)
+       if (!sp->root.rb_node)
                return;
-       write_lock(&p->lock);
-       next = rb_first(&p->root);
+       write_lock(&sp->lock);
+       next = rb_first(&sp->root);
        while (next) {
                n = rb_entry(next, struct sp_node, nd);
                next = rb_next(&n->nd);
-               sp_delete(p, n);
+               sp_delete(sp, n);
        }
-       write_unlock(&p->lock);
+       write_unlock(&sp->lock);
 }
 
 #ifdef CONFIG_NUMA_BALANCING
@@ -2917,7 +2804,6 @@ static inline void __init check_numabalancing_enable(void)
 }
 #endif /* CONFIG_NUMA_BALANCING */
 
-/* assumes fs == KERNEL_DS */
 void __init numa_policy_init(void)
 {
        nodemask_t interleave_nodes;
@@ -2980,7 +2866,6 @@ void numa_default_policy(void)
 /*
  * Parse and format mempolicy from/to strings
  */
-
 static const char * const policy_modes[] =
 {
        [MPOL_DEFAULT]    = "default",
@@ -2991,7 +2876,6 @@ static const char * const policy_modes[] =
        [MPOL_PREFERRED_MANY]  = "prefer (many)",
 };
 
-
 #ifdef CONFIG_TMPFS
 /**
  * mpol_parse_str - parse string to mempolicy, for tmpfs mpol mount option.