From: Liu Shixin liushixin2@huawei.com
hulk inclusion category: feature bugzilla: 46904, https://gitee.com/openeuler/kernel/issues/I6BDME CVE: NA
--------------------------------
The memory hotplug and memory failure will dissolve freed hugepages to buddy system, this is not the expected behavior for dynamic hugetlb. Skip the dissolve operation for hugepages belonging to dynamic hugetlb. For memory hotplug, the hotplug operation is not allowed, if dhugetlb pool existed. For memory failure, the hugepage will be discard directly.
Signed-off-by: Liu Shixin liushixin2@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com --- include/linux/hugetlb.h | 5 +++++ mm/hugetlb.c | 14 +++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 92fd6e2cbaf3..a26cbc4398a4 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -751,6 +751,11 @@ static inline struct dhugetlb_pool *get_dhugetlb_pool_from_task( { return NULL; } +static inline struct dhugetlb_pool *get_dhugetlb_pool_from_dhugetlb_pagelist( + struct page *page) +{ + return NULL; +} static inline void dhugetlb_pool_put(struct dhugetlb_pool *hpool) { return; } #endif /* CONFIG_DYNAMIC_HUGETLB */
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 8b88ac4620d5..625882b7cd97 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1769,12 +1769,20 @@ static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed, int dissolve_free_huge_page(struct page *page) { int rc = -EBUSY; + struct dhugetlb_pool *hpool;
retry: /* Not to disrupt normal path by vainly holding hugetlb_lock */ if (!PageHuge(page)) return 0;
+ /* Skip dissolve hugepage for dynamic hugetlb */ + hpool = get_dhugetlb_pool_from_dhugetlb_pagelist(page); + if (hpool) { + dhugetlb_pool_put(hpool); + return -EBUSY; + } + spin_lock(&hugetlb_lock); if (!PageHuge(page)) { rc = 0; @@ -3426,8 +3434,12 @@ struct dhugetlb_pool *get_dhugetlb_pool_from_dhugetlb_pagelist( struct page *page) { struct dhugetlb_pool *hpool = NULL; - unsigned long idx = page_to_pfn(page) >> (PUD_SHIFT - PAGE_SHIFT); + unsigned long idx; + + if (!dhugetlb_enabled) + return NULL;
+ idx = page_to_pfn(page) >> (PUD_SHIFT - PAGE_SHIFT); read_lock(&dhugetlb_pagelist_rwlock); if (idx < dhugetlb_pagelist_t->count) hpool = dhugetlb_pagelist_t->hpool[idx];