Skip to content

Commit 2c79da0

Browse files
mhiramatrostedt
authored andcommitted
tracing: Make the backup instance non-reusable
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 Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Link: https://patch.msgid.link/177502546939.1311542.1826814401724828930.stgit@mhiramat.tok.corp.google.com Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
1 parent 20ad8b0 commit 2c79da0

4 files changed

Lines changed: 104 additions & 65 deletions

File tree

kernel/trace/trace.c

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4022,6 +4022,11 @@ int tracing_open_generic_tr(struct inode *inode, struct file *filp)
40224022
if (ret)
40234023
return ret;
40244024

4025+
if ((filp->f_mode & FMODE_WRITE) && trace_array_is_readonly(tr)) {
4026+
trace_array_put(tr);
4027+
return -EACCES;
4028+
}
4029+
40254030
filp->private_data = inode->i_private;
40264031

40274032
return 0;
@@ -7097,6 +7102,11 @@ static int tracing_clock_open(struct inode *inode, struct file *file)
70977102
if (ret)
70987103
return ret;
70997104

7105+
if ((file->f_mode & FMODE_WRITE) && trace_array_is_readonly(tr)) {
7106+
trace_array_put(tr);
7107+
return -EACCES;
7108+
}
7109+
71007110
ret = single_open(file, tracing_clock_show, inode->i_private);
71017111
if (ret < 0)
71027112
trace_array_put(tr);
@@ -9866,17 +9876,22 @@ static __init void create_trace_instances(struct dentry *d_tracer)
98669876
static void
98679877
init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
98689878
{
9879+
umode_t writable_mode = TRACE_MODE_WRITE;
98699880
int cpu;
98709881

9882+
if (trace_array_is_readonly(tr))
9883+
writable_mode = TRACE_MODE_READ;
9884+
98719885
trace_create_file("available_tracers", TRACE_MODE_READ, d_tracer,
9872-
tr, &show_traces_fops);
9886+
tr, &show_traces_fops);
98739887

9874-
trace_create_file("current_tracer", TRACE_MODE_WRITE, d_tracer,
9875-
tr, &set_tracer_fops);
9888+
trace_create_file("current_tracer", writable_mode, d_tracer,
9889+
tr, &set_tracer_fops);
98769890

9877-
trace_create_file("tracing_cpumask", TRACE_MODE_WRITE, d_tracer,
9891+
trace_create_file("tracing_cpumask", writable_mode, d_tracer,
98789892
tr, &tracing_cpumask_fops);
98799893

9894+
/* Options are used for changing print-format even for readonly instance. */
98809895
trace_create_file("trace_options", TRACE_MODE_WRITE, d_tracer,
98819896
tr, &tracing_iter_fops);
98829897

@@ -9886,12 +9901,36 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
98869901
trace_create_file("trace_pipe", TRACE_MODE_READ, d_tracer,
98879902
tr, &tracing_pipe_fops);
98889903

9889-
trace_create_file("buffer_size_kb", TRACE_MODE_WRITE, d_tracer,
9904+
trace_create_file("buffer_size_kb", writable_mode, d_tracer,
98909905
tr, &tracing_entries_fops);
98919906

98929907
trace_create_file("buffer_total_size_kb", TRACE_MODE_READ, d_tracer,
98939908
tr, &tracing_total_entries_fops);
98949909

9910+
trace_create_file("trace_clock", writable_mode, d_tracer, tr,
9911+
&trace_clock_fops);
9912+
9913+
trace_create_file("timestamp_mode", TRACE_MODE_READ, d_tracer, tr,
9914+
&trace_time_stamp_mode_fops);
9915+
9916+
tr->buffer_percent = 50;
9917+
9918+
trace_create_file("buffer_subbuf_size_kb", writable_mode, d_tracer,
9919+
tr, &buffer_subbuf_size_fops);
9920+
9921+
create_trace_options_dir(tr);
9922+
9923+
if (tr->range_addr_start)
9924+
trace_create_file("last_boot_info", TRACE_MODE_READ, d_tracer,
9925+
tr, &last_boot_fops);
9926+
9927+
for_each_tracing_cpu(cpu)
9928+
tracing_init_tracefs_percpu(tr, cpu);
9929+
9930+
/* Read-only instance has above files only. */
9931+
if (trace_array_is_readonly(tr))
9932+
return;
9933+
98959934
trace_create_file("free_buffer", 0200, d_tracer,
98969935
tr, &tracing_free_buffer_fops);
98979936

@@ -9903,49 +9942,29 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
99039942
trace_create_file("trace_marker_raw", 0220, d_tracer,
99049943
tr, &tracing_mark_raw_fops);
99059944

9906-
trace_create_file("trace_clock", TRACE_MODE_WRITE, d_tracer, tr,
9907-
&trace_clock_fops);
9908-
9909-
trace_create_file("tracing_on", TRACE_MODE_WRITE, d_tracer,
9910-
tr, &rb_simple_fops);
9911-
9912-
trace_create_file("timestamp_mode", TRACE_MODE_READ, d_tracer, tr,
9913-
&trace_time_stamp_mode_fops);
9914-
9915-
tr->buffer_percent = 50;
9916-
99179945
trace_create_file("buffer_percent", TRACE_MODE_WRITE, d_tracer,
9918-
tr, &buffer_percent_fops);
9919-
9920-
trace_create_file("buffer_subbuf_size_kb", TRACE_MODE_WRITE, d_tracer,
9921-
tr, &buffer_subbuf_size_fops);
9946+
tr, &buffer_percent_fops);
99229947

99239948
trace_create_file("syscall_user_buf_size", TRACE_MODE_WRITE, d_tracer,
9924-
tr, &tracing_syscall_buf_fops);
9949+
tr, &tracing_syscall_buf_fops);
99259950

9926-
create_trace_options_dir(tr);
9951+
trace_create_file("tracing_on", TRACE_MODE_WRITE, d_tracer,
9952+
tr, &rb_simple_fops);
99279953

99289954
trace_create_maxlat_file(tr, d_tracer);
99299955

99309956
if (ftrace_create_function_files(tr, d_tracer))
99319957
MEM_FAIL(1, "Could not allocate function filter files");
99329958

9933-
if (tr->range_addr_start) {
9934-
trace_create_file("last_boot_info", TRACE_MODE_READ, d_tracer,
9935-
tr, &last_boot_fops);
99369959
#ifdef CONFIG_TRACER_SNAPSHOT
9937-
} else {
9960+
if (!tr->range_addr_start)
99389961
trace_create_file("snapshot", TRACE_MODE_WRITE, d_tracer,
99399962
tr, &snapshot_fops);
99409963
#endif
9941-
}
99429964

99439965
trace_create_file("error_log", TRACE_MODE_WRITE, d_tracer,
99449966
tr, &tracing_err_log_fops);
99459967

9946-
for_each_tracing_cpu(cpu)
9947-
tracing_init_tracefs_percpu(tr, cpu);
9948-
99499968
ftrace_init_tracefs(tr, d_tracer);
99509969
}
99519970

@@ -10772,7 +10791,7 @@ __init static void enable_instances(void)
1077210791
* Backup buffers can be freed but need vfree().
1077310792
*/
1077410793
if (backup)
10775-
tr->flags |= TRACE_ARRAY_FL_VMALLOC;
10794+
tr->flags |= TRACE_ARRAY_FL_VMALLOC | TRACE_ARRAY_FL_RDONLY;
1077610795

1077710796
if (start || backup) {
1077810797
tr->flags |= TRACE_ARRAY_FL_BOOT | TRACE_ARRAY_FL_LAST_BOOT;

kernel/trace/trace.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@ enum {
462462
TRACE_ARRAY_FL_MOD_INIT = BIT(3),
463463
TRACE_ARRAY_FL_MEMMAP = BIT(4),
464464
TRACE_ARRAY_FL_VMALLOC = BIT(5),
465+
TRACE_ARRAY_FL_RDONLY = BIT(6),
465466
};
466467

467468
#ifdef CONFIG_MODULES
@@ -491,6 +492,12 @@ extern unsigned long trace_adjust_address(struct trace_array *tr, unsigned long
491492

492493
extern struct trace_array *printk_trace;
493494

495+
static inline bool trace_array_is_readonly(struct trace_array *tr)
496+
{
497+
/* backup instance is read only. */
498+
return tr->flags & TRACE_ARRAY_FL_RDONLY;
499+
}
500+
494501
/*
495502
* The global tracer (top) should be the first trace array added,
496503
* but we check the flag anyway.

kernel/trace/trace_boot.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ trace_boot_set_instance_options(struct trace_array *tr, struct xbc_node *node)
6161
v = memparse(p, NULL);
6262
if (v < PAGE_SIZE)
6363
pr_err("Buffer size is too small: %s\n", p);
64-
if (tracing_resize_ring_buffer(tr, v, RING_BUFFER_ALL_CPUS) < 0)
64+
if (trace_array_is_readonly(tr) ||
65+
tracing_resize_ring_buffer(tr, v, RING_BUFFER_ALL_CPUS) < 0)
6566
pr_err("Failed to resize trace buffer to %s\n", p);
6667
}
6768

@@ -597,7 +598,7 @@ trace_boot_enable_tracer(struct trace_array *tr, struct xbc_node *node)
597598

598599
p = xbc_node_find_value(node, "tracer", NULL);
599600
if (p && *p != '\0') {
600-
if (tracing_set_tracer(tr, p) < 0)
601+
if (trace_array_is_readonly(tr) || tracing_set_tracer(tr, p) < 0)
601602
pr_err("Failed to set given tracer: %s\n", p);
602603
}
603604

kernel/trace/trace_events.c

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,6 +1401,9 @@ static int __ftrace_set_clr_event(struct trace_array *tr, const char *match,
14011401
{
14021402
int ret;
14031403

1404+
if (trace_array_is_readonly(tr))
1405+
return -EACCES;
1406+
14041407
mutex_lock(&event_mutex);
14051408
ret = __ftrace_set_clr_event_nolock(tr, match, sub, event, set, mod);
14061409
mutex_unlock(&event_mutex);
@@ -2973,8 +2976,8 @@ event_subsystem_dir(struct trace_array *tr, const char *name,
29732976
} else
29742977
__get_system(system);
29752978

2976-
/* ftrace only has directories no files */
2977-
if (strcmp(name, "ftrace") == 0)
2979+
/* ftrace only has directories no files, readonly instance too. */
2980+
if (strcmp(name, "ftrace") == 0 || trace_array_is_readonly(tr))
29782981
nr_entries = 0;
29792982
else
29802983
nr_entries = ARRAY_SIZE(system_entries);
@@ -3139,28 +3142,30 @@ event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file)
31393142
int ret;
31403143
static struct eventfs_entry event_entries[] = {
31413144
{
3142-
.name = "enable",
3145+
.name = "format",
31433146
.callback = event_callback,
3144-
.release = event_release,
31453147
},
3148+
#ifdef CONFIG_PERF_EVENTS
31463149
{
3147-
.name = "filter",
3150+
.name = "id",
31483151
.callback = event_callback,
31493152
},
3153+
#endif
3154+
#define NR_RO_EVENT_ENTRIES (1 + IS_ENABLED(CONFIG_PERF_EVENTS))
3155+
/* Readonly files must be above this line and counted by NR_RO_EVENT_ENTRIES. */
31503156
{
3151-
.name = "trigger",
3157+
.name = "enable",
31523158
.callback = event_callback,
3159+
.release = event_release,
31533160
},
31543161
{
3155-
.name = "format",
3162+
.name = "filter",
31563163
.callback = event_callback,
31573164
},
3158-
#ifdef CONFIG_PERF_EVENTS
31593165
{
3160-
.name = "id",
3166+
.name = "trigger",
31613167
.callback = event_callback,
31623168
},
3163-
#endif
31643169
#ifdef CONFIG_HIST_TRIGGERS
31653170
{
31663171
.name = "hist",
@@ -3193,7 +3198,10 @@ event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file)
31933198
if (!e_events)
31943199
return -ENOMEM;
31953200

3196-
nr_entries = ARRAY_SIZE(event_entries);
3201+
if (trace_array_is_readonly(tr))
3202+
nr_entries = NR_RO_EVENT_ENTRIES;
3203+
else
3204+
nr_entries = ARRAY_SIZE(event_entries);
31973205

31983206
name = trace_event_name(call);
31993207
ei = eventfs_create_dir(name, e_events, event_entries, nr_entries, file);
@@ -4536,31 +4544,44 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
45364544
int nr_entries;
45374545
static struct eventfs_entry events_entries[] = {
45384546
{
4539-
.name = "enable",
4547+
.name = "header_page",
45404548
.callback = events_callback,
45414549
},
45424550
{
4543-
.name = "header_page",
4551+
.name = "header_event",
45444552
.callback = events_callback,
45454553
},
4554+
#define NR_RO_TOP_ENTRIES 2
4555+
/* Readonly files must be above this line and counted by NR_RO_TOP_ENTRIES. */
45464556
{
4547-
.name = "header_event",
4557+
.name = "enable",
45484558
.callback = events_callback,
45494559
},
45504560
};
45514561

4552-
entry = trace_create_file("set_event", TRACE_MODE_WRITE, parent,
4553-
tr, &ftrace_set_event_fops);
4554-
if (!entry)
4555-
return -ENOMEM;
4562+
if (!trace_array_is_readonly(tr)) {
4563+
entry = trace_create_file("set_event", TRACE_MODE_WRITE, parent,
4564+
tr, &ftrace_set_event_fops);
4565+
if (!entry)
4566+
return -ENOMEM;
45564567

4557-
trace_create_file("show_event_filters", TRACE_MODE_READ, parent, tr,
4558-
&ftrace_show_event_filters_fops);
4568+
/* There are not as crucial, just warn if they are not created */
4569+
trace_create_file("show_event_filters", TRACE_MODE_READ, parent, tr,
4570+
&ftrace_show_event_filters_fops);
45594571

4560-
trace_create_file("show_event_triggers", TRACE_MODE_READ, parent, tr,
4561-
&ftrace_show_event_triggers_fops);
4572+
trace_create_file("show_event_triggers", TRACE_MODE_READ, parent, tr,
4573+
&ftrace_show_event_triggers_fops);
45624574

4563-
nr_entries = ARRAY_SIZE(events_entries);
4575+
trace_create_file("set_event_pid", TRACE_MODE_WRITE, parent,
4576+
tr, &ftrace_set_event_pid_fops);
4577+
4578+
trace_create_file("set_event_notrace_pid",
4579+
TRACE_MODE_WRITE, parent, tr,
4580+
&ftrace_set_event_notrace_pid_fops);
4581+
nr_entries = ARRAY_SIZE(events_entries);
4582+
} else {
4583+
nr_entries = NR_RO_TOP_ENTRIES;
4584+
}
45644585

45654586
e_events = eventfs_create_events_dir("events", parent, events_entries,
45664587
nr_entries, tr);
@@ -4569,15 +4590,6 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
45694590
return -ENOMEM;
45704591
}
45714592

4572-
/* There are not as crucial, just warn if they are not created */
4573-
4574-
trace_create_file("set_event_pid", TRACE_MODE_WRITE, parent,
4575-
tr, &ftrace_set_event_pid_fops);
4576-
4577-
trace_create_file("set_event_notrace_pid",
4578-
TRACE_MODE_WRITE, parent, tr,
4579-
&ftrace_set_event_notrace_pid_fops);
4580-
45814593
tr->event_dir = e_events;
45824594

45834595
return 0;

0 commit comments

Comments
 (0)