Skip to content

Commit cb402bb

Browse files
tujinjiang11akpm00
authored andcommitted
mm/hugetlb: fix surplus pages in dissolve_free_huge_page()
In dissolve_free_huge_page(), free huge pages are dissolved without adjusting surplus count. However, free huge pages may be accounted as surplus pages, and will lead to wrong surplus count. I reproduce this issue on qemu. The steps are: 1) Node1 is memory-less at first. Hot-add memory to node1 by executing the two commands in qemu monitor: object_add memory-backend-ram,id=mem1,size=1G device_add pc-dimm,id=dimm1,memdev=mem1,node=1 2) online one memory block of Node1 with: echo online_movable > /sys/devices/system/node/node1/memoryX/state 3) create 64 huge pages for node1 4) run a program to reserve (don't consume) all the huge pages 5) echo 0 > nr_huge_pages for node1. After this step, free huge pages in Node1 are surplus. 6) create 80 huge pages for node0 7) offline memory of node1, The memory range to offline contains the free surplus huge pages created in step3) ~ step5) echo offline > /sys/devices/system/node/node1/memoryX/state 8) kill the program in step 4) The result: Node0 Node1 total 80 0 free 80 0 surplus 0 61 To fix it, adjust surplus when destroying huge pages if the node has surplus pages in dissolve_free_hugetlb_folio(). The result with this patch: Node0 Node1 total 80 0 free 80 0 surplus 0 0 Link: https://lkml.kernel.org/r/20250304132106.2872754-1-tujinjiang@huawei.com Fixes: c8721bb ("mm: memory-hotplug: enable memory hotplug to handle hugepage") Signed-off-by: Jinjiang Tu <tujinjiang@huawei.com> Acked-by: David Hildenbrand <david@redhat.com> Acked-by: Oscar Salvador <osalvador@suse.de> Cc: Jinjiang Tu <tujinjiang@huawei.com> Cc: Kefeng Wang <wangkefeng.wang@huawei.com> Cc: Muchun Song <muchun.song@linux.dev> Cc: Nanyong Sun <sunnanyong@huawei.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent 73d7a69 commit cb402bb

File tree

1 file changed

+6
-2
lines changed

1 file changed

+6
-2
lines changed

mm/hugetlb.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2135,6 +2135,8 @@ int dissolve_free_hugetlb_folio(struct folio *folio)
21352135

21362136
if (!folio_ref_count(folio)) {
21372137
struct hstate *h = folio_hstate(folio);
2138+
bool adjust_surplus = false;
2139+
21382140
if (!available_huge_pages(h))
21392141
goto out;
21402142

@@ -2157,7 +2159,9 @@ int dissolve_free_hugetlb_folio(struct folio *folio)
21572159
goto retry;
21582160
}
21592161

2160-
remove_hugetlb_folio(h, folio, false);
2162+
if (h->surplus_huge_pages_node[folio_nid(folio)])
2163+
adjust_surplus = true;
2164+
remove_hugetlb_folio(h, folio, adjust_surplus);
21612165
h->max_huge_pages--;
21622166
spin_unlock_irq(&hugetlb_lock);
21632167

@@ -2177,7 +2181,7 @@ int dissolve_free_hugetlb_folio(struct folio *folio)
21772181
rc = hugetlb_vmemmap_restore_folio(h, folio);
21782182
if (rc) {
21792183
spin_lock_irq(&hugetlb_lock);
2180-
add_hugetlb_folio(h, folio, false);
2184+
add_hugetlb_folio(h, folio, adjust_surplus);
21812185
h->max_huge_pages++;
21822186
goto out;
21832187
}

0 commit comments

Comments
 (0)