From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
To: Pengfei Li <ljdlns1987@gmail.com>
Cc: Steven Rostedt <rostedt@goodmis.org>,
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
Mark Rutland <mark.rutland@arm.com>,
Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
kernel test robot <lkp@intel.com>,
Bo Zhang <zhangbo56@xiaomi.com>,
Pengfei Li <lipengfei28@xiaomi.com>,
linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org,
linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org
Subject: Re: [RFC PATCH v6 1/3] trace: add lock-free stackmap for stack trace deduplication
Date: Tue, 8 Sep 2026 10:21:40 +0900 [thread overview]
Message-ID: <20260908102140.2ed161f1c851d94e1365520d@kernel.org> (raw)
In-Reply-To: <20260903132409.270195-2-lipengfei28@xiaomi.com>
On Thu, 3 Sep 2026 21:24:07 +0800
Pengfei Li <ljdlns1987@gmail.com> wrote:
> Add a lock-free hash map (ftrace_stackmap) that deduplicates kernel
> stack traces for the ftrace ring buffer. Instead of storing full
> stack traces (80-160 bytes each) in the ring buffer for every event,
> ftrace can store a 4-byte stack_id when the stackmap option is enabled.
Thanks, I have some comments below.
[...]
>
> Kernel command line parameter:
> - ftrace_stackmap.bits=N: set map capacity (2^N unique stacks,
> range 10-18, default 14)
Ah, this kernel cmdline parameter is also be a separated patch,
because this is not fundamentary needed.
>
> Signed-off-by: Pengfei Li <lipengfei28@xiaomi.com>
It is OK to use an official address for SoB, but to make sure this
address work, please at least Cc to this address.
> ---
> kernel/trace/Kconfig | 22 +
> kernel/trace/Makefile | 1 +
> kernel/trace/trace_stackmap.c | 871 ++++++++++++++++++++++++++++++++++
> kernel/trace/trace_stackmap.h | 55 +++
> 4 files changed, 949 insertions(+)
> create mode 100644 kernel/trace/trace_stackmap.c
> create mode 100644 kernel/trace/trace_stackmap.h
[...]
> +/* --- Stats --- */
> +
> +static int stackmap_stat_show(struct seq_file *m, void *v)
> +{
> + struct ftrace_stackmap *smap = m->private;
> + u64 successes = 0, drops = 0;
> + u32 entries;
> + int cpu;
> +
> + if (!smap) {
> + seq_puts(m, "stackmap not initialized\n");
> + return 0;
> + }
> +
You also need down_read(&smap->reader_sem) here for serializing.
> + entries = atomic_read(&smap->next_elt);
> + for_each_possible_cpu(cpu) {
> + successes += local_read(per_cpu_ptr(smap->successes, cpu));
> + drops += local_read(per_cpu_ptr(smap->drops, cpu));
> + }
> +
> + seq_printf(m, "entries: %u / %u\n", entries, smap->max_elts);
> + seq_printf(m, "table_size: %u\n", smap->map_size);
> + seq_printf(m, "successes: %llu\n", successes);
> + seq_printf(m, "drops: %llu\n", drops);
> + if (successes + drops > 0) {
> + /*
> + * mul_u64_u64_div_u64() uses a 128-bit intermediate, so
> + * (successes * 100) cannot overflow even when successes
> + * approaches U64_MAX on a very long trace.
> + */
> + successes = mul_u64_u64_div_u64(successes, 100, successes + drops);
> + } else {
> + successes = 0;
> + }
> + seq_printf(m, "success_rate: %llu%%\n", successes);
and up_read(&smap->reader_sem) too.
> + return 0;
> +}
> +
> +static int stackmap_stat_open(struct inode *inode, struct file *file)
> +{
> + return single_open(file, stackmap_stat_show, inode->i_private);
> +}
> +
> +const struct file_operations ftrace_stackmap_stat_fops = {
> + .open = stackmap_stat_open,
> + .read = seq_read,
> + .llseek = seq_lseek,
> + .release = single_release,
> +};
> +
> +/* --- Binary export --- */
> +
> +struct stackmap_bin_snapshot {
> + /*
> + * Use u64 (not size_t) so data[] is 8-byte aligned on both
> + * 32-bit and 64-bit architectures. The IP array within data[]
> + * is accessed as u64*, which would alignment-fault on strict
> + * architectures (e.g. older ARM, SPARC) if data[] started at
> + * a 4-byte boundary.
> + */
> + u64 size;
> + char data[];
> +};
> +
> +static int stackmap_bin_open(struct inode *inode, struct file *file)
> +{
> + struct ftrace_stackmap *smap = inode->i_private;
> + struct stackmap_bin_snapshot *snap;
> + struct ftrace_stackmap_bin_header *hdr;
> + struct ftrace_stackmap_bin_entry *e;
> + size_t alloc_size, off;
> + u32 nr_entries, i, nr_stacks;
> +
> + if (!smap)
> + return -ENODEV;
> +
> + /*
> + * Serialize opens: only one snapshot may be pinned at a time
> + * (see @bin_open). Released in stackmap_bin_release().
> + */
> + if (atomic_cmpxchg(&smap->bin_open, 0, 1) != 0)
> + return -EBUSY;
> +
> + /*
> + * Worst-case allocation size: every populated entry uses a
> + * full-depth stack. The (+1) gives one slack slot in case a
> + * concurrent insert lands between this snapshot and iteration.
> + * The loop below performs an explicit bounds check anyway.
> + *
> + * At bits=18 this caps at ~135 MB. The file is mode 0440
> + * (TRACE_MODE_READ), so only privileged users can open it.
Hmm, this is too huge to make a copy inside the kernel.
If the stackmap is only increasing, and can avoid resetting by
reader_sem, what about rewriting this as a raw-output mode of
seq_file?
You can use seq_write() to seq_file buffer.
Thank you,
--
Masami Hiramatsu (Google) <mhiramat@kernel.org>
next prev parent reply other threads:[~2026-09-08 1:21 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 13:24 [RFC PATCH v6 0/3] trace: stack trace deduplication for ftrace ring buffer Pengfei Li
2026-09-03 13:24 ` [RFC PATCH v6 1/3] trace: add lock-free stackmap for stack trace deduplication Pengfei Li
2026-09-08 1:21 ` Masami Hiramatsu [this message]
2026-09-08 3:06 ` Pengfei Li
2026-09-03 13:24 ` [RFC PATCH v6 2/3] trace: integrate stackmap into ftrace stack recording path Pengfei Li
2026-09-03 13:24 ` [RFC PATCH v6 3/3] trace: add documentation, selftest and tooling for stackmap Pengfei Li
2026-09-08 1:35 ` Masami Hiramatsu
2026-09-08 3:09 ` Pengfei Li
2026-09-08 1:15 ` [RFC PATCH v6 0/3] trace: stack trace deduplication for ftrace ring buffer Masami Hiramatsu
2026-09-08 2:55 ` Pengfei Li
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260908102140.2ed161f1c851d94e1365520d@kernel.org \
--to=mhiramat@kernel.org \
--cc=corbet@lwn.net \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=lipengfei28@xiaomi.com \
--cc=ljdlns1987@gmail.com \
--cc=lkp@intel.com \
--cc=mark.rutland@arm.com \
--cc=mathieu.desnoyers@efficios.com \
--cc=rostedt@goodmis.org \
--cc=skhan@linuxfoundation.org \
--cc=zhangbo56@xiaomi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox