Skip to content

Commit d66b698

Browse files
committed
Merge tag 'folio-5.18e' of git://git.infradead.org/users/willy/pagecache
Pull folio fixes from Matthew Wilcox: "Fewer bug reports than I was expecting from enabling large folios. One that doesn't show up on x86 but does on arm64, one that shows up with hugetlbfs memory failure testing and one that shows up with page migration, which it turns out I wasn't testing because my last NUMA machine died. Need to set up a qemu fake NUMA machine so I don't skip testing that in future. Summary: - Remove the migration code's assumptions about large pages being PMD sized - Don't call pmd_page() on a non-leaf PMD - Fix handling of hugetlbfs pages in page_vma_mapped_walk" * tag 'folio-5.18e' of git://git.infradead.org/users/willy/pagecache: mm/rmap: Fix handling of hugetlbfs pages in page_vma_mapped_walk mm/mempolicy: Use vma_alloc_folio() in new_page() mm: Add vma_alloc_folio() mm/migrate: Use a folio in migrate_misplaced_transhuge_page() mm/migrate: Use a folio in alloc_migration_target() mm/huge_memory: Avoid calling pmd_page() on a non-leaf PMD
2 parents d00c50b + 98ea025 commit d66b698

5 files changed

Lines changed: 64 additions & 79 deletions

File tree

include/linux/gfp.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -613,9 +613,11 @@ static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask,
613613
#ifdef CONFIG_NUMA
614614
struct page *alloc_pages(gfp_t gfp, unsigned int order);
615615
struct folio *folio_alloc(gfp_t gfp, unsigned order);
616-
extern struct page *alloc_pages_vma(gfp_t gfp_mask, int order,
616+
struct page *alloc_pages_vma(gfp_t gfp_mask, int order,
617617
struct vm_area_struct *vma, unsigned long addr,
618618
bool hugepage);
619+
struct folio *vma_alloc_folio(gfp_t gfp, int order, struct vm_area_struct *vma,
620+
unsigned long addr, bool hugepage);
619621
#define alloc_hugepage_vma(gfp_mask, vma, addr, order) \
620622
alloc_pages_vma(gfp_mask, order, vma, addr, true)
621623
#else
@@ -627,8 +629,10 @@ static inline struct folio *folio_alloc(gfp_t gfp, unsigned int order)
627629
{
628630
return __folio_alloc_node(gfp, order, numa_node_id());
629631
}
630-
#define alloc_pages_vma(gfp_mask, order, vma, addr, false)\
632+
#define alloc_pages_vma(gfp_mask, order, vma, addr, hugepage) \
631633
alloc_pages(gfp_mask, order)
634+
#define vma_alloc_folio(gfp, order, vma, addr, hugepage) \
635+
folio_alloc(gfp, order)
632636
#define alloc_hugepage_vma(gfp_mask, vma, addr, order) \
633637
alloc_pages(gfp_mask, order)
634638
#endif

mm/huge_memory.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2145,15 +2145,14 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
21452145
* pmd against. Otherwise we can end up replacing wrong folio.
21462146
*/
21472147
VM_BUG_ON(freeze && !folio);
2148-
if (folio) {
2149-
VM_WARN_ON_ONCE(!folio_test_locked(folio));
2150-
if (folio != page_folio(pmd_page(*pmd)))
2151-
goto out;
2152-
}
2148+
VM_WARN_ON_ONCE(folio && !folio_test_locked(folio));
21532149

21542150
if (pmd_trans_huge(*pmd) || pmd_devmap(*pmd) ||
2155-
is_pmd_migration_entry(*pmd))
2151+
is_pmd_migration_entry(*pmd)) {
2152+
if (folio && folio != page_folio(pmd_page(*pmd)))
2153+
goto out;
21562154
__split_huge_pmd_locked(vma, pmd, range.start, freeze);
2155+
}
21572156

21582157
out:
21592158
spin_unlock(ptl);

mm/mempolicy.c

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,8 +1191,10 @@ int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
11911191
*/
11921192
static struct page *new_page(struct page *page, unsigned long start)
11931193
{
1194+
struct folio *dst, *src = page_folio(page);
11941195
struct vm_area_struct *vma;
11951196
unsigned long address;
1197+
gfp_t gfp = GFP_HIGHUSER_MOVABLE | __GFP_RETRY_MAYFAIL;
11961198

11971199
vma = find_vma(current->mm, start);
11981200
while (vma) {
@@ -1202,24 +1204,19 @@ static struct page *new_page(struct page *page, unsigned long start)
12021204
vma = vma->vm_next;
12031205
}
12041206

1205-
if (PageHuge(page)) {
1206-
return alloc_huge_page_vma(page_hstate(compound_head(page)),
1207+
if (folio_test_hugetlb(src))
1208+
return alloc_huge_page_vma(page_hstate(&src->page),
12071209
vma, address);
1208-
} else if (PageTransHuge(page)) {
1209-
struct page *thp;
12101210

1211-
thp = alloc_hugepage_vma(GFP_TRANSHUGE, vma, address,
1212-
HPAGE_PMD_ORDER);
1213-
if (!thp)
1214-
return NULL;
1215-
prep_transhuge_page(thp);
1216-
return thp;
1217-
}
1211+
if (folio_test_large(src))
1212+
gfp = GFP_TRANSHUGE;
1213+
12181214
/*
1219-
* if !vma, alloc_page_vma() will use task or system default policy
1215+
* if !vma, vma_alloc_folio() will use task or system default policy
12201216
*/
1221-
return alloc_page_vma(GFP_HIGHUSER_MOVABLE | __GFP_RETRY_MAYFAIL,
1222-
vma, address);
1217+
dst = vma_alloc_folio(gfp, folio_order(src), vma, address,
1218+
folio_test_large(src));
1219+
return &dst->page;
12231220
}
12241221
#else
12251222

@@ -2227,6 +2224,19 @@ struct page *alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
22272224
}
22282225
EXPORT_SYMBOL(alloc_pages_vma);
22292226

2227+
struct folio *vma_alloc_folio(gfp_t gfp, int order, struct vm_area_struct *vma,
2228+
unsigned long addr, bool hugepage)
2229+
{
2230+
struct folio *folio;
2231+
2232+
folio = (struct folio *)alloc_pages_vma(gfp, order, vma, addr,
2233+
hugepage);
2234+
if (folio && order > 1)
2235+
prep_transhuge_page(&folio->page);
2236+
2237+
return folio;
2238+
}
2239+
22302240
/**
22312241
* alloc_pages - Allocate pages.
22322242
* @gfp: GFP flags.

mm/migrate.c

Lines changed: 26 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1520,45 +1520,43 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page,
15201520

15211521
struct page *alloc_migration_target(struct page *page, unsigned long private)
15221522
{
1523+
struct folio *folio = page_folio(page);
15231524
struct migration_target_control *mtc;
15241525
gfp_t gfp_mask;
15251526
unsigned int order = 0;
1526-
struct page *new_page = NULL;
1527+
struct folio *new_folio = NULL;
15271528
int nid;
15281529
int zidx;
15291530

15301531
mtc = (struct migration_target_control *)private;
15311532
gfp_mask = mtc->gfp_mask;
15321533
nid = mtc->nid;
15331534
if (nid == NUMA_NO_NODE)
1534-
nid = page_to_nid(page);
1535+
nid = folio_nid(folio);
15351536

1536-
if (PageHuge(page)) {
1537-
struct hstate *h = page_hstate(compound_head(page));
1537+
if (folio_test_hugetlb(folio)) {
1538+
struct hstate *h = page_hstate(&folio->page);
15381539

15391540
gfp_mask = htlb_modify_alloc_mask(h, gfp_mask);
15401541
return alloc_huge_page_nodemask(h, nid, mtc->nmask, gfp_mask);
15411542
}
15421543

1543-
if (PageTransHuge(page)) {
1544+
if (folio_test_large(folio)) {
15441545
/*
15451546
* clear __GFP_RECLAIM to make the migration callback
15461547
* consistent with regular THP allocations.
15471548
*/
15481549
gfp_mask &= ~__GFP_RECLAIM;
15491550
gfp_mask |= GFP_TRANSHUGE;
1550-
order = HPAGE_PMD_ORDER;
1551+
order = folio_order(folio);
15511552
}
1552-
zidx = zone_idx(page_zone(page));
1553+
zidx = zone_idx(folio_zone(folio));
15531554
if (is_highmem_idx(zidx) || zidx == ZONE_MOVABLE)
15541555
gfp_mask |= __GFP_HIGHMEM;
15551556

1556-
new_page = __alloc_pages(gfp_mask, order, nid, mtc->nmask);
1557-
1558-
if (new_page && PageTransHuge(new_page))
1559-
prep_transhuge_page(new_page);
1557+
new_folio = __folio_alloc(gfp_mask, order, nid, mtc->nmask);
15601558

1561-
return new_page;
1559+
return &new_folio->page;
15621560
}
15631561

15641562
#ifdef CONFIG_NUMA
@@ -1999,32 +1997,20 @@ static struct page *alloc_misplaced_dst_page(struct page *page,
19991997
unsigned long data)
20001998
{
20011999
int nid = (int) data;
2002-
struct page *newpage;
2003-
2004-
newpage = __alloc_pages_node(nid,
2005-
(GFP_HIGHUSER_MOVABLE |
2006-
__GFP_THISNODE | __GFP_NOMEMALLOC |
2007-
__GFP_NORETRY | __GFP_NOWARN) &
2008-
~__GFP_RECLAIM, 0);
2009-
2010-
return newpage;
2011-
}
2012-
2013-
static struct page *alloc_misplaced_dst_page_thp(struct page *page,
2014-
unsigned long data)
2015-
{
2016-
int nid = (int) data;
2017-
struct page *newpage;
2018-
2019-
newpage = alloc_pages_node(nid, (GFP_TRANSHUGE_LIGHT | __GFP_THISNODE),
2020-
HPAGE_PMD_ORDER);
2021-
if (!newpage)
2022-
goto out;
2023-
2024-
prep_transhuge_page(newpage);
2000+
int order = compound_order(page);
2001+
gfp_t gfp = __GFP_THISNODE;
2002+
struct folio *new;
2003+
2004+
if (order > 0)
2005+
gfp |= GFP_TRANSHUGE_LIGHT;
2006+
else {
2007+
gfp |= GFP_HIGHUSER_MOVABLE | __GFP_NOMEMALLOC | __GFP_NORETRY |
2008+
__GFP_NOWARN;
2009+
gfp &= ~__GFP_RECLAIM;
2010+
}
2011+
new = __folio_alloc_node(gfp, order, nid);
20252012

2026-
out:
2027-
return newpage;
2013+
return &new->page;
20282014
}
20292015

20302016
static int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page)
@@ -2082,22 +2068,8 @@ int migrate_misplaced_page(struct page *page, struct vm_area_struct *vma,
20822068
int nr_remaining;
20832069
unsigned int nr_succeeded;
20842070
LIST_HEAD(migratepages);
2085-
new_page_t *new;
2086-
bool compound;
20872071
int nr_pages = thp_nr_pages(page);
20882072

2089-
/*
2090-
* PTE mapped THP or HugeTLB page can't reach here so the page could
2091-
* be either base page or THP. And it must be head page if it is
2092-
* THP.
2093-
*/
2094-
compound = PageTransHuge(page);
2095-
2096-
if (compound)
2097-
new = alloc_misplaced_dst_page_thp;
2098-
else
2099-
new = alloc_misplaced_dst_page;
2100-
21012073
/*
21022074
* Don't migrate file pages that are mapped in multiple processes
21032075
* with execute permissions as they are probably shared libraries.
@@ -2118,9 +2090,9 @@ int migrate_misplaced_page(struct page *page, struct vm_area_struct *vma,
21182090
goto out;
21192091

21202092
list_add(&page->lru, &migratepages);
2121-
nr_remaining = migrate_pages(&migratepages, *new, NULL, node,
2122-
MIGRATE_ASYNC, MR_NUMA_MISPLACED,
2123-
&nr_succeeded);
2093+
nr_remaining = migrate_pages(&migratepages, alloc_misplaced_dst_page,
2094+
NULL, node, MIGRATE_ASYNC,
2095+
MR_NUMA_MISPLACED, &nr_succeeded);
21242096
if (nr_remaining) {
21252097
if (!list_empty(&migratepages)) {
21262098
list_del(&page->lru);

mm/page_vma_mapped.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ bool page_vma_mapped_walk(struct page_vma_mapped_walk *pvmw)
163163
return not_found(pvmw);
164164

165165
if (unlikely(is_vm_hugetlb_page(vma))) {
166-
unsigned long size = pvmw->nr_pages * PAGE_SIZE;
166+
struct hstate *hstate = hstate_vma(vma);
167+
unsigned long size = huge_page_size(hstate);
167168
/* The only possible mapping was handled on last iteration */
168169
if (pvmw->pte)
169170
return not_found(pvmw);
@@ -173,8 +174,7 @@ bool page_vma_mapped_walk(struct page_vma_mapped_walk *pvmw)
173174
if (!pvmw->pte)
174175
return false;
175176

176-
pvmw->ptl = huge_pte_lockptr(size_to_hstate(size), mm,
177-
pvmw->pte);
177+
pvmw->ptl = huge_pte_lockptr(hstate, mm, pvmw->pte);
178178
spin_lock(pvmw->ptl);
179179
if (!check_pte(pvmw))
180180
return not_found(pvmw);

0 commit comments

Comments
 (0)