From 7877471860f5fc7966bfc4e44c16ff53ef772520 Mon Sep 17 00:00:00 2001
From: Liu Shixin <liushixin2@huawei.com>
Date: Sun, 20 Mar 2022 10:48:22 +0800
Subject: [PATCH] mm/dynamic_hugetlb: initialize subpages before merging

hulk inclusion
category: bugfix
bugzilla: 46904 https://gitee.com/openeuler/kernel/issues/I4Y0XO

--------------------------------

Patch ("hugetlb: address ref count racing in prep_compound_gigantic_page") add
a check of ref count in prep_compound_gigantic_page. We will call this function
in dynamic hugetlb feature too, so we should initialize subpages before calling
prep_compound_gigantic_page to satisfy the change.
Further, the input of prep_compound_gigantic_page should be a group of pages
rather than compound page, so clear the properties related to compound page.

Signed-off-by: Liu Shixin <liushixin2@huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
---
 mm/dynamic_hugetlb.c | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/mm/dynamic_hugetlb.c b/mm/dynamic_hugetlb.c
index 7dc1d7643a35..eb9b528b73de 100644
--- a/mm/dynamic_hugetlb.c
+++ b/mm/dynamic_hugetlb.c
@@ -210,7 +210,7 @@ static int hpool_merge_page(struct dhugetlb_pool *hpool, int hpages_pool_idx, bo
 	struct split_hugepage *split_page, *split_next;
 	unsigned long nr_pages, block_size;
 	struct page *page, *next, *p;
-	bool need_migrate = false;
+	bool need_migrate = false, need_initial = false;
 	int i, try;
 	LIST_HEAD(wait_page_list);
 
@@ -221,8 +221,9 @@ static int hpool_merge_page(struct dhugetlb_pool *hpool, int hpages_pool_idx, bo
 
 	switch (hpages_pool_idx) {
 		case HUGE_PAGES_POOL_1G:
-			nr_pages = 1 << (PUD_SHIFT - PMD_SHIFT);
+			nr_pages = 1 << (PUD_SHIFT - PAGE_SHIFT);
 			block_size = 1 << (PMD_SHIFT - PAGE_SHIFT);
+			need_initial = true;
 			break;
 		case HUGE_PAGES_POOL_2M:
 			nr_pages = 1 << (PMD_SHIFT - PAGE_SHIFT);
@@ -258,6 +259,25 @@ static int hpool_merge_page(struct dhugetlb_pool *hpool, int hpages_pool_idx, bo
 			p = pfn_to_page(split_page->start_pfn + i);
 			list_del(&p->lru);
 			src_hpages_pool->free_normal_pages--;
+			/*
+			 * The input of prep_compound_gigantic_page should be a
+			 * group of pages whose ref count is 1 rather than
+			 * compound_page.
+			 * Initialize the pages before merge them to 1G.
+			 */
+			if (need_initial) {
+				int j;
+
+				set_compound_page_dtor(p, NULL_COMPOUND_DTOR);
+				atomic_set(compound_mapcount_ptr(p), 0);
+				set_compound_order(p, 0);
+				__ClearPageHead(p);
+				set_page_count(p, 1);
+				for (j = 1; j < block_size; j++) {
+					clear_compound_head(&p[j]);
+					set_page_count(&p[j], 1);
+				}
+			}
 		}
 		kfree(split_page);
 		add_new_page_to_pool(hpool, page, hpages_pool_idx);
-- 
GitLab