Commit 622a3ed1 authored by Linus Torvalds's avatar Linus Torvalds

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
parents f6785e0c 2a13ca2e
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#ifndef _ASM_X86_FTRACE_H #ifndef _ASM_X86_FTRACE_H
#define _ASM_X86_FTRACE_H #define _ASM_X86_FTRACE_H
#include <asm/ptrace.h>
#ifdef CONFIG_FUNCTION_TRACER #ifdef CONFIG_FUNCTION_TRACER
#ifndef CC_USING_FENTRY #ifndef CC_USING_FENTRY
# error Compiler does not support fentry? # error Compiler does not support fentry?
......
...@@ -3697,8 +3697,8 @@ static void test_can_verify(void) ...@@ -3697,8 +3697,8 @@ static void test_can_verify(void)
void trace_check_vprintf(struct trace_iterator *iter, const char *fmt, void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
va_list ap) va_list ap)
{ {
long text_delta = iter->tr->text_delta; long text_delta = 0;
long data_delta = iter->tr->data_delta; long data_delta = 0;
const char *p = fmt; const char *p = fmt;
const char *str; const char *str;
bool good; bool good;
...@@ -3710,6 +3710,17 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt, ...@@ -3710,6 +3710,17 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
if (static_branch_unlikely(&trace_no_verify)) if (static_branch_unlikely(&trace_no_verify))
goto print; goto print;
/*
* When the kernel is booted with the tp_printk command line
* parameter, trace events go directly through to printk().
* It also is checked by this function, but it does not
* have an associated trace_array (tr) for it.
*/
if (iter->tr) {
text_delta = iter->tr->text_delta;
data_delta = iter->tr->data_delta;
}
/* Don't bother checking when doing a ftrace_dump() */ /* Don't bother checking when doing a ftrace_dump() */
if (iter->fmt == static_fmt_buf) if (iter->fmt == static_fmt_buf)
goto print; goto print;
......
...@@ -520,6 +520,8 @@ static void hwlat_hotplug_workfn(struct work_struct *dummy) ...@@ -520,6 +520,8 @@ static void hwlat_hotplug_workfn(struct work_struct *dummy)
if (!hwlat_busy || hwlat_data.thread_mode != MODE_PER_CPU) if (!hwlat_busy || hwlat_data.thread_mode != MODE_PER_CPU)
goto out_unlock; goto out_unlock;
if (!cpu_online(cpu))
goto out_unlock;
if (!cpumask_test_cpu(cpu, tr->tracing_cpumask)) if (!cpumask_test_cpu(cpu, tr->tracing_cpumask))
goto out_unlock; goto out_unlock;
......
...@@ -1953,12 +1953,8 @@ static void stop_kthread(unsigned int cpu) ...@@ -1953,12 +1953,8 @@ static void stop_kthread(unsigned int cpu)
{ {
struct task_struct *kthread; struct task_struct *kthread;
mutex_lock(&interface_lock); kthread = xchg_relaxed(&(per_cpu(per_cpu_osnoise_var, cpu).kthread), NULL);
kthread = per_cpu(per_cpu_osnoise_var, cpu).kthread;
if (kthread) { if (kthread) {
per_cpu(per_cpu_osnoise_var, cpu).kthread = NULL;
mutex_unlock(&interface_lock);
if (cpumask_test_and_clear_cpu(cpu, &kthread_cpumask) && if (cpumask_test_and_clear_cpu(cpu, &kthread_cpumask) &&
!WARN_ON(!test_bit(OSN_WORKLOAD, &osnoise_options))) { !WARN_ON(!test_bit(OSN_WORKLOAD, &osnoise_options))) {
kthread_stop(kthread); kthread_stop(kthread);
...@@ -1972,7 +1968,6 @@ static void stop_kthread(unsigned int cpu) ...@@ -1972,7 +1968,6 @@ static void stop_kthread(unsigned int cpu)
put_task_struct(kthread); put_task_struct(kthread);
} }
} else { } else {
mutex_unlock(&interface_lock);
/* if no workload, just return */ /* if no workload, just return */
if (!test_bit(OSN_WORKLOAD, &osnoise_options)) { if (!test_bit(OSN_WORKLOAD, &osnoise_options)) {
/* /*
...@@ -1994,8 +1989,12 @@ static void stop_per_cpu_kthreads(void) ...@@ -1994,8 +1989,12 @@ static void stop_per_cpu_kthreads(void)
{ {
int cpu; int cpu;
for_each_possible_cpu(cpu) cpus_read_lock();
for_each_online_cpu(cpu)
stop_kthread(cpu); stop_kthread(cpu);
cpus_read_unlock();
} }
/* /*
...@@ -2007,6 +2006,10 @@ static int start_kthread(unsigned int cpu) ...@@ -2007,6 +2006,10 @@ static int start_kthread(unsigned int cpu)
void *main = osnoise_main; void *main = osnoise_main;
char comm[24]; char comm[24];
/* Do not start a new thread if it is already running */
if (per_cpu(per_cpu_osnoise_var, cpu).kthread)
return 0;
if (timerlat_enabled()) { if (timerlat_enabled()) {
snprintf(comm, 24, "timerlat/%d", cpu); snprintf(comm, 24, "timerlat/%d", cpu);
main = timerlat_main; main = timerlat_main;
...@@ -2061,11 +2064,10 @@ static int start_per_cpu_kthreads(void) ...@@ -2061,11 +2064,10 @@ static int start_per_cpu_kthreads(void)
if (cpumask_test_and_clear_cpu(cpu, &kthread_cpumask)) { if (cpumask_test_and_clear_cpu(cpu, &kthread_cpumask)) {
struct task_struct *kthread; struct task_struct *kthread;
kthread = per_cpu(per_cpu_osnoise_var, cpu).kthread; kthread = xchg_relaxed(&(per_cpu(per_cpu_osnoise_var, cpu).kthread), NULL);
if (!WARN_ON(!kthread)) if (!WARN_ON(!kthread))
kthread_stop(kthread); kthread_stop(kthread);
} }
per_cpu(per_cpu_osnoise_var, cpu).kthread = NULL;
} }
for_each_cpu(cpu, current_mask) { for_each_cpu(cpu, current_mask) {
...@@ -2095,6 +2097,8 @@ static void osnoise_hotplug_workfn(struct work_struct *dummy) ...@@ -2095,6 +2097,8 @@ static void osnoise_hotplug_workfn(struct work_struct *dummy)
mutex_lock(&interface_lock); mutex_lock(&interface_lock);
cpus_read_lock(); cpus_read_lock();
if (!cpu_online(cpu))
goto out_unlock;
if (!cpumask_test_cpu(cpu, &osnoise_cpumask)) if (!cpumask_test_cpu(cpu, &osnoise_cpumask))
goto out_unlock; goto out_unlock;
......
...@@ -38,7 +38,7 @@ BINDIR := /usr/bin ...@@ -38,7 +38,7 @@ BINDIR := /usr/bin
.PHONY: install .PHONY: install
install: doc_install install: doc_install
@$(MKDIR) -p $(DESTDIR)$(BINDIR) @$(MKDIR) -p $(DESTDIR)$(BINDIR)
$(call QUIET_INSTALL,rtla)$(INSTALL) rtla -m 755 $(DESTDIR)$(BINDIR) $(call QUIET_INSTALL,rtla)$(INSTALL) $(RTLA) -m 755 $(DESTDIR)$(BINDIR)
@$(STRIP) $(DESTDIR)$(BINDIR)/rtla @$(STRIP) $(DESTDIR)$(BINDIR)/rtla
@test ! -f $(DESTDIR)$(BINDIR)/osnoise || $(RM) $(DESTDIR)$(BINDIR)/osnoise @test ! -f $(DESTDIR)$(BINDIR)/osnoise || $(RM) $(DESTDIR)$(BINDIR)/osnoise
@$(LN) rtla $(DESTDIR)$(BINDIR)/osnoise @$(LN) rtla $(DESTDIR)$(BINDIR)/osnoise
......
...@@ -442,7 +442,7 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv) ...@@ -442,7 +442,7 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv)
case 'd': case 'd':
params->duration = parse_seconds_duration(optarg); params->duration = parse_seconds_duration(optarg);
if (!params->duration) if (!params->duration)
osnoise_top_usage(params, "Invalid -D duration\n"); osnoise_top_usage(params, "Invalid -d duration\n");
break; break;
case 'e': case 'e':
tevent = trace_event_alloc(optarg); tevent = trace_event_alloc(optarg);
......
...@@ -459,7 +459,7 @@ static void timerlat_top_usage(char *usage) ...@@ -459,7 +459,7 @@ static void timerlat_top_usage(char *usage)
" -c/--cpus cpus: run the tracer only on the given cpus", " -c/--cpus cpus: run the tracer only on the given cpus",
" -H/--house-keeping cpus: run rtla control threads only on the given cpus", " -H/--house-keeping cpus: run rtla control threads only on the given cpus",
" -C/--cgroup[=cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited", " -C/--cgroup[=cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited",
" -d/--duration time[m|h|d]: duration of the session in seconds", " -d/--duration time[s|m|h|d]: duration of the session",
" -D/--debug: print debug info", " -D/--debug: print debug info",
" --dump-tasks: prints the task running on all CPUs if stop conditions are met (depends on !--no-aa)", " --dump-tasks: prints the task running on all CPUs if stop conditions are met (depends on !--no-aa)",
" -t/--trace[file]: save the stopped trace to [file|timerlat_trace.txt]", " -t/--trace[file]: save the stopped trace to [file|timerlat_trace.txt]",
...@@ -613,7 +613,7 @@ static struct timerlat_top_params ...@@ -613,7 +613,7 @@ static struct timerlat_top_params
case 'd': case 'd':
params->duration = parse_seconds_duration(optarg); params->duration = parse_seconds_duration(optarg);
if (!params->duration) if (!params->duration)
timerlat_top_usage("Invalid -D duration\n"); timerlat_top_usage("Invalid -d duration\n");
break; break;
case 'e': case 'e':
tevent = trace_event_alloc(optarg); tevent = trace_event_alloc(optarg);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment