diff mbox series

[v2,26/28] mm/hugetlb: add hugetlb_cma_only cmdline option

Message ID 20250129224157.2046079-27-fvdl@google.com (mailing list archive)
State New
Headers show
Series hugetlb/CMA improvements for large systems | expand

Commit Message

Frank van der Linden Jan. 29, 2025, 10:41 p.m. UTC
Add an option to force hugetlb gigantic pages to be allocated using
CMA only (if hugetlb_cma is enabled). This avoids a fallback to
allocation from the rest of system memory if the CMA allocation
fails. This makes the size of hugetlb_cma a hard upper boundary
for gigantic hugetlb page allocations.

This is useful because, with a large CMA area, the kernel's
unmovable allocations will have less room to work with and it
is undesirable for new hugetlb gigantic page allocations
to be done from that remaining area. It will eat in to the space
available for unmovable allocations, leading to unwanted system
behavior (OOMs because the kernel fails to do unmovable allocations).

So, with this enabled, an administrator can force a hard upper
bound for runtime gigantic page allocations, and have more
predictable system behavior.

Signed-off-by: Frank van der Linden <fvdl@google.com>
---
 Documentation/admin-guide/kernel-parameters.txt |  7 +++++++
 mm/hugetlb.c                                    | 14 ++++++++++++++
 2 files changed, 21 insertions(+)
diff mbox series

Patch

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index fb8752b42ec8..eb56b251ce10 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1892,6 +1892,13 @@ 
 			hugepages using the CMA allocator. If enabled, the
 			boot-time allocation of gigantic hugepages is skipped.
 
+	hugetlb_cma_only=
+			[HW,CMA,EARLY] When allocating new HugeTLB pages, only
+			try to allocate from the CMA areas.
+
+			This option does nothing if hugetlb_cma= is not also
+			specified.
+
 	hugetlb_free_vmemmap=
 			[KNL] Requires CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP
 			enabled.
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 5af544960052..c227d0b9cf1e 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -60,6 +60,7 @@  struct hstate hstates[HUGE_MAX_HSTATE];
 static struct cma *hugetlb_cma[MAX_NUMNODES];
 static unsigned long hugetlb_cma_size_in_node[MAX_NUMNODES] __initdata;
 #endif
+static bool hugetlb_cma_only;
 static unsigned long hugetlb_cma_size __initdata;
 
 __initdata struct list_head huge_boot_pages[MAX_NUMNODES];
@@ -1511,6 +1512,9 @@  static struct folio *alloc_gigantic_folio(struct hstate *h, gfp_t gfp_mask,
 	}
 #endif
 	if (!folio) {
+		if (hugetlb_cma_only)
+			return NULL;
+
 		folio = folio_alloc_gigantic(order, gfp_mask, nid, nodemask);
 		if (!folio)
 			return NULL;
@@ -4732,6 +4736,9 @@  static __init void hugetlb_parse_params(void)
 
 		hcp->setup(hcp->val);
 	}
+
+	if (!hugetlb_cma_size)
+		hugetlb_cma_only = false;
 }
 
 /*
@@ -7844,6 +7851,13 @@  static int __init cmdline_parse_hugetlb_cma(char *p)
 
 early_param("hugetlb_cma", cmdline_parse_hugetlb_cma);
 
+static int __init cmdline_parse_hugetlb_cma_only(char *p)
+{
+	return kstrtobool(p, &hugetlb_cma_only);
+}
+
+early_param("hugetlb_cma_only", cmdline_parse_hugetlb_cma_only);
+
 void __init hugetlb_cma_reserve(int order)
 {
 	unsigned long size, reserved, per_node;