Skip to content

Commit 622a3ed

Browse files
committed
Merge tag 'trace-v6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull tracing fixes from Steven Rostedt: - Fix tp_printk command line option crashing the kernel With the code that can handle a buffer from a previous boot, the trace_check_vprintf() needed access to the delta of the address space used by the old buffer and the current buffer. To do so, the trace_array (tr) parameter was used. But when tp_printk is enabled on the kernel command line, no trace buffer is used and the trace event is sent directly to printk(). That meant the tr field of the iterator descriptor was NULL, and since tp_printk still uses trace_check_vprintf() it caused a NULL dereference. - Add ptrace.h include to x86 ftrace file for completeness - Fix rtla installation when done with out-of-tree build - Fix the help messages in rtla that were incorrect - Several fixes to fix races with the timerlat and hwlat code Several locking issues were discovered with the coordination between timerlat kthread creation and hotplug. As timerlat has callbacks from hotplug code to start kthreads when CPUs come online. There are also locking issues with grabbing the cpu_read_lock() and the locks within timerlat. * tag 'trace-v6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: tracing/hwlat: Fix a race during cpuhp processing tracing/timerlat: Fix a race during cpuhp processing tracing/timerlat: Drop interface_lock in stop_kthread() tracing/timerlat: Fix duplicated kthread creation due to CPU online/offline x86/ftrace: Include <asm/ptrace.h> rtla: Fix the help text in osnoise and timerlat top tools tools/rtla: Fix installation from out-of-tree build tracing: Fix trace_check_vprintf() when tp_printk is used
2 parents f6785e0 + 2a13ca2 commit 622a3ed

File tree

7 files changed

+34
-15
lines changed

7 files changed

+34
-15
lines changed

arch/x86/include/asm/ftrace.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#ifndef _ASM_X86_FTRACE_H
33
#define _ASM_X86_FTRACE_H
44

5+
#include <asm/ptrace.h>
6+
57
#ifdef CONFIG_FUNCTION_TRACER
68
#ifndef CC_USING_FENTRY
79
# error Compiler does not support fentry?

kernel/trace/trace.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3697,8 +3697,8 @@ static void test_can_verify(void)
36973697
void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
36983698
va_list ap)
36993699
{
3700-
long text_delta = iter->tr->text_delta;
3701-
long data_delta = iter->tr->data_delta;
3700+
long text_delta = 0;
3701+
long data_delta = 0;
37023702
const char *p = fmt;
37033703
const char *str;
37043704
bool good;
@@ -3710,6 +3710,17 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
37103710
if (static_branch_unlikely(&trace_no_verify))
37113711
goto print;
37123712

3713+
/*
3714+
* When the kernel is booted with the tp_printk command line
3715+
* parameter, trace events go directly through to printk().
3716+
* It also is checked by this function, but it does not
3717+
* have an associated trace_array (tr) for it.
3718+
*/
3719+
if (iter->tr) {
3720+
text_delta = iter->tr->text_delta;
3721+
data_delta = iter->tr->data_delta;
3722+
}
3723+
37133724
/* Don't bother checking when doing a ftrace_dump() */
37143725
if (iter->fmt == static_fmt_buf)
37153726
goto print;

kernel/trace/trace_hwlat.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,8 @@ static void hwlat_hotplug_workfn(struct work_struct *dummy)
520520
if (!hwlat_busy || hwlat_data.thread_mode != MODE_PER_CPU)
521521
goto out_unlock;
522522

523+
if (!cpu_online(cpu))
524+
goto out_unlock;
523525
if (!cpumask_test_cpu(cpu, tr->tracing_cpumask))
524526
goto out_unlock;
525527

kernel/trace/trace_osnoise.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1953,12 +1953,8 @@ static void stop_kthread(unsigned int cpu)
19531953
{
19541954
struct task_struct *kthread;
19551955

1956-
mutex_lock(&interface_lock);
1957-
kthread = per_cpu(per_cpu_osnoise_var, cpu).kthread;
1956+
kthread = xchg_relaxed(&(per_cpu(per_cpu_osnoise_var, cpu).kthread), NULL);
19581957
if (kthread) {
1959-
per_cpu(per_cpu_osnoise_var, cpu).kthread = NULL;
1960-
mutex_unlock(&interface_lock);
1961-
19621958
if (cpumask_test_and_clear_cpu(cpu, &kthread_cpumask) &&
19631959
!WARN_ON(!test_bit(OSN_WORKLOAD, &osnoise_options))) {
19641960
kthread_stop(kthread);
@@ -1972,7 +1968,6 @@ static void stop_kthread(unsigned int cpu)
19721968
put_task_struct(kthread);
19731969
}
19741970
} else {
1975-
mutex_unlock(&interface_lock);
19761971
/* if no workload, just return */
19771972
if (!test_bit(OSN_WORKLOAD, &osnoise_options)) {
19781973
/*
@@ -1994,8 +1989,12 @@ static void stop_per_cpu_kthreads(void)
19941989
{
19951990
int cpu;
19961991

1997-
for_each_possible_cpu(cpu)
1992+
cpus_read_lock();
1993+
1994+
for_each_online_cpu(cpu)
19981995
stop_kthread(cpu);
1996+
1997+
cpus_read_unlock();
19991998
}
20001999

20012000
/*
@@ -2007,6 +2006,10 @@ static int start_kthread(unsigned int cpu)
20072006
void *main = osnoise_main;
20082007
char comm[24];
20092008

2009+
/* Do not start a new thread if it is already running */
2010+
if (per_cpu(per_cpu_osnoise_var, cpu).kthread)
2011+
return 0;
2012+
20102013
if (timerlat_enabled()) {
20112014
snprintf(comm, 24, "timerlat/%d", cpu);
20122015
main = timerlat_main;
@@ -2061,11 +2064,10 @@ static int start_per_cpu_kthreads(void)
20612064
if (cpumask_test_and_clear_cpu(cpu, &kthread_cpumask)) {
20622065
struct task_struct *kthread;
20632066

2064-
kthread = per_cpu(per_cpu_osnoise_var, cpu).kthread;
2067+
kthread = xchg_relaxed(&(per_cpu(per_cpu_osnoise_var, cpu).kthread), NULL);
20652068
if (!WARN_ON(!kthread))
20662069
kthread_stop(kthread);
20672070
}
2068-
per_cpu(per_cpu_osnoise_var, cpu).kthread = NULL;
20692071
}
20702072

20712073
for_each_cpu(cpu, current_mask) {
@@ -2095,6 +2097,8 @@ static void osnoise_hotplug_workfn(struct work_struct *dummy)
20952097
mutex_lock(&interface_lock);
20962098
cpus_read_lock();
20972099

2100+
if (!cpu_online(cpu))
2101+
goto out_unlock;
20982102
if (!cpumask_test_cpu(cpu, &osnoise_cpumask))
20992103
goto out_unlock;
21002104

tools/tracing/rtla/Makefile.rtla

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ BINDIR := /usr/bin
3838
.PHONY: install
3939
install: doc_install
4040
@$(MKDIR) -p $(DESTDIR)$(BINDIR)
41-
$(call QUIET_INSTALL,rtla)$(INSTALL) rtla -m 755 $(DESTDIR)$(BINDIR)
41+
$(call QUIET_INSTALL,rtla)$(INSTALL) $(RTLA) -m 755 $(DESTDIR)$(BINDIR)
4242
@$(STRIP) $(DESTDIR)$(BINDIR)/rtla
4343
@test ! -f $(DESTDIR)$(BINDIR)/osnoise || $(RM) $(DESTDIR)$(BINDIR)/osnoise
4444
@$(LN) rtla $(DESTDIR)$(BINDIR)/osnoise

tools/tracing/rtla/src/osnoise_top.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv)
442442
case 'd':
443443
params->duration = parse_seconds_duration(optarg);
444444
if (!params->duration)
445-
osnoise_top_usage(params, "Invalid -D duration\n");
445+
osnoise_top_usage(params, "Invalid -d duration\n");
446446
break;
447447
case 'e':
448448
tevent = trace_event_alloc(optarg);

tools/tracing/rtla/src/timerlat_top.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ static void timerlat_top_usage(char *usage)
459459
" -c/--cpus cpus: run the tracer only on the given cpus",
460460
" -H/--house-keeping cpus: run rtla control threads only on the given cpus",
461461
" -C/--cgroup[=cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited",
462-
" -d/--duration time[m|h|d]: duration of the session in seconds",
462+
" -d/--duration time[s|m|h|d]: duration of the session",
463463
" -D/--debug: print debug info",
464464
" --dump-tasks: prints the task running on all CPUs if stop conditions are met (depends on !--no-aa)",
465465
" -t/--trace[file]: save the stopped trace to [file|timerlat_trace.txt]",
@@ -613,7 +613,7 @@ static struct timerlat_top_params
613613
case 'd':
614614
params->duration = parse_seconds_duration(optarg);
615615
if (!params->duration)
616-
timerlat_top_usage("Invalid -D duration\n");
616+
timerlat_top_usage("Invalid -d duration\n");
617617
break;
618618
case 'e':
619619
tevent = trace_event_alloc(optarg);

0 commit comments

Comments
 (0)