From: Pengfei Li <[email protected]>

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 <[email protected]>
---
 .../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


Reply via email to