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
