]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
mm/huge_memory: move THP gfp limit helper into header
authorKairui Song <kasong@tencent.com>
Sun, 17 May 2026 15:39:42 +0000 (23:39 +0800)
committerAndrew Morton <akpm@linux-foundation.org>
Tue, 2 Jun 2026 22:22:21 +0000 (15:22 -0700)
Shmem has some special requirements for THP GFP and has to limit it in
certain zones or provide a more lenient fallback.

We'll use this helper for generic swap THP allocation, which needs to
support shmem.  For a typical GFP_HIGHUSER_MOVABLE swap-in, this helper is
basically a no-op.  But it's necessary for certain shmem users, mostly
drivers.

No feature change.

Link: https://lore.kernel.org/20260517-swap-table-p4-v5-3-88ae43e064c7@tencent.com
Signed-off-by: Kairui Song <kasong@tencent.com>
Acked-by: Chris Li <chrisl@kernel.org>
Reviewed-by: Zi Yan <ziy@nvidia.com>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: Barry Song <baohua@kernel.org>
Cc: Chengming Zhou <chengming.zhou@linux.dev>
Cc: David Hildenbrand <david@kernel.org>
Cc: Hugh Dickins <hughd@google.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Kemeng Shi <shikemeng@huaweicloud.com>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Youngjun Park <youngjun.park@lge.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
include/linux/huge_mm.h
mm/shmem.c

index 2949e5acff351bdb6b5747ad6e60459916dfd94a..58382e97a66d3f97f8848f70836bb5c161300f74 100644 (file)
@@ -237,6 +237,31 @@ static inline bool thp_vma_suitable_order(struct vm_area_struct *vma,
        return true;
 }
 
+/*
+ * Make sure huge_gfp is always more limited than limit_gfp.
+ * Some shmem users want THP allocation to be done less aggressively
+ * and only in certain zone.
+ */
+static inline gfp_t thp_shmem_limit_gfp_mask(gfp_t huge_gfp, gfp_t limit_gfp)
+{
+       gfp_t allowflags = __GFP_IO | __GFP_FS | __GFP_RECLAIM;
+       gfp_t denyflags = __GFP_NOWARN | __GFP_NORETRY;
+       gfp_t zoneflags = limit_gfp & GFP_ZONEMASK;
+       gfp_t result = huge_gfp & ~(allowflags | GFP_ZONEMASK);
+
+       /* Allow allocations only from the originally specified zones. */
+       result |= zoneflags;
+
+       /*
+        * Minimize the result gfp by taking the union with the deny flags,
+        * and the intersection of the allow flags.
+        */
+       result |= (limit_gfp & denyflags);
+       result |= (huge_gfp & limit_gfp) & allowflags;
+
+       return result;
+}
+
 /*
  * Filter the bitfield of input orders to the ones suitable for use in the vma.
  * See thp_vma_suitable_order().
@@ -581,6 +606,11 @@ static inline bool thp_vma_suitable_order(struct vm_area_struct *vma,
        return false;
 }
 
+static inline gfp_t thp_shmem_limit_gfp_mask(gfp_t huge_gfp, gfp_t limit_gfp)
+{
+       return huge_gfp;
+}
+
 static inline unsigned long thp_vma_suitable_orders(struct vm_area_struct *vma,
                unsigned long addr, unsigned long orders)
 {
index bab3529af23c563ba80052336c9ed7d864d4f8ed..6edb23b41bac9582629d8646709f11a9dbbd6d55 100644 (file)
@@ -1791,30 +1791,6 @@ static struct folio *shmem_swapin_cluster(swp_entry_t swap, gfp_t gfp,
        return folio;
 }
 
-/*
- * Make sure huge_gfp is always more limited than limit_gfp.
- * Some of the flags set permissions, while others set limitations.
- */
-static gfp_t limit_gfp_mask(gfp_t huge_gfp, gfp_t limit_gfp)
-{
-       gfp_t allowflags = __GFP_IO | __GFP_FS | __GFP_RECLAIM;
-       gfp_t denyflags = __GFP_NOWARN | __GFP_NORETRY;
-       gfp_t zoneflags = limit_gfp & GFP_ZONEMASK;
-       gfp_t result = huge_gfp & ~(allowflags | GFP_ZONEMASK);
-
-       /* Allow allocations only from the originally specified zones. */
-       result |= zoneflags;
-
-       /*
-        * Minimize the result gfp by taking the union with the deny flags,
-        * and the intersection of the allow flags.
-        */
-       result |= (limit_gfp & denyflags);
-       result |= (huge_gfp & limit_gfp) & allowflags;
-
-       return result;
-}
-
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 bool shmem_hpage_pmd_enabled(void)
 {
@@ -2065,7 +2041,7 @@ static struct folio *shmem_swap_alloc_folio(struct inode *inode,
                     non_swapcache_batch(entry, nr_pages) != nr_pages)
                        goto fallback;
 
-               alloc_gfp = limit_gfp_mask(vma_thp_gfp_mask(vma), gfp);
+               alloc_gfp = thp_shmem_limit_gfp_mask(vma_thp_gfp_mask(vma), gfp);
        }
 retry:
        new = shmem_alloc_folio(alloc_gfp, order, info, index);
@@ -2141,7 +2117,7 @@ static int shmem_replace_folio(struct folio **foliop, gfp_t gfp,
        if (nr_pages > 1) {
                gfp_t huge_gfp = vma_thp_gfp_mask(vma);
 
-               gfp = limit_gfp_mask(huge_gfp, gfp);
+               gfp = thp_shmem_limit_gfp_mask(huge_gfp, gfp);
        }
 #endif
 
@@ -2548,7 +2524,7 @@ repeat:
                gfp_t huge_gfp;
 
                huge_gfp = vma_thp_gfp_mask(vma);
-               huge_gfp = limit_gfp_mask(huge_gfp, gfp);
+               huge_gfp = thp_shmem_limit_gfp_mask(huge_gfp, gfp);
                folio = shmem_alloc_and_add_folio(vmf, huge_gfp,
                                inode, index, fault_mm, orders);
                if (!IS_ERR(folio)) {