Skip to content

Commit c010d47

Browse files
x-y-zakpm00
authored andcommitted
mm: thp: split huge page to any lower order pages
To split a THP to any lower order pages, we need to reform THPs on subpages at given order and add page refcount based on the new page order. Also we need to reinitialize page_deferred_list after removing the page from the split_queue, otherwise a subsequent split will see list corruption when checking the page_deferred_list again. Note: Anonymous order-1 folio is not supported because _deferred_list, which is used by partially mapped folios, is stored in subpage 2 and an order-1 folio only has subpage 0 and 1. File-backed order-1 folios are fine, since they do not use _deferred_list. [[email protected]: fixup per discussion with Ryan] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Zi Yan <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Hugh Dickins <[email protected]> Cc: Kirill A. Shutemov <[email protected]> Cc: Luis Chamberlain <[email protected]> Cc: "Matthew Wilcox (Oracle)" <[email protected]> Cc: Michal Koutny <[email protected]> Cc: Roman Gushchin <[email protected]> Cc: Ryan Roberts <[email protected]> Cc: Yang Shi <[email protected]> Cc: Yu Zhao <[email protected]> Cc: Zach O'Keefe <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 46d44d0 commit c010d47

File tree

2 files changed

+96
-32
lines changed

2 files changed

+96
-32
lines changed

include/linux/huge_mm.h

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,11 @@ unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr,
265265

266266
void folio_prep_large_rmappable(struct folio *folio);
267267
bool can_split_folio(struct folio *folio, int *pextra_pins);
268-
int split_huge_page_to_list(struct page *page, struct list_head *list);
268+
int split_huge_page_to_list_to_order(struct page *page, struct list_head *list,
269+
unsigned int new_order);
269270
static inline int split_huge_page(struct page *page)
270271
{
271-
return split_huge_page_to_list(page, NULL);
272+
return split_huge_page_to_list_to_order(page, NULL, 0);
272273
}
273274
void deferred_split_folio(struct folio *folio);
274275

@@ -422,7 +423,8 @@ can_split_folio(struct folio *folio, int *pextra_pins)
422423
return false;
423424
}
424425
static inline int
425-
split_huge_page_to_list(struct page *page, struct list_head *list)
426+
split_huge_page_to_list_to_order(struct page *page, struct list_head *list,
427+
unsigned int new_order)
426428
{
427429
return 0;
428430
}
@@ -519,17 +521,20 @@ static inline bool thp_migration_supported(void)
519521
}
520522
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
521523

522-
static inline int split_folio_to_list(struct folio *folio,
523-
struct list_head *list)
524+
static inline int split_folio_to_list_to_order(struct folio *folio,
525+
struct list_head *list, int new_order)
524526
{
525-
return split_huge_page_to_list(&folio->page, list);
527+
return split_huge_page_to_list_to_order(&folio->page, list, new_order);
526528
}
527529

528-
static inline int split_folio(struct folio *folio)
530+
static inline int split_folio_to_order(struct folio *folio, int new_order)
529531
{
530-
return split_folio_to_list(folio, NULL);
532+
return split_folio_to_list_to_order(folio, NULL, new_order);
531533
}
532534

535+
#define split_folio_to_list(f, l) split_folio_to_list_to_order(f, l, 0)
536+
#define split_folio(f) split_folio_to_order(f, 0)
537+
533538
/*
534539
* archs that select ARCH_WANTS_THP_SWAP but don't support THP_SWP due to
535540
* limitations in the implementation like arm64 MTE can override this to

mm/huge_memory.c

Lines changed: 83 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2770,7 +2770,6 @@ static void lru_add_page_tail(struct page *head, struct page *tail,
27702770
struct lruvec *lruvec, struct list_head *list)
27712771
{
27722772
VM_BUG_ON_PAGE(!PageHead(head), head);
2773-
VM_BUG_ON_PAGE(PageCompound(tail), head);
27742773
VM_BUG_ON_PAGE(PageLRU(tail), head);
27752774
lockdep_assert_held(&lruvec->lru_lock);
27762775

@@ -2791,7 +2790,8 @@ static void lru_add_page_tail(struct page *head, struct page *tail,
27912790
}
27922791

27932792
static void __split_huge_page_tail(struct folio *folio, int tail,
2794-
struct lruvec *lruvec, struct list_head *list)
2793+
struct lruvec *lruvec, struct list_head *list,
2794+
unsigned int new_order)
27952795
{
27962796
struct page *head = &folio->page;
27972797
struct page *page_tail = head + tail;
@@ -2861,10 +2861,15 @@ static void __split_huge_page_tail(struct folio *folio, int tail,
28612861
* which needs correct compound_head().
28622862
*/
28632863
clear_compound_head(page_tail);
2864+
if (new_order) {
2865+
prep_compound_page(page_tail, new_order);
2866+
folio_prep_large_rmappable(new_folio);
2867+
}
28642868

28652869
/* Finally unfreeze refcount. Additional reference from page cache. */
2866-
page_ref_unfreeze(page_tail, 1 + (!folio_test_anon(folio) ||
2867-
folio_test_swapcache(folio)));
2870+
page_ref_unfreeze(page_tail,
2871+
1 + ((!folio_test_anon(folio) || folio_test_swapcache(folio)) ?
2872+
folio_nr_pages(new_folio) : 0));
28682873

28692874
if (folio_test_young(folio))
28702875
folio_set_young(new_folio);
@@ -2882,19 +2887,20 @@ static void __split_huge_page_tail(struct folio *folio, int tail,
28822887
}
28832888

28842889
static void __split_huge_page(struct page *page, struct list_head *list,
2885-
pgoff_t end)
2890+
pgoff_t end, unsigned int new_order)
28862891
{
28872892
struct folio *folio = page_folio(page);
28882893
struct page *head = &folio->page;
28892894
struct lruvec *lruvec;
28902895
struct address_space *swap_cache = NULL;
28912896
unsigned long offset = 0;
28922897
int i, nr_dropped = 0;
2898+
unsigned int new_nr = 1 << new_order;
28932899
int order = folio_order(folio);
28942900
unsigned int nr = 1 << order;
28952901

28962902
/* complete memcg works before add pages to LRU */
2897-
split_page_memcg(head, order, 0);
2903+
split_page_memcg(head, order, new_order);
28982904

28992905
if (folio_test_anon(folio) && folio_test_swapcache(folio)) {
29002906
offset = swp_offset(folio->swap);
@@ -2907,8 +2913,8 @@ static void __split_huge_page(struct page *page, struct list_head *list,
29072913

29082914
ClearPageHasHWPoisoned(head);
29092915

2910-
for (i = nr - 1; i >= 1; i--) {
2911-
__split_huge_page_tail(folio, i, lruvec, list);
2916+
for (i = nr - new_nr; i >= new_nr; i -= new_nr) {
2917+
__split_huge_page_tail(folio, i, lruvec, list, new_order);
29122918
/* Some pages can be beyond EOF: drop them from page cache */
29132919
if (head[i].index >= end) {
29142920
struct folio *tail = page_folio(head + i);
@@ -2929,24 +2935,30 @@ static void __split_huge_page(struct page *page, struct list_head *list,
29292935
}
29302936
}
29312937

2932-
ClearPageCompound(head);
2938+
if (!new_order)
2939+
ClearPageCompound(head);
2940+
else {
2941+
struct folio *new_folio = (struct folio *)head;
2942+
2943+
folio_set_order(new_folio, new_order);
2944+
}
29332945
unlock_page_lruvec(lruvec);
29342946
/* Caller disabled irqs, so they are still disabled here */
29352947

2936-
split_page_owner(head, order, 0);
2948+
split_page_owner(head, order, new_order);
29372949

29382950
/* See comment in __split_huge_page_tail() */
29392951
if (PageAnon(head)) {
29402952
/* Additional pin to swap cache */
29412953
if (PageSwapCache(head)) {
2942-
page_ref_add(head, 2);
2954+
page_ref_add(head, 1 + new_nr);
29432955
xa_unlock(&swap_cache->i_pages);
29442956
} else {
29452957
page_ref_inc(head);
29462958
}
29472959
} else {
29482960
/* Additional pin to page cache */
2949-
page_ref_add(head, 2);
2961+
page_ref_add(head, 1 + new_nr);
29502962
xa_unlock(&head->mapping->i_pages);
29512963
}
29522964
local_irq_enable();
@@ -2958,7 +2970,15 @@ static void __split_huge_page(struct page *page, struct list_head *list,
29582970
if (folio_test_swapcache(folio))
29592971
split_swap_cluster(folio->swap);
29602972

2961-
for (i = 0; i < nr; i++) {
2973+
/*
2974+
* set page to its compound_head when split to non order-0 pages, so
2975+
* we can skip unlocking it below, since PG_locked is transferred to
2976+
* the compound_head of the page and the caller will unlock it.
2977+
*/
2978+
if (new_order)
2979+
page = compound_head(page);
2980+
2981+
for (i = 0; i < nr; i += new_nr) {
29622982
struct page *subpage = head + i;
29632983
if (subpage == page)
29642984
continue;
@@ -2992,29 +3012,36 @@ bool can_split_folio(struct folio *folio, int *pextra_pins)
29923012
}
29933013

29943014
/*
2995-
* This function splits huge page into normal pages. @page can point to any
2996-
* subpage of huge page to split. Split doesn't change the position of @page.
3015+
* This function splits huge page into pages in @new_order. @page can point to
3016+
* any subpage of huge page to split. Split doesn't change the position of
3017+
* @page.
3018+
*
3019+
* NOTE: order-1 anonymous folio is not supported because _deferred_list,
3020+
* which is used by partially mapped folios, is stored in subpage 2 and an
3021+
* order-1 folio only has subpage 0 and 1. File-backed order-1 folios are OK,
3022+
* since they do not use _deferred_list.
29973023
*
29983024
* Only caller must hold pin on the @page, otherwise split fails with -EBUSY.
29993025
* The huge page must be locked.
30003026
*
30013027
* If @list is null, tail pages will be added to LRU list, otherwise, to @list.
30023028
*
3003-
* Both head page and tail pages will inherit mapping, flags, and so on from
3004-
* the hugepage.
3029+
* Pages in new_order will inherit mapping, flags, and so on from the hugepage.
30053030
*
3006-
* GUP pin and PG_locked transferred to @page. Rest subpages can be freed if
3007-
* they are not mapped.
3031+
* GUP pin and PG_locked transferred to @page or the compound page @page belongs
3032+
* to. Rest subpages can be freed if they are not mapped.
30083033
*
30093034
* Returns 0 if the hugepage is split successfully.
30103035
* Returns -EBUSY if the page is pinned or if anon_vma disappeared from under
30113036
* us.
30123037
*/
3013-
int split_huge_page_to_list(struct page *page, struct list_head *list)
3038+
int split_huge_page_to_list_to_order(struct page *page, struct list_head *list,
3039+
unsigned int new_order)
30143040
{
30153041
struct folio *folio = page_folio(page);
30163042
struct deferred_split *ds_queue = get_deferred_split_queue(folio);
3017-
XA_STATE(xas, &folio->mapping->i_pages, folio->index);
3043+
/* reset xarray order to new order after split */
3044+
XA_STATE_ORDER(xas, &folio->mapping->i_pages, folio->index, new_order);
30183045
struct anon_vma *anon_vma = NULL;
30193046
struct address_space *mapping = NULL;
30203047
int extra_pins, ret;
@@ -3024,6 +3051,31 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
30243051
VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio);
30253052
VM_BUG_ON_FOLIO(!folio_test_large(folio), folio);
30263053

3054+
/* Cannot split anonymous THP to order-1 */
3055+
if (new_order == 1 && folio_test_anon(folio)) {
3056+
VM_WARN_ONCE(1, "Cannot split to order-1 folio");
3057+
return -EINVAL;
3058+
}
3059+
3060+
if (new_order) {
3061+
/* Only swapping a whole PMD-mapped folio is supported */
3062+
if (folio_test_swapcache(folio))
3063+
return -EINVAL;
3064+
/* Split shmem folio to non-zero order not supported */
3065+
if (shmem_mapping(folio->mapping)) {
3066+
VM_WARN_ONCE(1,
3067+
"Cannot split shmem folio to non-0 order");
3068+
return -EINVAL;
3069+
}
3070+
/* No split if the file system does not support large folio */
3071+
if (!mapping_large_folio_support(folio->mapping)) {
3072+
VM_WARN_ONCE(1,
3073+
"Cannot split file folio to non-0 order");
3074+
return -EINVAL;
3075+
}
3076+
}
3077+
3078+
30273079
is_hzp = is_huge_zero_page(&folio->page);
30283080
if (is_hzp) {
30293081
pr_warn_ratelimited("Called split_huge_page for huge zero page\n");
@@ -3120,14 +3172,21 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
31203172
if (folio_order(folio) > 1 &&
31213173
!list_empty(&folio->_deferred_list)) {
31223174
ds_queue->split_queue_len--;
3123-
list_del(&folio->_deferred_list);
3175+
/*
3176+
* Reinitialize page_deferred_list after removing the
3177+
* page from the split_queue, otherwise a subsequent
3178+
* split will see list corruption when checking the
3179+
* page_deferred_list.
3180+
*/
3181+
list_del_init(&folio->_deferred_list);
31243182
}
31253183
spin_unlock(&ds_queue->split_queue_lock);
31263184
if (mapping) {
31273185
int nr = folio_nr_pages(folio);
31283186

31293187
xas_split(&xas, folio, folio_order(folio));
3130-
if (folio_test_pmd_mappable(folio)) {
3188+
if (folio_test_pmd_mappable(folio) &&
3189+
new_order < HPAGE_PMD_ORDER) {
31313190
if (folio_test_swapbacked(folio)) {
31323191
__lruvec_stat_mod_folio(folio,
31333192
NR_SHMEM_THPS, -nr);
@@ -3139,7 +3198,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
31393198
}
31403199
}
31413200

3142-
__split_huge_page(page, list, end);
3201+
__split_huge_page(page, list, end, new_order);
31433202
ret = 0;
31443203
} else {
31453204
spin_unlock(&ds_queue->split_queue_lock);

0 commit comments

Comments
 (0)