From nobody Mon Feb 9 04:09:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A9B897260A; Tue, 20 Jan 2026 01:09:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768871370; cv=none; b=MvivOlyecY7+HqFD4/r2mcNhf6E7bv7xDt0bcid4rSeQhXYIlUY5Xfu0PeIuFOAoKaIUn3VO7pLy+ayGByesayVDFkrLir14hNUng04EpWaSWmzpTsN7OUuqfSFWoucoL/lcMVr++eQzwTdhDJ69ctQ54oKGcCUg9QZCsm/Eul0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768871370; c=relaxed/simple; bh=Cf2mbEmWcovYW5tS3zoShNkU5qDl/ggFL8Kh+ngWJ18=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=oXksGnRRWmUsMh9PKYQ2h+0fmHmoi2RR245Ib1vZI4pB+z9E9Up4gpYpl0/K8OMBAtVSuvVB7g3EMZqsiL7VliiEenWpDhmF2/LYBwgttKM6GAGQPc2a/PlhaKxH3OHpYbK24RVb+MeaJXXIsuzbvqXDNyDugJi5q5zXKSm5UuM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=a4W9mAZQ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="a4W9mAZQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8FE55C116C6; Tue, 20 Jan 2026 01:09:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768871370; bh=Cf2mbEmWcovYW5tS3zoShNkU5qDl/ggFL8Kh+ngWJ18=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=a4W9mAZQWSo4dOPW9Jd1lJpCeB9jFuaeg0wIykKSAhtvqVTx4RW9vWTWYmsKcvlnK AFyHCQnqd+p/RkU7zsgdi9WYuk6Gts550rLdqm5u8f+Y8Ct7XgfGj/jZ3ea6RW823A elwWORb1kX0UMN8hIW+eCMHHxqme8F/LPTCvE2/xuD868aC5lTKeufVqxQHYh5xjDm jQKSBoQpRUeWlxuNoCeG4sz+XSQrtw7fMtXVGjHToIwvNZksOubnbKZosQdcTXYxw0 XDAZGJtb4/s0a31LUB3Uj6FfF+FBbTw0xKGYCOK5+t2GLXDuK2DGtrYDeyuJAFDZq+ KT6z22Dwbe/rw== From: "Masami Hiramatsu (Google)" To: Steven Rostedt Cc: Masami Hiramatsu , Mathieu Desnoyers , linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Subject: [PATCH v4 1/4] tracing: Reset last_boot_info if ring buffer is reset Date: Tue, 20 Jan 2026 10:09:28 +0900 Message-ID: <176887136789.578403.10711988283653763711.stgit@mhiramat.tok.corp.google.com> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <176887135615.578403.6988045330349053692.stgit@mhiramat.tok.corp.google.com> References: <176887135615.578403.6988045330349053692.stgit@mhiramat.tok.corp.google.com> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Masami Hiramatsu (Google) Commit 32dc0042528d ("tracing: Reset last-boot buffers when reading out all cpu buffers") resets the last_boot_info when user read out all data via trace_pipe* files. But it is not reset when user resets the buffer from other files. (e.g. write `trace` file) Reset it when the corresponding ring buffer is reset too. Fixes: 32dc0042528d ("tracing: Reset last-boot buffers when reading out all= cpu buffers") Signed-off-by: Masami Hiramatsu (Google) --- kernel/trace/trace.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 38f7a7a55c23..5ddaeced9cb3 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -4873,6 +4873,8 @@ static int tracing_single_release_tr(struct inode *in= ode, struct file *file) return single_release(inode, file); } =20 +static bool update_last_data_if_empty(struct trace_array *tr); + static int tracing_open(struct inode *inode, struct file *file) { struct trace_array *tr =3D inode->i_private; @@ -4897,6 +4899,8 @@ static int tracing_open(struct inode *inode, struct f= ile *file) tracing_reset_online_cpus(trace_buf); else tracing_reset_cpu(trace_buf, cpu); + + update_last_data_if_empty(tr); } =20 if (file->f_mode & FMODE_READ) { @@ -5963,6 +5967,7 @@ tracing_set_trace_read(struct file *filp, char __user= *ubuf, int tracer_init(struct tracer *t, struct trace_array *tr) { tracing_reset_online_cpus(&tr->array_buffer); + update_last_data_if_empty(tr); return t->init(tr); } =20 @@ -7781,6 +7786,7 @@ int tracing_set_clock(struct trace_array *tr, const c= har *clockstr) ring_buffer_set_clock(tr->max_buffer.buffer, trace_clocks[i].func); tracing_reset_online_cpus(&tr->max_buffer); #endif + update_last_data_if_empty(tr); =20 if (tr->scratch && !(tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) { struct trace_scratch *tscratch =3D tr->scratch; @@ -8018,6 +8024,7 @@ tracing_snapshot_write(struct file *filp, const char = __user *ubuf, size_t cnt, tracing_reset_online_cpus(&tr->max_buffer); else tracing_reset_cpu(&tr->max_buffer, iter->cpu_file); + update_last_data_if_empty(tr); } break; } From nobody Mon Feb 9 04:09:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6FB541DF759; Tue, 20 Jan 2026 01:09:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768871378; cv=none; b=S8gcDELs/dGDRdF5l4FE7VoYxr260zrQB27hn4ZXYdEdb5FRoaOc0AxN+H26401BINw4lPRBEq9VMFBVL2TCXgMHO5c6On/kKMiSXgH+2iiD+I2uQ4tu5nxCCM7zxTyaoZ1SVM9Z4zWhycVwRmAwifxKv0zZ5acvdE/p7TT/TJc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768871378; c=relaxed/simple; bh=02uMh0DSJHWfU5iNanMhWiCifsZ88h4j/+7JbgwiCqs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lECizu3igz+sTZ/44bz4z+2A1FxtVmGeB36RjFGiWGElp0qqlOBSG6fs6I6DYUVrlI9aH593PlZuUi/qPmFfgNQXy+nPpgRqg5OQ4z3ag8VmO7/pI5GB0Yc9KJvDkCtA60bKLn4mSlsNYIpyZKegt6/mVZUjvY4HwGRRnc71UPo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VCA0LvZj; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VCA0LvZj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4C5AEC116C6; Tue, 20 Jan 2026 01:09:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768871378; bh=02uMh0DSJHWfU5iNanMhWiCifsZ88h4j/+7JbgwiCqs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VCA0LvZjQ9Y76iGrknKtUVrgcvsCWRR7G3/mnqDFnbw6oqC+OB2mu+g+S+R2PibRw 2LfkTwt0ccB927QY/2EfspG5dmvw5833h655Q10L2KLA3K8xXveLv54dcR5ecDYe4i GaCAv/spxoVgB/GD44hI5JAbZoIl1rIlWYDKmEo4DALs3xluRJzZVNsICel+VWg9mm aXTgVCR6PRkQmSWr9TJwMjnzh5uzQm3gaMsiNzS7l0WAv4xSOOOXt6GqkAqZd04mQY OGS2uklTcmjC6mB+ZZ+3fZTmmMS8rRy840xIvF2ZaR1+P/dJyhTb3iHZ71f899u0HI SK9GaLdJQPDsQ== From: "Masami Hiramatsu (Google)" To: Steven Rostedt Cc: Masami Hiramatsu , Mathieu Desnoyers , linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Subject: [PATCH v4 2/4] tracing: Make the backup instance non-reusable Date: Tue, 20 Jan 2026 10:09:35 +0900 Message-ID: <176887137556.578403.17994205756247311821.stgit@mhiramat.tok.corp.google.com> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <176887135615.578403.6988045330349053692.stgit@mhiramat.tok.corp.google.com> References: <176887135615.578403.6988045330349053692.stgit@mhiramat.tok.corp.google.com> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Masami Hiramatsu (Google) Since there is no reason to reuse the backup instance, make it readonly (but erasable). Note that only backup instances are readonly, because other trace instances will be empty unless it is writable. Only backup instances have copy entries from the original. With this change, most of the trace control files are removed from the backup instance, including eventfs enable/filter etc. # find /sys/kernel/tracing/instances/backup/events/ | wc -l 4093 # find /sys/kernel/tracing/instances/boot_map/events/ | wc -l 9573 Signed-off-by: Masami Hiramatsu (Google) --- Changes in v4: - Make trace data erasable. (not reusable) Changes in v3: - Resuse the beginning part of event_entries for readonly files. - Remove readonly file_operations and checking readonly flag in each write operation. Changes in v2: - Use readonly file_operations to prohibit writing instead of checking flags in write() callbacks. - Remove writable files from eventfs. --- kernel/trace/trace.c | 93 ++++++++++++++++++++++++++++++---------= ---- kernel/trace/trace.h | 8 +++- kernel/trace/trace_boot.c | 5 +- kernel/trace/trace_events.c | 68 +++++++++++++++++++------------ 4 files changed, 117 insertions(+), 57 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 5ddaeced9cb3..b27e1cdeffb0 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -5034,6 +5034,11 @@ static ssize_t tracing_write_stub(struct file *filp, const char __user *ubuf, size_t count, loff_t *ppos) { + struct trace_array *tr =3D file_inode(filp)->i_private; + + if (trace_array_is_readonly(tr)) + return -EPERM; + return count; } =20 @@ -5134,6 +5139,9 @@ tracing_cpumask_write(struct file *filp, const char _= _user *ubuf, cpumask_var_t tracing_cpumask_new; int err; =20 + if (trace_array_is_readonly(tr)) + return -EPERM; + if (count =3D=3D 0 || count > KMALLOC_MAX_SIZE) return -EINVAL; =20 @@ -6418,6 +6426,9 @@ tracing_set_trace_write(struct file *filp, const char= __user *ubuf, size_t ret; int err; =20 + if (trace_array_is_readonly(tr)) + return -EPERM; + ret =3D cnt; =20 if (cnt > MAX_TRACER_SIZE) @@ -7052,6 +7063,9 @@ tracing_entries_write(struct file *filp, const char _= _user *ubuf, unsigned long val; int ret; =20 + if (trace_array_is_readonly(tr)) + return -EPERM; + ret =3D kstrtoul_from_user(ubuf, cnt, 10, &val); if (ret) return ret; @@ -7806,6 +7820,9 @@ static ssize_t tracing_clock_write(struct file *filp,= const char __user *ubuf, const char *clockstr; int ret; =20 + if (trace_array_is_readonly(tr)) + return -EPERM; + if (cnt >=3D sizeof(buf)) return -EINVAL; =20 @@ -9360,12 +9377,16 @@ static void tracing_init_tracefs_percpu(struct trace_array *tr, long cpu) { struct dentry *d_percpu =3D tracing_dentry_percpu(tr, cpu); + umode_t writable_mode =3D TRACE_MODE_WRITE; struct dentry *d_cpu; char cpu_dir[30]; /* 30 characters should be more than enough */ =20 if (!d_percpu) return; =20 + if (trace_array_is_readonly(tr)) + writable_mode =3D TRACE_MODE_READ; + snprintf(cpu_dir, 30, "cpu%ld", cpu); d_cpu =3D tracefs_create_dir(cpu_dir, d_percpu); if (!d_cpu) { @@ -9588,7 +9609,6 @@ struct dentry *trace_create_file(const char *name, return ret; } =20 - static struct dentry *trace_options_init_dentry(struct trace_array *tr) { struct dentry *d_tracer; @@ -9818,6 +9838,9 @@ rb_simple_write(struct file *filp, const char __user = *ubuf, unsigned long val; int ret; =20 + if (trace_array_is_readonly(tr)) + return -EPERM; + ret =3D kstrtoul_from_user(ubuf, cnt, 10, &val); if (ret) return ret; @@ -9924,6 +9947,9 @@ buffer_subbuf_size_write(struct file *filp, const cha= r __user *ubuf, int pages; int ret; =20 + if (trace_array_is_readonly(tr)) + return -EPERM; + ret =3D kstrtoul_from_user(ubuf, cnt, 10, &val); if (ret) return ret; @@ -10604,17 +10630,23 @@ static __init void create_trace_instances(struct = dentry *d_tracer) static void init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer) { + umode_t writable_mode =3D TRACE_MODE_WRITE; + bool readonly =3D trace_array_is_readonly(tr); int cpu; =20 + if (readonly) + writable_mode =3D TRACE_MODE_READ; + trace_create_file("available_tracers", TRACE_MODE_READ, d_tracer, - tr, &show_traces_fops); + tr, &show_traces_fops); =20 - trace_create_file("current_tracer", TRACE_MODE_WRITE, d_tracer, - tr, &set_tracer_fops); + trace_create_file("current_tracer", writable_mode, d_tracer, + tr, &set_tracer_fops); =20 - trace_create_file("tracing_cpumask", TRACE_MODE_WRITE, d_tracer, + trace_create_file("tracing_cpumask", writable_mode, d_tracer, tr, &tracing_cpumask_fops); =20 + /* Options are used for changing print-format even for readonly instance.= */ trace_create_file("trace_options", TRACE_MODE_WRITE, d_tracer, tr, &tracing_iter_fops); =20 @@ -10624,27 +10656,35 @@ init_tracer_tracefs(struct trace_array *tr, struc= t dentry *d_tracer) trace_create_file("trace_pipe", TRACE_MODE_READ, d_tracer, tr, &tracing_pipe_fops); =20 - trace_create_file("buffer_size_kb", TRACE_MODE_WRITE, d_tracer, + trace_create_file("buffer_size_kb", writable_mode, d_tracer, tr, &tracing_entries_fops); =20 trace_create_file("buffer_total_size_kb", TRACE_MODE_READ, d_tracer, tr, &tracing_total_entries_fops); =20 - trace_create_file("free_buffer", 0200, d_tracer, - tr, &tracing_free_buffer_fops); + if (!readonly) { + trace_create_file("free_buffer", 0200, d_tracer, + tr, &tracing_free_buffer_fops); =20 - trace_create_file("trace_marker", 0220, d_tracer, - tr, &tracing_mark_fops); + trace_create_file("trace_marker", 0220, d_tracer, + tr, &tracing_mark_fops); =20 - tr->trace_marker_file =3D __find_event_file(tr, "ftrace", "print"); + tr->trace_marker_file =3D __find_event_file(tr, "ftrace", "print"); =20 - trace_create_file("trace_marker_raw", 0220, d_tracer, - tr, &tracing_mark_raw_fops); + trace_create_file("trace_marker_raw", 0220, d_tracer, + tr, &tracing_mark_raw_fops); =20 - trace_create_file("trace_clock", TRACE_MODE_WRITE, d_tracer, tr, + trace_create_file("buffer_percent", TRACE_MODE_WRITE, d_tracer, + tr, &buffer_percent_fops); + + trace_create_file("syscall_user_buf_size", TRACE_MODE_WRITE, d_tracer, + tr, &tracing_syscall_buf_fops); + } + + trace_create_file("trace_clock", writable_mode, d_tracer, tr, &trace_clock_fops); =20 - trace_create_file("tracing_on", TRACE_MODE_WRITE, d_tracer, + trace_create_file("tracing_on", writable_mode, d_tracer, tr, &rb_simple_fops); =20 trace_create_file("timestamp_mode", TRACE_MODE_READ, d_tracer, tr, @@ -10652,41 +10692,38 @@ init_tracer_tracefs(struct trace_array *tr, struc= t dentry *d_tracer) =20 tr->buffer_percent =3D 50; =20 - trace_create_file("buffer_percent", TRACE_MODE_WRITE, d_tracer, - tr, &buffer_percent_fops); - - trace_create_file("buffer_subbuf_size_kb", TRACE_MODE_WRITE, d_tracer, + trace_create_file("buffer_subbuf_size_kb", writable_mode, d_tracer, tr, &buffer_subbuf_size_fops); =20 - trace_create_file("syscall_user_buf_size", TRACE_MODE_WRITE, d_tracer, - tr, &tracing_syscall_buf_fops); - create_trace_options_dir(tr); =20 #ifdef CONFIG_TRACER_MAX_TRACE - trace_create_maxlat_file(tr, d_tracer); + if (!readonly) + trace_create_maxlat_file(tr, d_tracer); #endif =20 - if (ftrace_create_function_files(tr, d_tracer)) + if (!readonly && ftrace_create_function_files(tr, d_tracer)) MEM_FAIL(1, "Could not allocate function filter files"); =20 if (tr->range_addr_start) { trace_create_file("last_boot_info", TRACE_MODE_READ, d_tracer, tr, &last_boot_fops); #ifdef CONFIG_TRACER_SNAPSHOT - } else { + } else if (!readonly) { trace_create_file("snapshot", TRACE_MODE_WRITE, d_tracer, tr, &snapshot_fops); #endif } =20 - trace_create_file("error_log", TRACE_MODE_WRITE, d_tracer, - tr, &tracing_err_log_fops); + if (!readonly) + trace_create_file("error_log", TRACE_MODE_WRITE, d_tracer, + tr, &tracing_err_log_fops); =20 for_each_tracing_cpu(cpu) tracing_init_tracefs_percpu(tr, cpu); =20 - ftrace_init_tracefs(tr, d_tracer); + if (!readonly) + ftrace_init_tracefs(tr, d_tracer); } =20 #ifdef CONFIG_TRACEFS_AUTOMOUNT_DEPRECATED diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index b6d42fe06115..a098011951cc 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -33,6 +33,7 @@ =20 #define TRACE_MODE_WRITE 0640 #define TRACE_MODE_READ 0440 +#define TRACE_MODE_WRITE_MASK (TRACE_MODE_WRITE & ~TRACE_MODE_READ) =20 enum trace_type { __TRACE_FIRST_TYPE =3D 0, @@ -483,6 +484,12 @@ extern bool trace_clock_in_ns(struct trace_array *tr); =20 extern unsigned long trace_adjust_address(struct trace_array *tr, unsigned= long addr); =20 +static inline bool trace_array_is_readonly(struct trace_array *tr) +{ + /* backup instance is read only. */ + return tr->flags & TRACE_ARRAY_FL_VMALLOC; +} + /* * The global tracer (top) should be the first trace array added, * but we check the flag anyway. @@ -681,7 +688,6 @@ struct dentry *trace_create_file(const char *name, void *data, const struct file_operations *fops); =20 - /** * tracer_tracing_is_on_cpu - show real state of ring buffer enabled on fo= r a cpu * @tr : the trace array to know if ring buffer is enabled diff --git a/kernel/trace/trace_boot.c b/kernel/trace/trace_boot.c index dbe29b4c6a7a..2ca2541c8a58 100644 --- a/kernel/trace/trace_boot.c +++ b/kernel/trace/trace_boot.c @@ -61,7 +61,8 @@ trace_boot_set_instance_options(struct trace_array *tr, s= truct xbc_node *node) v =3D memparse(p, NULL); if (v < PAGE_SIZE) pr_err("Buffer size is too small: %s\n", p); - if (tracing_resize_ring_buffer(tr, v, RING_BUFFER_ALL_CPUS) < 0) + if (trace_array_is_readonly(tr) || + tracing_resize_ring_buffer(tr, v, RING_BUFFER_ALL_CPUS) < 0) pr_err("Failed to resize trace buffer to %s\n", p); } =20 @@ -597,7 +598,7 @@ trace_boot_enable_tracer(struct trace_array *tr, struct= xbc_node *node) =20 p =3D xbc_node_find_value(node, "tracer", NULL); if (p && *p !=3D '\0') { - if (tracing_set_tracer(tr, p) < 0) + if (trace_array_is_readonly(tr) || tracing_set_tracer(tr, p) < 0) pr_err("Failed to set given tracer: %s\n", p); } =20 diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 9b07ad9eb284..5a9e03470b03 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -1379,6 +1379,9 @@ static int __ftrace_set_clr_event(struct trace_array = *tr, const char *match, { int ret; =20 + if (trace_array_is_readonly(tr)) + return -EPERM; + mutex_lock(&event_mutex); ret =3D __ftrace_set_clr_event_nolock(tr, match, sub, event, set, mod); mutex_unlock(&event_mutex); @@ -2817,8 +2820,8 @@ event_subsystem_dir(struct trace_array *tr, const cha= r *name, } else __get_system(system); =20 - /* ftrace only has directories no files */ - if (strcmp(name, "ftrace") =3D=3D 0) + /* ftrace only has directories no files, readonly instance too. */ + if (strcmp(name, "ftrace") =3D=3D 0 || trace_array_is_readonly(tr)) nr_entries =3D 0; else nr_entries =3D ARRAY_SIZE(system_entries); @@ -2983,28 +2986,30 @@ event_create_dir(struct eventfs_inode *parent, stru= ct trace_event_file *file) int ret; static struct eventfs_entry event_entries[] =3D { { - .name =3D "enable", + .name =3D "format", .callback =3D event_callback, - .release =3D event_release, }, +#ifdef CONFIG_PERF_EVENTS { - .name =3D "filter", + .name =3D "id", .callback =3D event_callback, }, +#endif +#define NR_RO_EVENT_ENTRIES (1 + IS_ENABLED(CONFIG_PERF_EVENTS)) +/* Readonly files must be above this line and counted by NR_RO_EVENT_ENTRI= ES. */ { - .name =3D "trigger", + .name =3D "enable", .callback =3D event_callback, + .release =3D event_release, }, { - .name =3D "format", + .name =3D "filter", .callback =3D event_callback, }, -#ifdef CONFIG_PERF_EVENTS { - .name =3D "id", + .name =3D "trigger", .callback =3D event_callback, }, -#endif #ifdef CONFIG_HIST_TRIGGERS { .name =3D "hist", @@ -3037,9 +3042,13 @@ event_create_dir(struct eventfs_inode *parent, struc= t trace_event_file *file) if (!e_events) return -ENOMEM; =20 - nr_entries =3D ARRAY_SIZE(event_entries); + if (trace_array_is_readonly(tr)) + nr_entries =3D NR_RO_EVENT_ENTRIES; + else + nr_entries =3D ARRAY_SIZE(event_entries); =20 name =3D trace_event_name(call); + ei =3D eventfs_create_dir(name, e_events, event_entries, nr_entries, file= ); if (IS_ERR(ei)) { pr_warn("Could not create tracefs '%s' directory\n", name); @@ -4381,25 +4390,25 @@ create_event_toplevel_files(struct dentry *parent, = struct trace_array *tr) int nr_entries; static struct eventfs_entry events_entries[] =3D { { - .name =3D "enable", + .name =3D "header_page", .callback =3D events_callback, }, { - .name =3D "header_page", + .name =3D "header_event", .callback =3D events_callback, }, +#define NR_RO_TOP_ENTRIES 2 +/* Readonly files must be above this line and counted by NR_RO_TOP_ENTRIES= . */ { - .name =3D "header_event", + .name =3D "enable", .callback =3D events_callback, }, }; =20 - entry =3D trace_create_file("set_event", TRACE_MODE_WRITE, parent, - tr, &ftrace_set_event_fops); - if (!entry) - return -ENOMEM; - - nr_entries =3D ARRAY_SIZE(events_entries); + if (trace_array_is_readonly(tr)) + nr_entries =3D NR_RO_TOP_ENTRIES; + else + nr_entries =3D ARRAY_SIZE(events_entries); =20 e_events =3D eventfs_create_events_dir("events", parent, events_entries, nr_entries, tr); @@ -4408,15 +4417,22 @@ create_event_toplevel_files(struct dentry *parent, = struct trace_array *tr) return -ENOMEM; } =20 - /* There are not as crucial, just warn if they are not created */ + if (!trace_array_is_readonly(tr)) { =20 - trace_create_file("set_event_pid", TRACE_MODE_WRITE, parent, - tr, &ftrace_set_event_pid_fops); + entry =3D trace_create_file("set_event", TRACE_MODE_WRITE, parent, + tr, &ftrace_set_event_fops); + if (!entry) + return -ENOMEM; + + /* There are not as crucial, just warn if they are not created */ =20 - trace_create_file("set_event_notrace_pid", - TRACE_MODE_WRITE, parent, tr, - &ftrace_set_event_notrace_pid_fops); + trace_create_file("set_event_pid", TRACE_MODE_WRITE, parent, + tr, &ftrace_set_event_pid_fops); =20 + trace_create_file("set_event_notrace_pid", + TRACE_MODE_WRITE, parent, tr, + &ftrace_set_event_notrace_pid_fops); + } tr->event_dir =3D e_events; =20 return 0; From nobody Mon Feb 9 04:09:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2347B3BB57; Tue, 20 Jan 2026 01:09:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768871388; cv=none; b=sm4ZoWxUy8/avA19fHE2BL87ghwIiOrgGv63wcWi2q6nLZGN6TjG9iydfDm9A/S2fdj9QQjiWm3wNeLTOoBFJ7EOdnFla1R9AuPO+T9tkpiF96HLiVwVR3DO/UwvhLfa8aKfW8fYyTVPQd/TmHdVyJ2zijn3BwcJ/axIhkM5Xm4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768871388; c=relaxed/simple; bh=EvEKBerZnuyaXVWqI2juRsdFyqQcXzo2yf2xobNO7zQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=R84ojdiOtZe6MXYLQrLNOkCGqS6DCjEfY9mEN3OSXUifvV1MFoHUUrdqCbKLfq6SPTh1UGWGVJmvqE5xThzd0LMM6LJY5q91Q6cpkbvdMmwPZaPL6N3cXFDjSsxz5S+Da4DjUbozBH1H+VCG8ikqi/KkOux99iZrdHp6AMLwKCw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=eJxMZqWu; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="eJxMZqWu" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 01D96C116C6; Tue, 20 Jan 2026 01:09:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768871385; bh=EvEKBerZnuyaXVWqI2juRsdFyqQcXzo2yf2xobNO7zQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eJxMZqWuz4dthBJPVaUx236z+zAVVggtnlzt4zWvt878GGrNT4hHdzF4Lg1vsJ6FW Rr/yrTbQYBigw3QGThE3Fd6NrB43/Jffe3MxdCVcfrHc1b2HFplvzgmPXRmO/sR0Og 1FnUtCB/KZW7v5tA+m6SJfrBdm6yB4O7dmfzNfrUFn2cGzJNIle1x0Bw6QjK8mE4bz 5YaIgNPuL3oFNFONLZvMTMKfIqlVsbhvBwERWH3DAd8MSsJViwnxqRyG7qW9WFwAAF 0etBdyKp7b4G0UBmuenK8qp1tF597z3ij63Fg0JAve34z+KCeXHYNpGVEWw/5WHS0B yiv4X+/aiD++Q== From: "Masami Hiramatsu (Google)" To: Steven Rostedt Cc: Masami Hiramatsu , Mathieu Desnoyers , linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Subject: [PATCH v4 3/4] tracing: Remove the backup instance automatically after read Date: Tue, 20 Jan 2026 10:09:43 +0900 Message-ID: <176887138332.578403.342690450188917584.stgit@mhiramat.tok.corp.google.com> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <176887135615.578403.6988045330349053692.stgit@mhiramat.tok.corp.google.com> References: <176887135615.578403.6988045330349053692.stgit@mhiramat.tok.corp.google.com> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Masami Hiramatsu (Google) Since the backup instance is readonly, after reading all data via pipe, no data is left on the instance. Thus it can be removed safely after closing all files. This also removes it if user resets the ring buffer manually via 'trace' file. Signed-off-by: Masami Hiramatsu (Google) --- Changes in v4: - Update description. --- kernel/trace/trace.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++= +++- kernel/trace/trace.h | 6 +++++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index b27e1cdeffb0..7fa0809cd71b 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -590,6 +590,55 @@ void trace_set_ring_buffer_expanded(struct trace_array= *tr) tr->ring_buffer_expanded =3D true; } =20 +static int __remove_instance(struct trace_array *tr); + +static void trace_array_autoremove(struct work_struct *work) +{ + struct trace_array *tr =3D container_of(work, struct trace_array, autorem= ove_work); + + guard(mutex)(&event_mutex); + guard(mutex)(&trace_types_lock); + + /* + * This can be fail if someone gets @tr before starting this + * function, but in that case, this will be kicked again when + * putting it. So we don't care the result. + */ + __remove_instance(tr); +} + +static struct workqueue_struct *autoremove_wq; + +static void trace_array_init_autoremove(struct trace_array *tr) +{ + INIT_WORK(&tr->autoremove_work, trace_array_autoremove); +} + +static void trace_array_kick_autoremove(struct trace_array *tr) +{ + if (!work_pending(&tr->autoremove_work) && autoremove_wq) + queue_work(autoremove_wq, &tr->autoremove_work); +} + +static void trace_array_cancel_autoremove(struct trace_array *tr) +{ + if (work_pending(&tr->autoremove_work)) + cancel_work(&tr->autoremove_work); +} + +__init static int trace_array_init_autoremove_wq(void) +{ + autoremove_wq =3D alloc_workqueue("tr_autoremove_wq", + WQ_UNBOUND | WQ_HIGHPRI, 0); + if (!autoremove_wq) { + pr_err("Unable to allocate tr_autoremove_wq\n"); + return -ENOMEM; + } + return 0; +} + +late_initcall_sync(trace_array_init_autoremove_wq); + LIST_HEAD(ftrace_trace_arrays); =20 int trace_array_get(struct trace_array *this_tr) @@ -598,7 +647,7 @@ int trace_array_get(struct trace_array *this_tr) =20 guard(mutex)(&trace_types_lock); list_for_each_entry(tr, &ftrace_trace_arrays, list) { - if (tr =3D=3D this_tr) { + if (tr =3D=3D this_tr && !tr->free_on_close) { tr->ref++; return 0; } @@ -611,6 +660,12 @@ static void __trace_array_put(struct trace_array *this= _tr) { WARN_ON(!this_tr->ref); this_tr->ref--; + /* + * When free_on_close is set, prepare removing the array + * when the last reference is released. + */ + if (this_tr->ref =3D=3D 1 && this_tr->free_on_close) + trace_array_kick_autoremove(this_tr); } =20 /** @@ -6219,6 +6274,10 @@ static void update_last_data(struct trace_array *tr) /* Only if the buffer has previous boot data clear and update it. */ tr->flags &=3D ~TRACE_ARRAY_FL_LAST_BOOT; =20 + /* If this is a backup instance, mark it for autoremove. */ + if (tr->flags & TRACE_ARRAY_FL_VMALLOC) + tr->free_on_close =3D true; + /* Reset the module list and reload them */ if (tr->scratch) { struct trace_scratch *tscratch =3D tr->scratch; @@ -10390,6 +10449,8 @@ trace_array_create_systems(const char *name, const = char *systems, if (ftrace_allocate_ftrace_ops(tr) < 0) goto out_free_tr; =20 + trace_array_init_autoremove(tr); + ftrace_init_trace_array(tr); =20 init_trace_flags_index(tr); @@ -10538,6 +10599,7 @@ static int __remove_instance(struct trace_array *tr) if (update_marker_trace(tr, 0)) synchronize_rcu(); =20 + trace_array_cancel_autoremove(tr); tracing_set_nop(tr); clear_ftrace_function_probes(tr); event_trace_del_tracer(tr); diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index a098011951cc..947f641a9cf0 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -447,6 +447,12 @@ struct trace_array { * we do not waste memory on systems that are not using tracing. */ bool ring_buffer_expanded; + /* + * If the ring buffer is a read only backup instance, it will be + * removed after dumping all data via pipe, because no readable data. + */ + bool free_on_close; + struct work_struct autoremove_work; }; =20 enum { From nobody Mon Feb 9 04:09:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C0B221DF25F; Tue, 20 Jan 2026 01:09:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768871393; cv=none; b=vFokzV5m0KvhiGAhnF1n+AUnLOerYMT7oB0EBjfZjTLy20x75zy9y65T19dopNL6Q8dbeLEVXBKBw1oNiBpVeA4RvKB7zWXK4YXxAQoo1qLJFby0Vxws0AUUOA2cNegstssje41UahW4R2lCeAj7pFNVipM+fpdaZS22KZyqHGg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768871393; c=relaxed/simple; bh=ZaW5oZCDs9KNm6pL3BS/uCrrK5EMecxzSSpu9ruwHzs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=PSHCt0o4dS8C0IFo0JoLkJET5oaZjo0OaJpyj6xehyCJD2XtnxEzrMrumzYvJp68gtgqwNGCU3aGrxeiuTBUh7KferudT+bS9xOHoyLdgwxpxWC1eDNj0d7jaj8SMfk+xTWbo1+QumLiT/DkputOvjgJ7A+RwJNVz/ifoqX3jJs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=C/TvJ7pS; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="C/TvJ7pS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AF00AC116C6; Tue, 20 Jan 2026 01:09:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768871393; bh=ZaW5oZCDs9KNm6pL3BS/uCrrK5EMecxzSSpu9ruwHzs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=C/TvJ7pS0NhR61CwdDHcHKYj8XVBlvJpo2SsZ47Ep9K55gm0G8+0fPqEDV31nusMV UhRdQRtc73chc/r1Mh+mnd2YmeNUsAi65FzbXg3msdM2e8SRSG8W3mdqF3pXMIM5LW NckKc+qfiy26KG9tUQpkaK2uDqJZpGL73Dx51cvn9pFORCUAtMqWlzqNZkLpu5X5Y1 aJSNudIAV6Z8Yxm6tGg2B59dBAwS5Anl8b0vw76nFEHpq7qQEu6ykjbtiTbJWCtHvH +jf8ToRkG1LBlkAoZI4TWmQb6zF4agaymfprF3VFeA4EkT5vTiiDPfhcTgX7FEofAR YUMhj+OuHV/Aw== From: "Masami Hiramatsu (Google)" To: Steven Rostedt Cc: Masami Hiramatsu , Mathieu Desnoyers , linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Subject: [PATCH v4 4/4] tracing/Documentation: Add a section about backup instance Date: Tue, 20 Jan 2026 10:09:51 +0900 Message-ID: <176887139099.578403.7828440306150090568.stgit@mhiramat.tok.corp.google.com> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <176887135615.578403.6988045330349053692.stgit@mhiramat.tok.corp.google.com> References: <176887135615.578403.6988045330349053692.stgit@mhiramat.tok.corp.google.com> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Masami Hiramatsu (Google) Add a section about backup instance to the debugging.rst. Signed-off-by: Masami Hiramatsu (Google) --- Documentation/trace/debugging.rst | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Documentation/trace/debugging.rst b/Documentation/trace/debugg= ing.rst index 4d88c346fc38..73e2154bcf98 100644 --- a/Documentation/trace/debugging.rst +++ b/Documentation/trace/debugging.rst @@ -159,3 +159,22 @@ If setting it from the kernel command line, it is reco= mmended to also disable tracing with the "traceoff" flag, and enable tracing after boot up. Otherwise the trace from the most recent boot will be mixed with the trace from the previous boot, and may make it confusing to read. + +Using a backup instance for keeping previous boot data +------------------------------------------------------ + +It is also possible to record trace data at system boot time by specifying +events with the persistent ring buffer, but in this case the data before t= he +reboot will be lost before it can be read. This problem can be solved by a +backup instance. From the kernel command line:: + + reserve_mem=3D12M:4096:trace trace_instance=3Dboot_map@trace,sched,irq t= race_instance=3Dbackup=3Dboot_map + +When the boot up, the previous data in the`boot_map` is copied to "backup" +instance, and the "sched:*" and "irq:*" events for current boot are traced= on +"boot_map". Thus user can read the previous boot data from the "backup" in= stance +without stopping trace. + +Note that this "backup" instance is readonly, and will be removed automati= cally +if you clear the trace data or read out all trace data from "trace_pipe" or +"trace_pipe_raw" files. \ No newline at end of file