Move the accounting from the constructor to the allocation site. Some of the architecture code is a little complex to reason about, but I think this is all correct (and slightly more efficient due to having 'order' as an argument instead of having to retrieve it from struct page again). Signed-off-by: Matthew Wilcox (Oracle) --- include/linux/mm.h | 11 ----------- mm/memory.c | 11 ++++++++++- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index ec9365375d9c..ade37df5ea2b 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -3044,26 +3044,15 @@ static inline bool ptlock_init(struct ptdesc *ptdesc) { return true; } static inline void ptlock_free(struct ptdesc *ptdesc) {} #endif /* defined(CONFIG_SPLIT_PTE_PTLOCKS) */ -static inline unsigned long ptdesc_nr_pages(const struct ptdesc *ptdesc) -{ - return compound_nr(ptdesc_page(ptdesc)); -} - static inline void __pagetable_ctor(struct ptdesc *ptdesc) { - pg_data_t *pgdat = NODE_DATA(memdesc_nid(ptdesc->pt_flags)); - __SetPageTable(ptdesc_page(ptdesc)); - mod_node_page_state(pgdat, NR_PAGETABLE, ptdesc_nr_pages(ptdesc)); } static inline void pagetable_dtor(struct ptdesc *ptdesc) { - pg_data_t *pgdat = NODE_DATA(memdesc_nid(ptdesc->pt_flags)); - ptlock_free(ptdesc); __ClearPageTable(ptdesc_page(ptdesc)); - mod_node_page_state(pgdat, NR_PAGETABLE, -ptdesc_nr_pages(ptdesc)); } static inline void pagetable_dtor_free(struct ptdesc *ptdesc) diff --git a/mm/memory.c b/mm/memory.c index de9f999ffcf6..033fc4e29232 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -7280,7 +7280,13 @@ long copy_folio_from_user(struct folio *dst_folio, struct ptdesc *pagetable_alloc_noprof(gfp_t gfp, unsigned int order) { struct page *page = alloc_frozen_pages_noprof(gfp | __GFP_COMP, order); + pg_data_t *pgdat; + if (!page) + return NULL; + + pgdat = NODE_DATA(page_to_nid(page)); + mod_node_page_state(pgdat, NR_PAGETABLE, 1 << order); return page_ptdesc(page); } @@ -7293,9 +7299,12 @@ struct ptdesc *pagetable_alloc_noprof(gfp_t gfp, unsigned int order) */ void pagetable_free(struct ptdesc *pt) { + pg_data_t *pgdat = NODE_DATA(memdesc_nid(pt->pt_flags)); struct page *page = ptdesc_page(pt); + unsigned int order = compound_order(page); - free_frozen_pages(page, compound_order(page)); + mod_node_page_state(pgdat, NR_PAGETABLE, -(1L << order)); + free_frozen_pages(page, order); } #if defined(CONFIG_SPLIT_PTE_PTLOCKS) && ALLOC_SPLIT_PTLOCKS -- 2.47.2