Skip to content

Commit ba1d8b0

Browse files
committed
Merge tag 'trace-v6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull tracing updates from Steven Rostedt: - Deprecate auto-mounting tracefs to /sys/kernel/debug/tracing When tracefs was first introduced back in 2014, the directory /sys/kernel/tracing was added and is the designated location to mount tracefs. To keep backward compatibility, tracefs was auto-mounted in /sys/kernel/debug/tracing as well. All distros now mount tracefs on /sys/kernel/tracing. Having it seen in two different locations has lead to various issues and inconsistencies. The VFS folks have to also maintain debugfs_create_automount() for this single user. It's been over 10 years. Tooling and scripts should start replacing the debugfs location with the tracefs one. The reason tracefs was created in the first place was to allow access to the tracing facilities without the need to configure debugfs into the kernel. Using tracefs should now be more robust. A new config is created: CONFIG_TRACEFS_AUTOMOUNT_DEPRECATED which is default y, so that the kernel is still built with the automount. This config allows those that want to remove the automount from debugfs to do so. When tracefs is accessed from /sys/kernel/debug/tracing, the following printk is triggerd: pr_warn("NOTICE: Automounting of tracing to debugfs is deprecated and will be removed in 2030\n"); This gives users another 5 years to fix their scripts. - Use queue_rcu_work() instead of call_rcu() for freeing event filters The number of filters to be free can be many depending on the number of events within an event system. Freeing them from softirq context can potentially cause undesired latency. Use the RCU workqueue to free them instead. - Remove pointless memory barriers in latency code Memory barriers were added to some of the latency code a long time ago with the idea of "making them visible", but that's not what memory barriers are for. They are to synchronize access between different variables. There was no synchronization here making them pointless. - Remove "__attribute__()" from the type field of event format When LLVM is used to compile the kernel with CONFIG_DEBUG_INFO_BTF=y and PAHOLE_HAS_BTF_TAG=y, some of the format fields get expanded with the following: field:const char * filename; offset:24; size:8; signed:0; Turns into: field:const char __attribute__((btf_type_tag("user"))) * filename; offset:24; size:8; signed:0; This confuses parsers. Add code to strip these tags from the strings. - Add eprobe config option CONFIG_EPROBE_EVENTS Eprobes were added back in 5.15 but were only enabled when another probe was enabled (kprobe, fprobe, uprobe, etc). The eprobes had no config option of their own. Add one as they should be a separate entity. It's default y to keep with the old kernels but still has dependencies on TRACING and HAVE_REGS_AND_STACK_ACCESS_API. - Add eprobe documentation When eprobes were added back in 5.15 no documentation was added to describe them. This needs to be rectified. - Replace open coded cpumask_next_wrap() in move_to_next_cpu() - Have preemptirq_delay_run() use off-stack CPU mask - Remove obsolete comment about pelt_cfs event DECLARE_TRACE() appends "_tp" to trace events now, but the comment above pelt_cfs still mentioned appending it manually. - Remove EVENT_FILE_FL_SOFT_MODE flag The SOFT_MODE flag was required when the soft enabling and disabling of trace events was first introduced. But there was a bug with this approach as it only worked for a single instance. When multiple users required soft disabling and disabling the code was changed to have a ref count. The SOFT_MODE flag is now set iff the ref count is non zero. This is redundant and just reading the ref count is good enough. - Fix typo in comment * tag 'trace-v6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: Documentation: tracing: Add documentation about eprobes tracing: Have eprobes have their own config option tracing: Remove "__attribute__()" from the type field of event format tracing: Deprecate auto-mounting tracefs in debugfs tracing: Fix comment in trace_module_remove_events() tracing: Remove EVENT_FILE_FL_SOFT_MODE flag tracing: Remove pointless memory barriers tracing/sched: Remove obsolete comment on suffixes kernel: trace: preemptirq_delay_test: use offstack cpu mask tracing: Use queue_rcu_work() to free filters tracing: Replace opencoded cpumask_next_wrap() in move_to_next_cpu()
2 parents ef7acd3 + 085fbc3 commit ba1d8b0

1 file changed

Lines changed: 120 additions & 34 deletions

File tree

kernel/trace/trace_events.c

Lines changed: 120 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,7 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file,
768768
{
769769
struct trace_event_call *call = file->event_call;
770770
struct trace_array *tr = file->tr;
771+
bool soft_mode = atomic_read(&file->sm_ref) != 0;
771772
int ret = 0;
772773
int disable;
773774

@@ -782,19 +783,19 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file,
782783
* is set we do not want the event to be enabled before we
783784
* clear the bit.
784785
*
785-
* When soft_disable is not set but the SOFT_MODE flag is,
786+
* When soft_disable is not set but the soft_mode is,
786787
* we do nothing. Do not disable the tracepoint, otherwise
787788
* "soft enable"s (clearing the SOFT_DISABLED bit) wont work.
788789
*/
789790
if (soft_disable) {
790791
if (atomic_dec_return(&file->sm_ref) > 0)
791792
break;
792793
disable = file->flags & EVENT_FILE_FL_SOFT_DISABLED;
793-
clear_bit(EVENT_FILE_FL_SOFT_MODE_BIT, &file->flags);
794+
soft_mode = false;
794795
/* Disable use of trace_buffered_event */
795796
trace_buffered_event_disable();
796797
} else
797-
disable = !(file->flags & EVENT_FILE_FL_SOFT_MODE);
798+
disable = !soft_mode;
798799

799800
if (disable && (file->flags & EVENT_FILE_FL_ENABLED)) {
800801
clear_bit(EVENT_FILE_FL_ENABLED_BIT, &file->flags);
@@ -812,8 +813,8 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file,
812813

813814
WARN_ON_ONCE(ret);
814815
}
815-
/* If in SOFT_MODE, just set the SOFT_DISABLE_BIT, else clear it */
816-
if (file->flags & EVENT_FILE_FL_SOFT_MODE)
816+
/* If in soft mode, just set the SOFT_DISABLE_BIT, else clear it */
817+
if (soft_mode)
817818
set_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, &file->flags);
818819
else
819820
clear_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, &file->flags);
@@ -823,7 +824,7 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file,
823824
* When soft_disable is set and enable is set, we want to
824825
* register the tracepoint for the event, but leave the event
825826
* as is. That means, if the event was already enabled, we do
826-
* nothing (but set SOFT_MODE). If the event is disabled, we
827+
* nothing (but set soft_mode). If the event is disabled, we
827828
* set SOFT_DISABLED before enabling the event tracepoint, so
828829
* it still seems to be disabled.
829830
*/
@@ -832,15 +833,15 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file,
832833
else {
833834
if (atomic_inc_return(&file->sm_ref) > 1)
834835
break;
835-
set_bit(EVENT_FILE_FL_SOFT_MODE_BIT, &file->flags);
836+
soft_mode = true;
836837
/* Enable use of trace_buffered_event */
837838
trace_buffered_event_enable();
838839
}
839840

840841
if (!(file->flags & EVENT_FILE_FL_ENABLED)) {
841842
bool cmd = false, tgid = false;
842843

843-
/* Keep the event disabled, when going to SOFT_MODE. */
844+
/* Keep the event disabled, when going to soft mode. */
844845
if (soft_disable)
845846
set_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, &file->flags);
846847

@@ -1792,8 +1793,7 @@ event_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
17921793
!(flags & EVENT_FILE_FL_SOFT_DISABLED))
17931794
strcpy(buf, "1");
17941795

1795-
if (flags & EVENT_FILE_FL_SOFT_DISABLED ||
1796-
flags & EVENT_FILE_FL_SOFT_MODE)
1796+
if (atomic_read(&file->sm_ref) != 0)
17971797
strcat(buf, "*");
17981798

17991799
strcat(buf, "\n");
@@ -3267,43 +3267,120 @@ static void add_str_to_module(struct module *module, char *str)
32673267
list_add(&modstr->next, &module_strings);
32683268
}
32693269

3270+
#define ATTRIBUTE_STR "__attribute__("
3271+
#define ATTRIBUTE_STR_LEN (sizeof(ATTRIBUTE_STR) - 1)
3272+
3273+
/* Remove all __attribute__() from @type. Return allocated string or @type. */
3274+
static char *sanitize_field_type(const char *type)
3275+
{
3276+
char *attr, *tmp, *next, *ret = (char *)type;
3277+
int depth;
3278+
3279+
next = (char *)type;
3280+
while ((attr = strstr(next, ATTRIBUTE_STR))) {
3281+
/* Retry if "__attribute__(" is a part of another word. */
3282+
if (attr != next && !isspace(attr[-1])) {
3283+
next = attr + ATTRIBUTE_STR_LEN;
3284+
continue;
3285+
}
3286+
3287+
if (ret == type) {
3288+
ret = kstrdup(type, GFP_KERNEL);
3289+
if (WARN_ON_ONCE(!ret))
3290+
return NULL;
3291+
attr = ret + (attr - type);
3292+
}
3293+
3294+
/* the ATTRIBUTE_STR already has the first '(' */
3295+
depth = 1;
3296+
next = attr + ATTRIBUTE_STR_LEN;
3297+
do {
3298+
tmp = strpbrk(next, "()");
3299+
/* There is unbalanced parentheses */
3300+
if (WARN_ON_ONCE(!tmp)) {
3301+
kfree(ret);
3302+
return (char *)type;
3303+
}
3304+
3305+
if (*tmp == '(')
3306+
depth++;
3307+
else
3308+
depth--;
3309+
next = tmp + 1;
3310+
} while (depth > 0);
3311+
next = skip_spaces(next);
3312+
strcpy(attr, next);
3313+
next = attr;
3314+
}
3315+
return ret;
3316+
}
3317+
3318+
static char *find_replacable_eval(const char *type, const char *eval_string,
3319+
int len)
3320+
{
3321+
char *ptr;
3322+
3323+
if (!eval_string)
3324+
return NULL;
3325+
3326+
ptr = strchr(type, '[');
3327+
if (!ptr)
3328+
return NULL;
3329+
ptr++;
3330+
3331+
if (!isalpha(*ptr) && *ptr != '_')
3332+
return NULL;
3333+
3334+
if (strncmp(eval_string, ptr, len) != 0)
3335+
return NULL;
3336+
3337+
return ptr;
3338+
}
3339+
32703340
static void update_event_fields(struct trace_event_call *call,
32713341
struct trace_eval_map *map)
32723342
{
32733343
struct ftrace_event_field *field;
3344+
const char *eval_string = NULL;
32743345
struct list_head *head;
3346+
int len = 0;
32753347
char *ptr;
32763348
char *str;
3277-
int len = strlen(map->eval_string);
32783349

32793350
/* Dynamic events should never have field maps */
3280-
if (WARN_ON_ONCE(call->flags & TRACE_EVENT_FL_DYNAMIC))
3351+
if (call->flags & TRACE_EVENT_FL_DYNAMIC)
32813352
return;
32823353

3354+
if (map) {
3355+
eval_string = map->eval_string;
3356+
len = strlen(map->eval_string);
3357+
}
3358+
32833359
head = trace_get_fields(call);
32843360
list_for_each_entry(field, head, link) {
3285-
ptr = strchr(field->type, '[');
3286-
if (!ptr)
3287-
continue;
3288-
ptr++;
3289-
3290-
if (!isalpha(*ptr) && *ptr != '_')
3291-
continue;
3361+
str = sanitize_field_type(field->type);
3362+
if (!str)
3363+
return;
32923364

3293-
if (strncmp(map->eval_string, ptr, len) != 0)
3294-
continue;
3365+
ptr = find_replacable_eval(str, eval_string, len);
3366+
if (ptr) {
3367+
if (str == field->type) {
3368+
str = kstrdup(field->type, GFP_KERNEL);
3369+
if (WARN_ON_ONCE(!str))
3370+
return;
3371+
ptr = str + (ptr - field->type);
3372+
}
32953373

3296-
str = kstrdup(field->type, GFP_KERNEL);
3297-
if (WARN_ON_ONCE(!str))
3298-
return;
3299-
ptr = str + (ptr - field->type);
3300-
ptr = eval_replace(ptr, map, len);
3301-
/* enum/sizeof string smaller than value */
3302-
if (WARN_ON_ONCE(!ptr)) {
3303-
kfree(str);
3304-
continue;
3374+
ptr = eval_replace(ptr, map, len);
3375+
/* enum/sizeof string smaller than value */
3376+
if (WARN_ON_ONCE(!ptr)) {
3377+
kfree(str);
3378+
continue;
3379+
}
33053380
}
33063381

3382+
if (str == field->type)
3383+
continue;
33073384
/*
33083385
* If the event is part of a module, then we need to free the string
33093386
* when the module is removed. Otherwise, it will stay allocated
@@ -3313,14 +3390,18 @@ static void update_event_fields(struct trace_event_call *call,
33133390
add_str_to_module(call->module, str);
33143391

33153392
field->type = str;
3393+
if (field->filter_type == FILTER_OTHER)
3394+
field->filter_type = filter_assign_type(field->type);
33163395
}
33173396
}
33183397

3319-
void trace_event_eval_update(struct trace_eval_map **map, int len)
3398+
/* Update all events for replacing eval and sanitizing */
3399+
void trace_event_update_all(struct trace_eval_map **map, int len)
33203400
{
33213401
struct trace_event_call *call, *p;
33223402
const char *last_system = NULL;
33233403
bool first = false;
3404+
bool updated;
33243405
int last_i;
33253406
int i;
33263407

@@ -3333,6 +3414,7 @@ void trace_event_eval_update(struct trace_eval_map **map, int len)
33333414
last_system = call->class->system;
33343415
}
33353416

3417+
updated = false;
33363418
/*
33373419
* Since calls are grouped by systems, the likelihood that the
33383420
* next call in the iteration belongs to the same system as the
@@ -3352,8 +3434,12 @@ void trace_event_eval_update(struct trace_eval_map **map, int len)
33523434
}
33533435
update_event_printk(call, map[i]);
33543436
update_event_fields(call, map[i]);
3437+
updated = true;
33553438
}
33563439
}
3440+
/* If not updated yet, update field for sanitizing. */
3441+
if (!updated)
3442+
update_event_fields(call, NULL);
33573443
cond_resched();
33583444
}
33593445
up_write(&trace_event_sem);
@@ -3587,7 +3673,7 @@ static int probe_remove_event_call(struct trace_event_call *call)
35873673
continue;
35883674
/*
35893675
* We can't rely on ftrace_event_enable_disable(enable => 0)
3590-
* we are going to do, EVENT_FILE_FL_SOFT_MODE can suppress
3676+
* we are going to do, soft mode can suppress
35913677
* TRACE_REG_UNREGISTER.
35923678
*/
35933679
if (file->flags & EVENT_FILE_FL_ENABLED)
@@ -3698,7 +3784,7 @@ static void trace_module_remove_events(struct module *mod)
36983784
if (call->module == mod)
36993785
__trace_remove_event_call(call);
37003786
}
3701-
/* Check for any strings allocade for this module */
3787+
/* Check for any strings allocated for this module */
37023788
list_for_each_entry_safe(modstr, m, &module_strings, next) {
37033789
if (modstr->module != mod)
37043790
continue;
@@ -4002,7 +4088,7 @@ static int free_probe_data(void *data)
40024088

40034089
edata->ref--;
40044090
if (!edata->ref) {
4005-
/* Remove the SOFT_MODE flag */
4091+
/* Remove soft mode */
40064092
__ftrace_event_enable_disable(edata->file, 0, 1);
40074093
trace_event_put_ref(edata->file->event_call);
40084094
kfree(edata);

0 commit comments

Comments
 (0)