All of lore.kernel.org
 help / color / mirror / Atom feed
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>

  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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.