mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
mm/huge_memory: move THP gfp limit helper into header
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>
This commit is contained in:
parent
bebee474c1
commit
1dfbe92e70
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
30
mm/shmem.c
30
mm/shmem.c
|
|
@ -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 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
|
|||
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)) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user