summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-10-27 15:01:12 -1000
committerLinus Torvalds <torvalds@linux-foundation.org>2026-10-27 15:01:12 -1000
commit59a02493f3b68fd0ad68c661393f680bcca5a85b (patch)
treec5f6641a4330f1b23888dcfebb40726a15aed97f /kernel
parent8a36f53fd5ec3eff01f1b637d42cbdc3821d0493 (diff)
parent1fdc4164e488916402badddbb1f51e9380dabb91 (diff)
Merge tag 'trace-v7.4' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull tracing updates from Steven Rostedt: - Add "within" to filter logic Add a way to trace events by what function they fall in. echo 'within == "vfs_read" > events/sched/sched_switch/filter Will only trigger sched_switch events that happen within the vfs_read function. It uses a stacktrace at the event and checks if any entry is within the specified function and if so, it prints the event. - Remove a duplicate definition of ftrace_set_clr_event() from the header - Do not have ftrace_set_clr_event() modify its input buffer Have the buffer passed into ftrace_set_clr_event() to be const char * and not allow modifications to it that might cause side effects. - Add kunit tests for ftrace_parse_event_string() - Add filter argument to __ftrace_set_clr_event() Make it possible to set a filter on an event at the same time it is enabled. - Add event filtering logic to the kernel command line To allow filtering events on boot, allow filtering to be specified on the kernel command line when enabling events. - Rename "ring_buffer_size()" to "ring_buffer_capacity()" "size" refers to how much is allocated whereas the actual return value is the amount of available data in the ring buffer minus its meta data. - Rename "trace_array_entries" to "trace_array_capacity" There's several functions that use "entries" and returns the amount of data that that is usable. "entries" should be only for the number of events, not the amount of data. - Print the histogram "bucket" size as unsigned. If a bucket size is LONG_MAX, then it shows up as a negative number. - Show bucket size in output of histograms The output of what the histogram is shown doesn't show the size of the buckets when buckets are used. The output should be the same as the input and since specifying buckets without a size is an invalid command, the output to display what was entered should also show the size. - Fix stacktrace modifier output Only show the stacktrace modifier when it was specified in creation. - Unregister filed variable histograms when the command fails If one histogram references a variable of another histogram it registers that other histogram. But if the first histogram fails in setup after it registered the other histogram it doesn't unregister it. Have the first histogram add the reference to the other histogram so the failure clean up will unregister the second histogram too. - Fix 64-bit signed histogram fields on 32-bit kernels A fix to convert char * to u64 with added casting also incorrectly added an intermediate cast to convert a long value to u64 which ended up truncating the upper 32 bits for 32-bit kernels. Remove the intermediate typecast. - Print signed histogram keys as signed Histogram keys were being printed as unsigned and with signed keys it was giving the wrong output. - Use copy_from_user() and not __copy_from_user() in syscall tracing The syscall tracing incorrectly was using __copy_from_user() which could be an issue if the system trusts perf doing the trace. - Take trace_types_lock when recording a new module in persistent buffer When a new module is loaded, the persistent ring buffer saves it in its persistent memory. All the trace_arrays are iterated looking for any persistent buffer to add the module to. But it did not hold the trace_types_lock meaning a trace_array could be added or removed while iterating the list. - Only create tracepoint guest_halt_poll_ns when it is used The tracepoint guest_halt_poll_ns is defined in the power management code but it is only used when CONFIG_CPU_IDLE_GOV_HALTPOLL is enabled. This wastes memory when that config isn't enabled so wrap the tracepoint around that as well. - Handle empty fields for events in trace_event_get_offsets() The user events could have empty fields and this causes trace_event_get_offsets() to crash as it expects events to always have fields. Make the function handle events with no fields. - Reject incomplete event filter expressions If a filter has an incomplete expression (common_pid == 1111 || ), it will cause a out-of-bounds bug. Have the predicate_parse() only process the expression if it is complete. * tag 'trace-v7.4' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: (27 commits) tracing: Reject incomplete event filter expressions tracing: Guard trace_event_get_offsets() against an empty fields list cpuidle: haltpoll: Only define guest_halt_poll_ns tracepoint when used tracing/osnoise: Add __printf attribute to osnoise_print() tracing/histograms: Verify event_call identity when updating synth_event refcount tracing: Save the event file instead of the compatible histogram tracing: Hold trace_types_lock when resetting last boot data from readers tracing: Hold trace_types_lock when updating modules in persistent instances tracing/syscalls: Use copy_from_user for the faultable syscall buffer tracing: Print a signed histogram key as signed tracing: Fix 64-bit and signed histogram fields on 32-bit kernels tracing: Clamp the printed end of a histogram bucket at U64_MAX tracing: Unregister field variable histograms when the command fails tracing: Only report the stacktrace modifier on a real field tracing: Add the bucket size to expr_field_str() tracing: Print the bucket size as unsigned tracing: Rename tracing_entries_fops to tracing_capacity_fops tracing: Rename trace_array::entries to capacity ring-buffer: Rename ring_buffer_size() to ring_buffer_capacity() tracing: Parse filter from boot event string ...
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/Kconfig8
-rw-r--r--kernel/trace/Makefile1
-rw-r--r--kernel/trace/ring_buffer.c13
-rw-r--r--kernel/trace/trace.c72
-rw-r--r--kernel/trace/trace.h13
-rw-r--r--kernel/trace/trace_boot.c2
-rw-r--r--kernel/trace/trace_events.c132
-rw-r--r--kernel/trace/trace_events_filter.c50
-rw-r--r--kernel/trace/trace_events_hist.c61
-rw-r--r--kernel/trace/trace_events_synth.c10
-rw-r--r--kernel/trace/trace_events_test.c122
-rw-r--r--kernel/trace/trace_osnoise.c1
-rw-r--r--kernel/trace/trace_snapshot.c14
-rw-r--r--kernel/trace/trace_synth.h1
-rw-r--r--kernel/trace/trace_syscalls.c2
15 files changed, 383 insertions, 119 deletions
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index d8faeb659cfc..c41397eccee5 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -151,6 +151,14 @@ config EVENT_TRACING
select GLOB
bool
+config EVENT_TRACING_TEST
+ tristate "Test for event tracing" if !KUNIT_ALL_TESTS
+ depends on EVENT_TRACING
+ depends on KUNIT
+ default KUNIT_ALL_TESTS
+ help
+ KUnit test for the event tracing implementation.
+
config CONTEXT_SWITCH_TRACER
bool
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index 1f925cd1b9f8..b0c44f438999 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -96,6 +96,7 @@ obj-$(CONFIG_EVENT_TRACING) += blktrace.o
endif
obj-$(CONFIG_EVENT_TRACING) += trace_events.o
obj-$(CONFIG_EVENT_TRACING) += trace_export.o
+obj-$(CONFIG_EVENT_TRACING_TEST) += trace_events_test.o
obj-$(CONFIG_FTRACE_SYSCALLS) += trace_syscalls.o
ifeq ($(CONFIG_PERF_EVENTS),y)
obj-$(CONFIG_EVENT_TRACING) += trace_event_perf.o
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index b52f51db9045..1fd28a72e6ee 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -6548,18 +6548,23 @@ void ring_buffer_iter_advance(struct ring_buffer_iter *iter)
EXPORT_SYMBOL_GPL(ring_buffer_iter_advance);
/**
- * ring_buffer_size - return the size of the ring buffer (in bytes)
+ * ring_buffer_capacity - return the capacity of the ring buffer (in bytes)
* @buffer: The ring buffer.
- * @cpu: The CPU to get ring buffer size from.
+ * @cpu: The CPU to get ring buffer capacity from.
+ *
+ * Capacity is the total memory available for recording event data in the
+ * ring buffer. It excludes subbuffer headers.
+ *
+ * Returns the capacity in bytes, or 0 if the CPU is not set in the buffer mask.
*/
-unsigned long ring_buffer_size(struct trace_buffer *buffer, int cpu)
+unsigned long ring_buffer_capacity(struct trace_buffer *buffer, int cpu)
{
if (!cpumask_test_cpu(cpu, buffer->cpumask))
return 0;
return rb_subbuf_capacity(buffer) * buffer->buffers[cpu]->nr_pages;
}
-EXPORT_SYMBOL_GPL(ring_buffer_size);
+EXPORT_SYMBOL_GPL(ring_buffer_capacity);
/**
* ring_buffer_max_event_size - return the max data size of an event
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 97a058623f94..e8c4efa8107b 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -3614,6 +3614,7 @@ static int tracing_single_release_tr(struct inode *inode, struct file *file)
return single_release(inode, file);
}
+static bool __update_last_data_if_empty(struct trace_array *tr);
static bool update_last_data_if_empty(struct trace_array *tr);
static int tracing_open(struct inode *inode, struct file *file)
@@ -4708,24 +4709,24 @@ 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);
+ __update_last_data_if_empty(tr);
return t->init(tr);
}
-void trace_set_buffer_entries(struct array_buffer *buf, unsigned long val)
+void trace_set_buffer_capacity(struct array_buffer *buf, unsigned long val)
{
int cpu;
for_each_tracing_cpu(cpu)
- per_cpu_ptr(buf->data, cpu)->entries = val;
+ per_cpu_ptr(buf->data, cpu)->capacity = val;
}
-static void update_buffer_entries(struct array_buffer *buf, int cpu)
+static void update_buffer_capacity(struct array_buffer *buf, int cpu)
{
if (cpu == RING_BUFFER_ALL_CPUS) {
- trace_set_buffer_entries(buf, ring_buffer_size(buf->buffer, 0));
+ trace_set_buffer_capacity(buf, ring_buffer_capacity(buf->buffer, 0));
} else {
- per_cpu_ptr(buf->data, cpu)->entries = ring_buffer_size(buf->buffer, cpu);
+ per_cpu_ptr(buf->data, cpu)->capacity = ring_buffer_capacity(buf->buffer, cpu);
}
}
@@ -4781,12 +4782,12 @@ static int __tracing_resize_ring_buffer(struct trace_array *tr,
goto out_start;
}
- update_buffer_entries(&tr->snapshot_buffer, cpu);
+ update_buffer_capacity(&tr->snapshot_buffer, cpu);
out:
#endif /* CONFIG_TRACER_SNAPSHOT */
- update_buffer_entries(&tr->array_buffer, cpu);
+ update_buffer_capacity(&tr->array_buffer, cpu);
out_start:
tracing_start_tr(tr);
return ret;
@@ -5387,8 +5388,10 @@ static int tracing_wait_pipe(struct file *filp)
return 1;
}
-static bool update_last_data_if_empty(struct trace_array *tr)
+static bool __update_last_data_if_empty(struct trace_array *tr)
{
+ lockdep_assert_held(&trace_types_lock);
+
if (!(tr->flags & TRACE_ARRAY_FL_LAST_BOOT))
return false;
@@ -5403,6 +5406,16 @@ static bool update_last_data_if_empty(struct trace_array *tr)
return true;
}
+static bool update_last_data_if_empty(struct trace_array *tr)
+{
+ /* Avoid the lock on the read path unless this is a last boot buffer */
+ if (!(tr->flags & TRACE_ARRAY_FL_LAST_BOOT))
+ return false;
+
+ guard(mutex)(&trace_types_lock);
+ return __update_last_data_if_empty(tr);
+}
+
/*
* Consumer reader.
*/
@@ -5688,8 +5701,7 @@ tracing_syscall_buf_write(struct file *filp, const char __user *ubuf,
}
static ssize_t
-tracing_entries_read(struct file *filp, char __user *ubuf,
- size_t cnt, loff_t *ppos)
+tracing_capacity_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
{
struct inode *inode = file_inode(filp);
struct trace_array *tr = inode->i_private;
@@ -5710,8 +5722,8 @@ tracing_entries_read(struct file *filp, char __user *ubuf,
for_each_tracing_cpu(cpu) {
/* fill in the size from first enabled cpu */
if (size == 0)
- size = per_cpu_ptr(tr->array_buffer.data, cpu)->entries;
- if (size != per_cpu_ptr(tr->array_buffer.data, cpu)->entries) {
+ size = per_cpu_ptr(tr->array_buffer.data, cpu)->capacity;
+ if (size != per_cpu_ptr(tr->array_buffer.data, cpu)->capacity) {
buf_size_same = 0;
break;
}
@@ -5727,7 +5739,7 @@ tracing_entries_read(struct file *filp, char __user *ubuf,
} else
r = sprintf(buf, "X\n");
} else
- r = sprintf(buf, "%lu\n", per_cpu_ptr(tr->array_buffer.data, cpu)->entries >> 10);
+ r = sprintf(buf, "%lu\n", per_cpu_ptr(tr->array_buffer.data, cpu)->capacity >> 10);
mutex_unlock(&trace_types_lock);
@@ -5736,8 +5748,7 @@ tracing_entries_read(struct file *filp, char __user *ubuf,
}
static ssize_t
-tracing_entries_write(struct file *filp, const char __user *ubuf,
- size_t cnt, loff_t *ppos)
+tracing_capacity_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
{
struct inode *inode = file_inode(filp);
struct trace_array *tr = inode->i_private;
@@ -5764,8 +5775,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
}
static ssize_t
-tracing_total_entries_read(struct file *filp, char __user *ubuf,
- size_t cnt, loff_t *ppos)
+tracing_total_capacity_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
{
struct trace_array *tr = filp->private_data;
char buf[64];
@@ -5774,7 +5784,7 @@ tracing_total_entries_read(struct file *filp, char __user *ubuf,
mutex_lock(&trace_types_lock);
for_each_tracing_cpu(cpu) {
- size += per_cpu_ptr(tr->array_buffer.data, cpu)->entries >> 10;
+ size += per_cpu_ptr(tr->array_buffer.data, cpu)->capacity >> 10;
if (!tr->ring_buffer_expanded)
expanded_size += trace_buf_size >> 10;
}
@@ -6495,7 +6505,7 @@ int tracing_set_clock(struct trace_array *tr, const char *clockstr)
ring_buffer_set_clock(tr->snapshot_buffer.buffer, trace_clocks[i].func);
tracing_reset_online_cpus(&tr->snapshot_buffer);
#endif
- update_last_data_if_empty(tr);
+ __update_last_data_if_empty(tr);
if (tr->scratch && !(tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) {
struct trace_scratch *tscratch = tr->scratch;
@@ -6616,10 +6626,10 @@ static const struct file_operations tracing_pipe_fops = {
.release = tracing_release_pipe,
};
-static const struct file_operations tracing_entries_fops = {
+static const struct file_operations tracing_capacity_fops = {
.open = tracing_open_generic_tr,
- .read = tracing_entries_read,
- .write = tracing_entries_write,
+ .read = tracing_capacity_read,
+ .write = tracing_capacity_write,
.llseek = generic_file_llseek,
.release = tracing_release_generic_tr,
};
@@ -6639,9 +6649,9 @@ static const struct file_operations tracing_buffer_meta_fops = {
.release = tracing_seq_release,
};
-static const struct file_operations tracing_total_entries_fops = {
+static const struct file_operations tracing_total_capacity_fops = {
.open = tracing_open_generic_tr,
- .read = tracing_total_entries_read,
+ .read = tracing_total_capacity_read,
.llseek = generic_file_llseek,
.release = tracing_release_generic_tr,
};
@@ -7669,7 +7679,7 @@ tracing_init_tracefs_percpu(struct trace_array *tr, long cpu)
tr, cpu, &tracing_stats_fops);
trace_create_cpu_file("buffer_size_kb", TRACE_MODE_WRITE, d_cpu,
- tr, cpu, &tracing_entries_fops);
+ tr, cpu, &tracing_capacity_fops);
if (tr->range_addr_start)
trace_create_cpu_file("buffer_meta", TRACE_MODE_READ, d_cpu,
@@ -8535,8 +8545,8 @@ int allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf, int
}
/* Allocate the first page for all buffers */
- trace_set_buffer_entries(&tr->array_buffer,
- ring_buffer_size(tr->array_buffer.buffer, 0));
+ trace_set_buffer_capacity(&tr->array_buffer,
+ ring_buffer_capacity(tr->array_buffer.buffer, 0));
return 0;
}
@@ -9014,10 +9024,10 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
tr, &tracing_pipe_fops);
trace_create_file("buffer_size_kb", writable_mode, d_tracer,
- tr, &tracing_entries_fops);
+ tr, &tracing_capacity_fops);
trace_create_file("buffer_total_size_kb", TRACE_MODE_READ, d_tracer,
- tr, &tracing_total_entries_fops);
+ tr, &tracing_total_capacity_fops);
trace_create_file("trace_clock", writable_mode, d_tracer, tr,
&trace_clock_fops);
@@ -9263,6 +9273,8 @@ static void trace_module_record(struct module *mod, bool add)
struct trace_array *tr;
unsigned long flags;
+ guard(mutex)(&trace_types_lock);
+
list_for_each_entry(tr, &ftrace_trace_arrays, list) {
flags = tr->flags & (TRACE_ARRAY_FL_BOOT | TRACE_ARRAY_FL_LAST_BOOT);
/* Update any persistent trace array that has already been started */
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 9044f03fe2d9..0635503a31dd 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -191,7 +191,7 @@ struct trace_array;
struct trace_array_cpu {
local_t disabled;
- unsigned long entries;
+ unsigned long capacity;
unsigned long saved_latency;
unsigned long critical_start;
unsigned long critical_end;
@@ -731,7 +731,7 @@ ssize_t tracing_nsecs_read(unsigned long *ptr, char __user *ubuf,
ssize_t tracing_nsecs_write(unsigned long *ptr, const char __user *ubuf,
size_t cnt, loff_t *ppos);
-void trace_set_buffer_entries(struct array_buffer *buf, unsigned long val);
+void trace_set_buffer_capacity(struct array_buffer *buf, unsigned long val);
/*
* Should be used after trace_array_get(), trace_types_lock
@@ -1823,7 +1823,8 @@ static inline bool is_string_field(struct ftrace_event_field *field)
field->filter_type == FILTER_RDYN_STRING ||
field->filter_type == FILTER_STATIC_STRING ||
field->filter_type == FILTER_PTR_STRING ||
- field->filter_type == FILTER_COMM;
+ field->filter_type == FILTER_COMM ||
+ field->filter_type == FILTER_WITHIN;
}
static inline bool is_function_field(struct ftrace_event_field *field)
@@ -2286,7 +2287,6 @@ static inline const char *get_syscall_name(int syscall)
void trace_event_init(void);
void trace_event_update_all(struct trace_eval_map **map, int len, struct module *mod);
/* Used from boot time tracer */
-extern int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set);
extern int trigger_process_regex(struct trace_event_file *file, char *buff);
#else
static inline void __init trace_event_init(void) { }
@@ -2506,3 +2506,8 @@ static inline int rv_init_interface(void)
})
#endif /* _LINUX_KERNEL_TRACE_H */
+
+#if IS_ENABLED(CONFIG_KUNIT)
+void ftrace_parse_event_string(char *buf, char **match, char **sub, char **event, char **mod,
+ bool handle_filter, char **filter);
+#endif
diff --git a/kernel/trace/trace_boot.c b/kernel/trace/trace_boot.c
index 5da0a8bbb110..6ba70dac1f06 100644
--- a/kernel/trace/trace_boot.c
+++ b/kernel/trace/trace_boot.c
@@ -94,7 +94,7 @@ trace_boot_enable_events(struct trace_array *tr, struct xbc_node *node)
continue;
}
- if (ftrace_set_clr_event(tr, buf, 1) < 0)
+ if (ftrace_set_clr_event(tr, buf, 1, false) < 0)
pr_err("Failed to enable event: %s\n", p);
}
}
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 6428861102a1..49d135bc2fbf 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -25,6 +25,8 @@
#include <linux/delay.h>
#include <linux/btf.h>
+#include <kunit/visibility.h>
+
#include <trace/events/sched.h>
#include <trace/syscall.h>
@@ -201,6 +203,9 @@ static int trace_define_generic_fields(void)
__generic_field(char *, comm, FILTER_COMM);
__generic_field(char *, stacktrace, FILTER_STACKTRACE);
__generic_field(char *, STACKTRACE, FILTER_STACKTRACE);
+#ifdef CONFIG_STACKTRACE
+ __generic_field(char *, within, FILTER_WITHIN);
+#endif
return ret;
}
@@ -241,6 +246,10 @@ int trace_event_get_offsets(struct trace_event_call *call)
struct list_head *head;
head = trace_get_fields(call);
+
+ if (list_empty(head))
+ return sizeof(struct trace_entry);
+
/*
* head->next points to the last field with the largest offset,
* since it was added last by trace_define_field()
@@ -941,6 +950,7 @@ struct event_mod_load {
char *match;
char *system;
char *event;
+ char *filter;
};
static void free_event_mod(struct event_mod_load *event_mod)
@@ -950,6 +960,7 @@ static void free_event_mod(struct event_mod_load *event_mod)
kfree(event_mod->match);
kfree(event_mod->system);
kfree(event_mod->event);
+ kfree(event_mod->filter);
kfree(event_mod);
}
@@ -991,7 +1002,7 @@ static int remove_cache_mod(struct trace_array *tr, const char *mod,
}
static int cache_mod(struct trace_array *tr, const char *mod, int set,
- const char *match, const char *system, const char *event)
+ const char *match, const char *system, const char *event, const char *filter)
{
struct event_mod_load *event_mod;
@@ -1030,6 +1041,12 @@ static int cache_mod(struct trace_array *tr, const char *mod, int set,
goto out_free;
}
+ if (filter) {
+ event_mod->filter = kstrdup(filter, GFP_KERNEL);
+ if (!event_mod->filter)
+ goto out_free;
+ }
+
list_add(&event_mod->list, &tr->mod_events);
return 0;
@@ -1042,7 +1059,7 @@ static int cache_mod(struct trace_array *tr, const char *mod, int set,
#else /* CONFIG_MODULES */
static inline void clear_mod_events(struct trace_array *tr) { }
static int cache_mod(struct trace_array *tr, const char *mod, int set,
- const char *match, const char *system, const char *event)
+ const char *match, const char *system, const char *event, const char *filter)
{
return -EINVAL;
}
@@ -1351,7 +1368,7 @@ static void remove_event_file_dir(struct trace_event_file *file)
static int
__ftrace_set_clr_event_nolock(struct trace_array *tr, const char *match,
const char *sub, const char *event, int set,
- const char *mod)
+ const char *mod, char *filter)
{
struct trace_event_file *file;
struct trace_event_call *call;
@@ -1401,7 +1418,11 @@ __ftrace_set_clr_event_nolock(struct trace_array *tr, const char *match,
if (event && strcmp(event, name) != 0)
continue;
- ret = ftrace_event_enable_disable(file, set);
+ if (filter)
+ ret = apply_event_filter(file, filter);
+
+ if (!filter || !ret)
+ ret = ftrace_event_enable_disable(file, set);
/*
* Save the first error and return that. Some events
@@ -1419,14 +1440,14 @@ __ftrace_set_clr_event_nolock(struct trace_array *tr, const char *match,
* check if the module was loaded. If it wasn't cache it.
*/
if (module && ret == -EINVAL && !eret)
- ret = cache_mod(tr, module, set, match, sub, event);
+ ret = cache_mod(tr, module, set, match, sub, event, filter);
return ret;
}
static int __ftrace_set_clr_event(struct trace_array *tr, const char *match,
const char *sub, const char *event, int set,
- const char *mod)
+ const char *mod, char *filter)
{
int ret;
@@ -1434,26 +1455,35 @@ static int __ftrace_set_clr_event(struct trace_array *tr, const char *match,
return -EACCES;
mutex_lock(&event_mutex);
- ret = __ftrace_set_clr_event_nolock(tr, match, sub, event, set, mod);
+ ret = __ftrace_set_clr_event_nolock(tr, match, sub, event, set, mod, filter);
mutex_unlock(&event_mutex);
return ret;
}
-int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set)
+VISIBLE_IF_KUNIT void
+ftrace_parse_event_string(char *buf, char **match, char **sub, char **event, char **mod,
+ bool handle_filter, char **filter)
{
- char *event = NULL, *sub = NULL, *match, *mod;
- int ret;
+ *event = NULL;
+ *sub = NULL;
+ *filter = NULL;
- if (!tr)
- return -ENOENT;
+ /* event filters can be appended with :filter:<filter> */
+ if (handle_filter) {
+ *filter = strstr(buf, ":filter:");
+ if (*filter) {
+ **filter = '\0';
+ *filter += 8;
+ }
+ }
/* Modules events can be appended with :mod:<module> */
- mod = strstr(buf, ":mod:");
- if (mod) {
- *mod = '\0';
+ *mod = strstr(buf, ":mod:");
+ if (*mod) {
+ **mod = '\0';
/* move to the module name */
- mod += 5;
+ *mod += 5;
}
/*
@@ -1468,31 +1498,38 @@ int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set)
* the name <name> or any event that matches <name>
*/
- match = strsep(&buf, ":");
+ *match = strsep(&buf, ":");
if (buf) {
- sub = match;
- event = buf;
- match = NULL;
-
- if (!strlen(sub) || strcmp(sub, "*") == 0)
- sub = NULL;
- if (!strlen(event) || strcmp(event, "*") == 0)
- event = NULL;
- } else if (mod) {
+ *sub = *match;
+ *event = buf;
+ *match = NULL;
+
+ if (!strlen(*sub) || strcmp(*sub, "*") == 0)
+ *sub = NULL;
+ if (!strlen(*event) || strcmp(*event, "*") == 0)
+ *event = NULL;
+ } else if (*mod) {
/* Allow wildcard for no length or star */
- if (!strlen(match) || strcmp(match, "*") == 0)
- match = NULL;
+ if (!strlen(*match) || strcmp(*match, "*") == 0)
+ *match = NULL;
}
+}
+EXPORT_SYMBOL_IF_KUNIT(ftrace_parse_event_string);
- ret = __ftrace_set_clr_event(tr, match, sub, event, set, mod);
+int ftrace_set_clr_event(struct trace_array *tr, const char *arg_buf, int set, bool handle_filter)
+{
+ char *event, *sub, *match, *mod, *filter;
- /* Put back the colon to allow this to be called again */
- if (buf)
- *(buf - 1) = ':';
- if (mod)
- *(mod - 5) = ':';
+ if (!tr)
+ return -ENOENT;
- return ret;
+ char *dupped_buf __free(kfree) = kstrdup(arg_buf, GFP_KERNEL);
+ if (!dupped_buf)
+ return -ENOMEM;
+
+ ftrace_parse_event_string(dupped_buf, &match, &sub, &event, &mod, handle_filter, &filter);
+
+ return __ftrace_set_clr_event(tr, match, sub, event, set, mod, filter);
}
/**
@@ -1514,7 +1551,7 @@ int trace_set_clr_event(const char *system, const char *event, int set)
if (!tr)
return -ENODEV;
- return __ftrace_set_clr_event(tr, NULL, system, event, set, NULL);
+ return __ftrace_set_clr_event(tr, NULL, system, event, set, NULL, NULL);
}
EXPORT_SYMBOL_GPL(trace_set_clr_event);
@@ -1540,7 +1577,7 @@ int trace_array_set_clr_event(struct trace_array *tr, const char *system,
return -ENOENT;
set = (enable == true) ? 1 : 0;
- return __ftrace_set_clr_event(tr, NULL, system, event, set, NULL);
+ return __ftrace_set_clr_event(tr, NULL, system, event, set, NULL, NULL);
}
EXPORT_SYMBOL_GPL(trace_array_set_clr_event);
@@ -1574,7 +1611,7 @@ ftrace_event_write(struct file *file, const char __user *ubuf,
if (*parser.buffer == '!')
set = 0;
- ret = ftrace_set_clr_event(tr, parser.buffer + !set, set);
+ ret = ftrace_set_clr_event(tr, parser.buffer + !set, set, false);
if (ret)
goto out_put;
}
@@ -2060,7 +2097,7 @@ system_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
if (system)
name = system->name;
- ret = __ftrace_set_clr_event(dir->tr, NULL, name, NULL, val, NULL);
+ ret = __ftrace_set_clr_event(dir->tr, NULL, name, NULL, val, NULL, NULL);
if (ret)
goto out;
@@ -4035,7 +4072,8 @@ static void update_mod_cache(struct trace_array *tr, struct module *mod)
__ftrace_set_clr_event_nolock(tr, event_mod->match,
event_mod->system,
- event_mod->event, 1, mod->name);
+ event_mod->event, 1, mod->name,
+ event_mod->filter);
free_event_mod(event_mod);
}
}
@@ -4809,7 +4847,7 @@ int event_trace_del_tracer(struct trace_array *tr)
__ftrace_clear_event_pids(tr, TRACE_PIDS | TRACE_NO_PIDS);
/* Disable any running events */
- __ftrace_set_clr_event_nolock(tr, NULL, NULL, NULL, 0, NULL);
+ __ftrace_set_clr_event_nolock(tr, NULL, NULL, NULL, 0, NULL, NULL);
/* Make sure no more events are being executed */
tracepoint_synchronize_unregister();
@@ -4842,10 +4880,10 @@ static __init void __early_set_events(struct trace_array *tr, char *buf, bool en
while ((token = strsep(&buf, ","))) {
if (*token) {
if (enable) {
- if (ftrace_set_clr_event(tr, token, 1))
+ if (ftrace_set_clr_event(tr, token, 1, true))
pr_warn("Failed to enable trace event: %s\n", token);
} else {
- ftrace_set_clr_event(tr, token, 0);
+ ftrace_set_clr_event(tr, token, 0, true);
}
}
@@ -5119,7 +5157,7 @@ static __init void event_trace_self_tests(void)
pr_info("Testing event system %s: ", system->name);
- ret = __ftrace_set_clr_event(tr, NULL, system->name, NULL, 1, NULL);
+ ret = __ftrace_set_clr_event(tr, NULL, system->name, NULL, 1, NULL, NULL);
if (WARN_ON_ONCE(ret)) {
pr_warn("error enabling system %s\n",
system->name);
@@ -5128,7 +5166,7 @@ static __init void event_trace_self_tests(void)
event_test_stuff();
- ret = __ftrace_set_clr_event(tr, NULL, system->name, NULL, 0, NULL);
+ ret = __ftrace_set_clr_event(tr, NULL, system->name, NULL, 0, NULL, NULL);
if (WARN_ON_ONCE(ret)) {
pr_warn("error disabling system %s\n",
system->name);
@@ -5143,7 +5181,7 @@ static __init void event_trace_self_tests(void)
pr_info("Running tests on all trace events:\n");
pr_info("Testing all events: ");
- ret = __ftrace_set_clr_event(tr, NULL, NULL, NULL, 1, NULL);
+ ret = __ftrace_set_clr_event(tr, NULL, NULL, NULL, 1, NULL, NULL);
if (WARN_ON_ONCE(ret)) {
pr_warn("error enabling all events\n");
return;
@@ -5152,7 +5190,7 @@ static __init void event_trace_self_tests(void)
event_test_stuff();
/* reset sysname */
- ret = __ftrace_set_clr_event(tr, NULL, NULL, NULL, 0, NULL);
+ ret = __ftrace_set_clr_event(tr, NULL, NULL, NULL, 0, NULL, NULL);
if (WARN_ON_ONCE(ret)) {
pr_warn("error disabling all events\n");
return;
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 127880ebe83f..c10951bcfc5f 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -72,6 +72,7 @@ enum filter_pred_fn {
FILTER_PRED_FN_CPUMASK,
FILTER_PRED_FN_CPUMASK_CPU,
FILTER_PRED_FN_FUNCTION,
+ FILTER_PRED_FN_WITHIN,
FILTER_PRED_FN_,
FILTER_PRED_TEST_VISITED,
};
@@ -117,6 +118,7 @@ struct filter_pred {
C(IP_FIELD_ONLY, "Only 'ip' field is supported for function trace"), \
C(INVALID_VALUE, "Invalid value (did you forget quotes)?"), \
C(NO_FUNCTION, "Function not found"), \
+ C(GLOB_WITHIN, "'within' filter cannot take glob expressions"), \
C(ERRNO, "Error"), \
C(NO_FILTER, "No filter found")
@@ -595,6 +597,12 @@ predicate_parse(const char *str, int nr_parens, int nr_preds,
top--; /* #12 */
}
}
+ /* Only the inner loop can complete a non-empty expression. */
+ if (N) {
+ ret = -EINVAL;
+ parse_error(pe, FILT_ERR_INVALID_FILTER, ptr - str);
+ goto out_free;
+ }
out:
if (top != op_stack) {
/* Too many '(' */
@@ -1008,6 +1016,22 @@ static int filter_pred_function(struct filter_pred *pred, void *event)
return pred->op == OP_EQ ? ret : !ret;
}
+/* Filter predicate for within. */
+static int filter_pred_within(struct filter_pred *pred, void *event)
+{
+#ifdef CONFIG_STACKTRACE
+ unsigned long entries[16];
+ unsigned int nr_entries;
+ int i;
+
+ nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 0);
+ for (i = 0; i < nr_entries; i++)
+ if (pred->val <= entries[i] && entries[i] < pred->val2)
+ return !pred->not;
+#endif
+ return pred->not;
+}
+
/*
* regex_match_foo - Basic regex callbacks
*
@@ -1617,6 +1641,8 @@ static int filter_pred_fn_call(struct filter_pred *pred, void *event)
return filter_pred_cpumask_cpu(pred, event);
case FILTER_PRED_FN_FUNCTION:
return filter_pred_function(pred, event);
+ case FILTER_PRED_FN_WITHIN:
+ return filter_pred_within(pred, event);
case FILTER_PRED_TEST_VISITED:
return test_pred_visited_fn(pred, event);
default:
@@ -2002,10 +2028,30 @@ static int parse_pred(const char *str, void *data,
} else if (field->filter_type == FILTER_DYN_STRING) {
pred->fn_num = FILTER_PRED_FN_STRLOC;
- } else if (field->filter_type == FILTER_RDYN_STRING)
+ } else if (field->filter_type == FILTER_RDYN_STRING) {
pred->fn_num = FILTER_PRED_FN_STRRELLOC;
- else {
+ } else if (field->filter_type == FILTER_WITHIN) {
+ unsigned long func;
+ if (op == OP_GLOB) {
+ parse_error(pe, FILT_ERR_GLOB_WITHIN, pos + i);
+ goto err_free;
+ }
+
+ pred->fn_num = FILTER_PRED_FN_WITHIN;
+ func = kallsyms_lookup_name(pred->regex->pattern);
+ if (!func) {
+ parse_error(pe, FILT_ERR_NO_FUNCTION, pos + i);
+ goto err_free;
+ }
+ /* Now find the function start and end address */
+ if (!kallsyms_lookup_size_offset(func, &size, &offset)) {
+ parse_error(pe, FILT_ERR_NO_FUNCTION, pos + i);
+ goto err_free;
+ }
+ pred->val = func - offset;
+ pred->val2 = pred->val + size;
+ } else {
if (!ustring_per_cpu) {
/* Once allocated, keep it around for good */
ustring_per_cpu = alloc_percpu(struct ustring_buffer);
diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index 5c07fee3a328..1aae7d7c6dc5 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -279,6 +279,14 @@ static u64 hist_field_pstring(struct hist_field *hist_field,
return (u64)(unsigned long)*addr;
}
+static bool hist_field_is_signed(struct hist_field *hist_field)
+{
+ if (hist_field->field)
+ return hist_field->field->is_signed;
+
+ return hist_field->is_signed;
+}
+
static u64 hist_field_log2(struct hist_field *hist_field,
struct tracing_map_elt *elt,
struct trace_buffer *buffer,
@@ -466,7 +474,7 @@ static u64 hist_field_unary_minus(struct hist_field *hist_field,
{ \
type *addr = (type *)(event + hist_field->field->offset); \
\
- return (u64)(unsigned long)*addr; \
+ return (u64)*addr; \
}
DEFINE_HIST_FIELD_FN(s64);
@@ -549,7 +557,7 @@ struct field_var {
};
struct field_var_hist {
- struct hist_trigger_data *hist_data;
+ struct trace_event_file *file;
char *cmd;
};
@@ -1725,7 +1733,7 @@ static const char *get_hist_field_flags(struct hist_field *hist_field)
flags_str = "percent";
else if (hist_field->flags & HIST_FIELD_FL_GRAPH)
flags_str = "graph";
- else if (hist_field->flags & HIST_FIELD_FL_STACKTRACE)
+ else if (hist_field->flags & HIST_FIELD_FL_STACKTRACE && hist_field->field)
flags_str = "stacktrace";
return flags_str;
@@ -1754,6 +1762,9 @@ static bool expr_field_str(struct hist_field *field, struct seq_buf *s)
seq_buf_printf(s, ".%s", flags_str);
}
+ if (field->buckets)
+ seq_buf_printf(s, "=%lu", field->buckets);
+
return !seq_buf_has_overflowed(s);
}
@@ -3117,8 +3128,8 @@ create_field_var_hist(struct hist_trigger_data *target_hist_data,
return ERR_PTR(-ENOMEM);
}
- /* Save the compatible histogram information */
- var_hist->hist_data = hist_data;
+ /* Needed to remove the histogram when the target goes away */
+ var_hist->file = file;
/* Create the new histogram with our variable */
ret = event_hist_trigger_parse(&trigger_hist_cmd, file,
@@ -3133,20 +3144,18 @@ create_field_var_hist(struct hist_trigger_data *target_hist_data,
kfree(cmd);
+ n = target_hist_data->n_field_var_hists;
+ target_hist_data->field_var_hists[n] = var_hist;
+ target_hist_data->n_field_var_hists++;
+
/* If we can't find the variable, something went wrong */
event_var = find_synthetic_field_var(target_hist_data, subsys_name,
event_name, field_name);
if (IS_ERR_OR_NULL(event_var)) {
- kfree(var_hist->cmd);
- kfree(var_hist);
hist_err(tr, HIST_ERR_SYNTH_VAR_NOT_FOUND, errpos(field_name));
return ERR_PTR(-EINVAL);
}
- n = target_hist_data->n_field_var_hists;
- target_hist_data->field_var_hists[n] = var_hist;
- target_hist_data->n_field_var_hists++;
-
return event_var;
}
@@ -5565,15 +5574,24 @@ static void hist_trigger_print_key(struct seq_file *m,
*(u64 *)(key + key_field->offset));
} else if (key_field->flags & HIST_FIELD_FL_BUCKET) {
unsigned long buckets = key_field->buckets;
+ u64 end;
+
uval = *(u64 *)(key + key_field->offset);
+ end = uval + buckets - 1;
+ if (end < uval)
+ end = U64_MAX;
seq_printf(m, "%s: ~ %llu-%llu", field_name,
- uval, uval + buckets -1);
+ uval, end);
} else if (key_field->flags & HIST_FIELD_FL_STRING) {
seq_printf(m, "%s: %-50s", field_name,
(char *)(key + key_field->offset));
} else {
uval = *(u64 *)(key + key_field->offset);
- seq_printf(m, "%s: %10llu", field_name, uval);
+ if (hist_field_is_signed(key_field))
+ seq_printf(m, "%s: %10lld", field_name,
+ (s64)uval);
+ else
+ seq_printf(m, "%s: %10llu", field_name, uval);
}
}
@@ -6205,7 +6223,7 @@ static void hist_field_print(struct seq_file *m, struct hist_field *hist_field)
}
}
if (hist_field->buckets)
- seq_printf(m, "=%ld", hist_field->buckets);
+ seq_printf(m, "=%lu", hist_field->buckets);
}
static int event_hist_trigger_print(struct seq_file *m,
@@ -6349,7 +6367,7 @@ static void unregister_field_var_hists(struct hist_trigger_data *hist_data)
int ret;
for (i = 0; i < hist_data->n_field_var_hists; i++) {
- file = hist_data->field_var_hists[i]->hist_data->event_file;
+ file = hist_data->field_var_hists[i]->file;
cmd = hist_data->field_var_hists[i]->cmd;
ret = event_hist_trigger_parse(&trigger_hist_cmd, file,
"!hist", "hist", cmd);
@@ -6799,7 +6817,6 @@ static void hist_unreg_all(struct trace_event_file *file)
struct event_trigger_data *test, *n;
struct hist_trigger_data *hist_data;
struct synth_event *se;
- const char *se_name;
lockdep_assert_held(&event_mutex);
@@ -6812,8 +6829,7 @@ static void hist_unreg_all(struct trace_event_file *file)
list_del_rcu(&test->list);
trace_event_trigger_enable_disable(file, 0);
- se_name = trace_event_name(file->event_call);
- se = find_synth_event(se_name);
+ se = find_synth_event_call(file->event_call);
if (se)
se->ref--;
@@ -6837,7 +6853,6 @@ static int event_hist_trigger_parse(struct event_command *cmd_ops,
struct hist_trigger_data *hist_data;
char *param, *filter, *p, *start;
struct synth_event *se;
- const char *se_name;
bool remove;
int ret = 0;
@@ -6931,8 +6946,7 @@ static int event_hist_trigger_parse(struct event_command *cmd_ops,
}
event_trigger_unregister(cmd_ops, file, glob+1, trigger_data);
- se_name = trace_event_name(file->event_call);
- se = find_synth_event(se_name);
+ se = find_synth_event_call(file->event_call);
if (se)
se->ref--;
ret = 0;
@@ -6967,8 +6981,7 @@ static int event_hist_trigger_parse(struct event_command *cmd_ops,
if (ret)
goto out_unreg;
- se_name = trace_event_name(file->event_call);
- se = find_synth_event(se_name);
+ se = find_synth_event_call(file->event_call);
if (se)
se->ref++;
out:
@@ -6985,6 +6998,8 @@ static int event_hist_trigger_parse(struct event_command *cmd_ops,
trigger_data_free(trigger_data);
+ unregister_field_var_hists(hist_data);
+
destroy_hist_data(hist_data);
goto out;
}
diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c
index dc15658a887c..e2870212e58d 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -914,6 +914,16 @@ struct synth_event *find_synth_event(const char *name)
return NULL;
}
+struct synth_event *find_synth_event_call(struct trace_event_call *call)
+{
+ struct synth_event *se;
+ const char *name;
+
+ name = trace_event_name(call);
+ se = find_synth_event(name);
+ return se && &se->call == call ? se : NULL;
+}
+
static struct trace_event_fields synth_event_fields_array[] = {
{ .type = TRACE_FUNCTION_TYPE,
.define_fields = synth_event_define_fields },
diff --git a/kernel/trace/trace_events_test.c b/kernel/trace/trace_events_test.c
new file mode 100644
index 000000000000..4a2d77fa0f58
--- /dev/null
+++ b/kernel/trace/trace_events_test.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/module.h>
+
+#include <kunit/test.h>
+
+#include "trace.h"
+
+struct parse_event_string_test_case {
+ const char *input;
+
+ const char *match, *sub, *event, *mod, *filter;
+};
+
+static const struct parse_event_string_test_case parse_event_string_test_cases[] = {
+ {
+ "",
+ .match = "",
+ },
+ {
+ "*:event",
+ .event = "event",
+ },
+ {
+ ":event",
+ .event = "event",
+ },
+ {
+ "sub:*",
+ .sub = "sub",
+ },
+ {
+ "sub:",
+ .sub = "sub",
+ },
+ {
+ "sub:event",
+ .sub = "sub",
+ .event = "event",
+ },
+ {
+ "sub:event:filter:filter",
+ .sub = "sub",
+ .event = "event",
+ .filter = "filter",
+ },
+ {
+ "match",
+ .match = "match",
+ },
+ {
+ ":mod:module",
+ .mod = "module",
+ },
+ {
+ "sub:event:mod:module",
+ .sub = "sub",
+ .event = "event",
+ .mod = "module",
+ },
+ {
+ "sub:event:mod:module:filter:filter",
+ .sub = "sub",
+ .event = "event",
+ .mod = "module",
+ .filter = "filter",
+ },
+ {
+ "sub:event:mod:module:filter:unexpected-filter",
+ .sub = "sub",
+ .event = "event",
+ .mod = "module:filter:unexpected-filter",
+ },
+};
+
+static void
+parse_event_string_test_desc(const struct parse_event_string_test_case *params, char *desc)
+{
+ snprintf(desc, KUNIT_PARAM_DESC_SIZE, "'%s'", params->input);
+}
+
+KUNIT_ARRAY_PARAM(parse_event_string, parse_event_string_test_cases, parse_event_string_test_desc);
+
+#define EXPECT_NULL_OR_STR_EQ(test, left, right) \
+({ \
+ if ((left) != NULL) \
+ KUNIT_EXPECT_STREQ(test, (left), (right)); \
+ else \
+ KUNIT_EXPECT_NULL(test, (right)); \
+})
+
+static void parse_event_string(struct kunit *test)
+{
+ const struct parse_event_string_test_case *params = test->param_value;
+ char *input, *match, *sub, *event, *mod, *filter;
+
+ input = kunit_kstrdup(test, params->input, GFP_KERNEL);
+ if (!input)
+ kunit_skip(test, "ENOMEM");
+
+ ftrace_parse_event_string(input, &match, &sub, &event, &mod, params->filter, &filter);
+
+ EXPECT_NULL_OR_STR_EQ(test, match, params->match);
+ EXPECT_NULL_OR_STR_EQ(test, sub, params->sub);
+ EXPECT_NULL_OR_STR_EQ(test, event, params->event);
+ EXPECT_NULL_OR_STR_EQ(test, mod, params->mod);
+ EXPECT_NULL_OR_STR_EQ(test, filter, params->filter);
+}
+
+static struct kunit_case trace_events_test_cases[] = {
+ KUNIT_CASE_PARAM(parse_event_string, parse_event_string_gen_params),
+ {}
+};
+
+static struct kunit_suite trace_events_test_suite = {
+ .name = "trace-events",
+ .test_cases = trace_events_test_cases,
+};
+kunit_test_suite(trace_events_test_suite);
+
+MODULE_DESCRIPTION("KUnit test for the event tracing implementation");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
diff --git a/kernel/trace/trace_osnoise.c b/kernel/trace/trace_osnoise.c
index 0e1265acd1cc..995da9e0b548 100644
--- a/kernel/trace/trace_osnoise.c
+++ b/kernel/trace/trace_osnoise.c
@@ -83,6 +83,7 @@ struct osnoise_instance {
static struct list_head osnoise_instances;
+__printf(1, 2)
static void osnoise_print(const char *fmt, ...)
{
struct osnoise_instance *inst;
diff --git a/kernel/trace/trace_snapshot.c b/kernel/trace/trace_snapshot.c
index 4731ef7325a5..72b8e6803144 100644
--- a/kernel/trace/trace_snapshot.c
+++ b/kernel/trace/trace_snapshot.c
@@ -142,18 +142,18 @@ int resize_buffer_duplicate_size(struct array_buffer *trace_buf,
if (cpu_id == RING_BUFFER_ALL_CPUS) {
for_each_tracing_cpu(cpu) {
ret = ring_buffer_resize(trace_buf->buffer,
- per_cpu_ptr(size_buf->data, cpu)->entries, cpu);
+ per_cpu_ptr(size_buf->data, cpu)->capacity, cpu);
if (ret < 0)
break;
- per_cpu_ptr(trace_buf->data, cpu)->entries =
- per_cpu_ptr(size_buf->data, cpu)->entries;
+ per_cpu_ptr(trace_buf->data, cpu)->capacity =
+ per_cpu_ptr(size_buf->data, cpu)->capacity;
}
} else {
ret = ring_buffer_resize(trace_buf->buffer,
- per_cpu_ptr(size_buf->data, cpu_id)->entries, cpu_id);
+ per_cpu_ptr(size_buf->data, cpu_id)->capacity, cpu_id);
if (ret == 0)
- per_cpu_ptr(trace_buf->data, cpu_id)->entries =
- per_cpu_ptr(size_buf->data, cpu_id)->entries;
+ per_cpu_ptr(trace_buf->data, cpu_id)->capacity =
+ per_cpu_ptr(size_buf->data, cpu_id)->capacity;
}
return ret;
@@ -193,7 +193,7 @@ void free_snapshot(struct trace_array *tr)
*/
ring_buffer_subbuf_order_set(tr->snapshot_buffer.buffer, 0);
ring_buffer_resize(tr->snapshot_buffer.buffer, 1, RING_BUFFER_ALL_CPUS);
- trace_set_buffer_entries(&tr->snapshot_buffer, 1);
+ trace_set_buffer_capacity(&tr->snapshot_buffer, 1);
tracing_reset_online_cpus(&tr->snapshot_buffer);
tr->allocated_snapshot = false;
}
diff --git a/kernel/trace/trace_synth.h b/kernel/trace/trace_synth.h
index 43f6fb6078db..d4ebf01b7049 100644
--- a/kernel/trace/trace_synth.h
+++ b/kernel/trace/trace_synth.h
@@ -37,5 +37,6 @@ struct synth_event {
};
extern struct synth_event *find_synth_event(const char *name);
+extern struct synth_event *find_synth_event_call(struct trace_event_call *call);
#endif /* __TRACE_SYNTH_H */
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index e35744049e3f..d9190fdc030d 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -683,7 +683,7 @@ static int syscall_copy_user_array(char *buf, const char __user *ptr,
for (int i = 0; i < args->uargs; i++, buf += SYSCALL_FAULT_ARG_SZ) {
ptr = (char __user *)args->ptr_array[i];
- ret = __copy_from_user(buf, ptr, size);
+ ret = copy_from_user(buf, ptr, size);
args->read[i] = ret ? -1 : size;
}
return 0;