From: Wang Wensheng <wangwensheng4@huawei.com> hulk inclusion category: feature bugzilla: NA ---------------------------------------- This is used to allocate 2M-sized compound page from buddy. It acts like hugetlbfs hugepage in that it will be accounted into the HugePages_Total items in /proc/meminfo. HPageTemporary is set so that the page will be retruned to buddy after its refcount reaches zero. Signed-off-by: Wang Wensheng <wangwensheng4@huawei.com> --- include/linux/hugetlb.h | 25 +++++++++++++++++++++++++ mm/hugetlb.c | 39 +++++++++++++++++++++++++++++++++++++++ mm/share_pool.c | 4 ++-- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 46785a6cd9d6..038c6343749b 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -317,6 +317,9 @@ static inline int hugetlb_insert_hugepage_pte_size(struct mm_struct *mm, unsigne struct folio *alloc_hugetlb_folio_size(int nid, unsigned long size); struct folio *alloc_hugetlb_folio_nodemask_size(unsigned long size, int nid, nodemask_t *nodemask); +struct folio *alloc_temporary_hugetlb_folio_nodemask(int nid, nodemask_t *nodemask, + gfp_t gfp_mask); +struct folio *alloc_temporary_hugetlb_folio(int nid, gfp_t gfp_mask); #else static inline struct folio *alloc_hugetlb_folio_nodemask_size(unsigned long size, int nid, nodemask_t *nodemask) @@ -328,6 +331,17 @@ static inline struct folio *alloc_hugetlb_folio_size(int nid, unsigned long size { return NULL; } + +static inline struct folio *alloc_temporary_hugetlb_folio_nodemask(int nid, + nodemask_t *nodemask, gfp_t gfp_mask) +{ + return NULL; +} + +static inline struct folio *alloc_temporary_hugetlb_folio(int nid, gfp_t gfp_mask) +{ + return NULL; +} #endif #else /* !CONFIG_HUGETLB_PAGE */ @@ -568,6 +582,17 @@ static inline struct folio *alloc_hugetlb_folio_size(int nid, unsigned long size return NULL; } +static inline struct folio *alloc_temporary_hugetlb_folio_nodemask(int nid, + nodemask_t *nodemask, gfp_t gfp_mask) +{ + return NULL; +} + +static inline struct folio *alloc_temporary_hugetlb_folio(int nid, gfp_t gfp_mask) +{ + return NULL; +} + static inline void hugetlb_split(struct vm_area_struct *vma, unsigned long addr) {} #endif /* !CONFIG_HUGETLB_PAGE */ diff --git a/mm/hugetlb.c b/mm/hugetlb.c index a1e096e48e83..f782af1c8ce8 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -8444,4 +8444,43 @@ struct folio *alloc_hugetlb_folio_size(int nid, unsigned long size) return alloc_hugetlb_folio_nodemask_size(size, nid, &nodemask); } EXPORT_SYMBOL(alloc_hugetlb_folio_size); + +struct folio *alloc_temporary_hugetlb_folio_nodemask(int nid, nodemask_t *nodemask, + gfp_t gfp_mask) +{ + struct hstate *h; + struct folio *folio; + + h = size_to_hstate(PMD_SIZE); + if (!h) + return NULL; + + folio = only_alloc_fresh_hugetlb_folio(h, gfp_mask, nid, nodemask, NULL); + if (!folio) + return NULL; + + spin_lock_irq(&hugetlb_lock); + __prep_account_new_huge_page(h, folio_nid(folio)); + spin_unlock_irq(&hugetlb_lock); + + folio_ref_unfreeze(folio, 1); + /* + * We do not account these pages as surplus because they are only + * temporary and will be released properly on the last reference + */ + folio_set_hugetlb_temporary(folio); + + return folio; +} + +struct folio *alloc_temporary_hugetlb_folio(int nid, gfp_t gfp_mask) +{ + nodemask_t nodemask; + + nodes_clear(nodemask); + node_set(nid, nodemask); + + return alloc_temporary_hugetlb_folio_nodemask(nid, &nodemask, gfp_mask); +} +EXPORT_SYMBOL(alloc_temporary_hugetlb_folio); #endif diff --git a/mm/share_pool.c b/mm/share_pool.c index fb662732f671..58aede9b3325 100644 --- a/mm/share_pool.c +++ b/mm/share_pool.c @@ -1529,8 +1529,8 @@ static bool sp_area_alloc_hugepages(struct sp_area *spa, int nid, nodemask_t *no pages[i] = (struct page *)alloc_hugetlb_folio_nodemask_size(PMD_SIZE, nid, nodemask); if (!pages[i]) - pages[i] = __alloc_pages(GFP_HIGHUSER_MOVABLE | __GFP_COMP | __GFP_ACCOUNT, - get_order(PMD_SIZE), nid, nodemask); + pages[i] = (struct page *)alloc_temporary_hugetlb_folio_nodemask(nid, + nodemask, GFP_HIGHUSER_MOVABLE | __GFP_COMP | __GFP_ACCOUNT); if (!pages[i]) { while (i--) put_page(pages[i]); -- 2.43.0