Thread (15 messages) flat view 15 messages, 2 authors, 4d ago
COOLING4d

[RFC PATCH v7 05/10] trace: make the stackmap capacity settable on the kernel command line

From: Li Pengfei <hidden>
Date: 2026-09-12 08:39:27
Also in: linux-doc, linux-kselftest, lkml
Subsystem: documentation, the rest, tracing · Maintainers: Jonathan Corbet, Linus Torvalds, Steven Rostedt, Masami Hiramatsu

From: Pengfei Li <redacted>

Add ftrace_stackmap.bits=N to size the map at boot, replacing the fixed
capacity the map was created with so far.

N is clamped to [10, 18], and the value is clamped again at create time
so a bogus setting cannot get through even if early_param is bypassed.
The upper bound keeps the worst case bounded: bits=18 means 256K
elements, 512K table slots and a ~130 MB element pool. The default stays
at 14, which gives 16K elements and a ~8 MB pool.

Signed-off-by: Pengfei Li <redacted>
---
 .../admin-guide/kernel-parameters.txt         |  7 ++++
 kernel/trace/Kconfig                          |  4 +++
 kernel/trace/trace_stackmap.c                 | 36 +++++++++++++++----
 3 files changed, 41 insertions(+), 6 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index b5493a7f8f22..9ca271e21bf0 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1794,6 +1794,13 @@ Kernel parameters
 			can be changed at run time by the max_graph_depth file
 			in the tracefs tracing directory. default: 0 (no limit)
 
+	ftrace_stackmap.bits=
+			[FTRACE] Set the stackmap capacity to 2^N records.
+			Format: <int>
+			default: 14; values are clamped to the range 10-18.
+			The upper bound reserves roughly 130 MB for the element
+			pool. See Documentation/trace/ftrace-stackmap.rst.
+
 	fw_devlink=	[KNL,EARLY] Create device links between consumer and supplier
 			devices by scanning the firmware to infer the
 			consumer/supplier relationships. This feature is
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 7001453bbfd3..b2cde74d803b 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -435,6 +435,10 @@ config FTRACE_STACKMAP
 	  deduplicated when stackmap is enabled for their trace array. Stackmap
 	  is currently available only for the global trace array.
 
+	  Map capacity defaults to 2^14 records and can be changed with the
+	  ftrace_stackmap.bits= boot parameter. Values are clamped to 10-18;
+	  the upper bound reserves roughly 130 MB for the element pool.
+
 	  The deduplicated stacks are exported via:
 	    /sys/kernel/debug/tracing/stack_map
 
diff --git a/kernel/trace/trace_stackmap.c b/kernel/trace/trace_stackmap.c
index 439d3be9e351..49ea403822ba 100644
--- a/kernel/trace/trace_stackmap.c
+++ b/kernel/trace/trace_stackmap.c
@@ -150,12 +150,31 @@ struct ftrace_stackmap {
 };
 
 /*
- * Map capacity: 2^FTRACE_STACKMAP_BITS stack records, with the hash
- * table over-provisioned 2x on top of that. This gives 16K elements
- * and a ~8 MB element pool, sized for the repetitive-stack workloads
- * the map targets.
+ * Map capacity: 2^bits stack records, with the hash table
+ * over-provisioned 2x on top of that. The range is capped to keep
+ * worst-case allocations bounded:
+ *   bits=18 -> 256K elts, 512K slots, ~130 MB elt pool, and a
+ *              stack_map_bin reader walking that many entries.
+ * The default of 14 gives 16K elts and a ~8 MB pool, which suits the
+ * repetitive-stack workloads the map targets; raise it through
+ * ftrace_stackmap.bits= for a higher stack-record capacity.
  */
-#define FTRACE_STACKMAP_BITS		14
+#define FTRACE_STACKMAP_BITS_MIN	10
+#define FTRACE_STACKMAP_BITS_MAX	18
+#define FTRACE_STACKMAP_BITS_DEFAULT	14
+
+static unsigned int stackmap_map_bits = FTRACE_STACKMAP_BITS_DEFAULT;
+static int __init stackmap_bits_setup(char *str)
+{
+	unsigned long val;
+
+	if (kstrtoul(str, 0, &val))
+		return -EINVAL;
+	val = clamp_val(val, FTRACE_STACKMAP_BITS_MIN, FTRACE_STACKMAP_BITS_MAX);
+	stackmap_map_bits = val;
+	return 0;
+}
+early_param("ftrace_stackmap.bits", stackmap_bits_setup);
 
 /* --- Element pool --- */
 
@@ -182,12 +201,17 @@ static struct stackmap_elt *stackmap_get_elt(struct ftrace_stackmap *smap)
 struct ftrace_stackmap *ftrace_stackmap_create(struct trace_array *tr)
 {
 	struct ftrace_stackmap *smap;
-	unsigned int bits = FTRACE_STACKMAP_BITS;
+	unsigned int bits;
 
 	smap = kzalloc_obj(*smap, GFP_KERNEL);
 	if (!smap)
 		return ERR_PTR(-ENOMEM);
 
+	/* Defensive clamp even if the early parameter path is bypassed. */
+	bits = clamp_val(stackmap_map_bits,
+			 FTRACE_STACKMAP_BITS_MIN,
+			 FTRACE_STACKMAP_BITS_MAX);
+
 	smap->tr = tr;
 	smap->map_bits = bits;
 	smap->max_elts = 1U << bits;
-- 
2.34.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help