Use ptdesc->pt_list instead of page->lru. These are the same bits for now, but will be different when ptdesc is allocated separately. Signed-off-by: Matthew Wilcox (Oracle) --- include/linux/mm_types.h | 1 + mm/pgtable-generic.c | 24 +++++++++++++++--------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index a0f4bd6099cc..5e08c4a41777 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -602,6 +602,7 @@ struct ptdesc { TABLE_MATCH(flags, pt_flags); TABLE_MATCH(compound_head, pt_list); TABLE_MATCH(compound_head, _pt_pad_1); +TABLE_MATCH(lru, pt_list); TABLE_MATCH(mapping, __page_mapping); TABLE_MATCH(__folio_index, pt_index); TABLE_MATCH(rcu_head, pt_rcu_head); diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c index 597049e21ac1..a3990c04b31e 100644 --- a/mm/pgtable-generic.c +++ b/mm/pgtable-generic.c @@ -166,13 +166,14 @@ pud_t pudp_huge_clear_flush(struct vm_area_struct *vma, unsigned long address, void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp, pgtable_t pgtable) { + struct ptdesc *ptdesc = page_ptdesc(pgtable); assert_spin_locked(pmd_lockptr(mm, pmdp)); /* FIFO */ if (!pmd_huge_pte(mm, pmdp)) - INIT_LIST_HEAD(&pgtable->lru); + INIT_LIST_HEAD(&ptdesc->pt_list); else - list_add(&pgtable->lru, &pmd_huge_pte(mm, pmdp)->lru); + list_add(&ptdesc->pt_list, &page_ptdesc(pmd_huge_pte(mm, pmdp))->pt_list); pmd_huge_pte(mm, pmdp) = pgtable; } #endif @@ -181,17 +182,22 @@ void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp, /* no "address" argument so destroys page coloring of some arch */ pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp) { - pgtable_t pgtable; + struct ptdesc *ptdesc, *next; + struct page *page; assert_spin_locked(pmd_lockptr(mm, pmdp)); /* FIFO */ - pgtable = pmd_huge_pte(mm, pmdp); - pmd_huge_pte(mm, pmdp) = list_first_entry_or_null(&pgtable->lru, - struct page, lru); - if (pmd_huge_pte(mm, pmdp)) - list_del(&pgtable->lru); - return pgtable; + page = pmd_huge_pte(mm, pmdp); + ptdesc = page_ptdesc(page); + next = list_first_entry_or_null(&ptdesc->pt_list, struct ptdesc, pt_list); + if (next) { + pmd_huge_pte(mm, pmdp) = ptdesc_page(next); + list_del(&ptdesc->pt_list); + } else { + pmd_huge_pte(mm, pmdp) = NULL; + } + return page; } #endif -- 2.47.2