Skip to content

Commit 99ddf22

Browse files
committed
Merge tag 'trace-v6.3-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull tracing fixes from Steven Rostedt: - Fix timerlat notification, as it was not triggering the notify to users when a new max latency was hit. - Do not trigger max latency if the tracing is off. When tracing is off, the ring buffer is not updated, it does not make sense to notify when there's a new max latency detected by the tracer, as why that latency happened is not available. The tracing logic still runs when the ring buffer is disabled, but it should not be triggering notifications. - Fix race on freeing the synthetic event "last_cmd" variable by adding a mutex around it. - Fix race between reader and writer of the ring buffer by adding memory barriers. When the writer is still on the reader page it must have its content visible on the buffer before it moves the commit index that the reader uses to know how much content is on the page. - Make get_lock_parent_ip() always inlined, as it uses _THIS_IP_ and _RET_IP_, which gets broken if it is not inlined. - Make __field(int, arr[5]) in a TRACE_EVENT() macro fail to build. The field formats of trace events are calculated by using sizeof(type) and other means by what is passed into the structure macros like __field(). The __field() macro is only meant for atom types like int, long, short, pointer, etc. It is not meant for arrays. The code will currently compile with arrays, but then the format produced will be inaccurate, and user space parsing tools will break. Two bugs have already been fixed, now add code that will make the kernel fail to build if another trace event includes this buggy field format. - Fix boot up snapshot code: Boot snapshots were triggering when not even asked for on the kernel command line. This was caused by two bugs: 1) It would trigger a snapshot on any instance if one was created from the kernel command line. 2) The error handling would only affect the top level instance. So the fact that a snapshot was done on a instance that didn't allocate a buffer triggered a warning written into the top level buffer, and worse yet, disabled the top level buffer. - Fix memory leak that was caused when an error was logged in a trace buffer instance, and then the buffer instance was removed. The allocated error log messages still needed to be freed. * tag 'trace-v6.3-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: tracing: Free error logs of tracing instances tracing: Fix ftrace_boot_snapshot command line logic tracing: Have tracing_snapshot_instance_cond() write errors to the appropriate instance tracing: Error if a trace event has an array for a __field() tracing/osnoise: Fix notify new tracing_max_latency tracing/timerlat: Notify new max thread latency ftrace: Mark get_lock_parent_ip() __always_inline ring-buffer: Fix race while reader and writer are on the same page tracing/synthetic: Fix races on freeing last_cmd
2 parents 76f598b + 3357c6e commit 99ddf22

File tree

6 files changed

+63
-24
lines changed

6 files changed

+63
-24
lines changed

include/linux/ftrace.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,7 @@ static inline void __ftrace_enabled_restore(int enabled)
980980
#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
981981
#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
982982

983-
static inline unsigned long get_lock_parent_ip(void)
983+
static __always_inline unsigned long get_lock_parent_ip(void)
984984
{
985985
unsigned long addr = CALLER_ADDR0;
986986

include/trace/stages/stage5_get_offsets.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,30 @@
99
#undef __entry
1010
#define __entry entry
1111

12+
/*
13+
* Fields should never declare an array: i.e. __field(int, arr[5])
14+
* If they do, it will cause issues in parsing and possibly corrupt the
15+
* events. To prevent that from happening, test the sizeof() a fictitious
16+
* type called "struct _test_no_array_##item" which will fail if "item"
17+
* contains array elements (like "arr[5]").
18+
*
19+
* If you hit this, use __array(int, arr, 5) instead.
20+
*/
1221
#undef __field
13-
#define __field(type, item)
22+
#define __field(type, item) \
23+
{ (void)sizeof(struct _test_no_array_##item *); }
1424

1525
#undef __field_ext
16-
#define __field_ext(type, item, filter_type)
26+
#define __field_ext(type, item, filter_type) \
27+
{ (void)sizeof(struct _test_no_array_##item *); }
1728

1829
#undef __field_struct
19-
#define __field_struct(type, item)
30+
#define __field_struct(type, item) \
31+
{ (void)sizeof(struct _test_no_array_##item *); }
2032

2133
#undef __field_struct_ext
22-
#define __field_struct_ext(type, item, filter_type)
34+
#define __field_struct_ext(type, item, filter_type) \
35+
{ (void)sizeof(struct _test_no_array_##item *); }
2336

2437
#undef __array
2538
#define __array(type, item, len)

kernel/trace/ring_buffer.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3098,6 +3098,10 @@ rb_set_commit_to_write(struct ring_buffer_per_cpu *cpu_buffer)
30983098
if (RB_WARN_ON(cpu_buffer,
30993099
rb_is_reader_page(cpu_buffer->tail_page)))
31003100
return;
3101+
/*
3102+
* No need for a memory barrier here, as the update
3103+
* of the tail_page did it for this page.
3104+
*/
31013105
local_set(&cpu_buffer->commit_page->page->commit,
31023106
rb_page_write(cpu_buffer->commit_page));
31033107
rb_inc_page(&cpu_buffer->commit_page);
@@ -3107,6 +3111,8 @@ rb_set_commit_to_write(struct ring_buffer_per_cpu *cpu_buffer)
31073111
while (rb_commit_index(cpu_buffer) !=
31083112
rb_page_write(cpu_buffer->commit_page)) {
31093113

3114+
/* Make sure the readers see the content of what is committed. */
3115+
smp_wmb();
31103116
local_set(&cpu_buffer->commit_page->page->commit,
31113117
rb_page_write(cpu_buffer->commit_page));
31123118
RB_WARN_ON(cpu_buffer,
@@ -4684,7 +4690,12 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer)
46844690

46854691
/*
46864692
* Make sure we see any padding after the write update
4687-
* (see rb_reset_tail())
4693+
* (see rb_reset_tail()).
4694+
*
4695+
* In addition, a writer may be writing on the reader page
4696+
* if the page has not been fully filled, so the read barrier
4697+
* is also needed to make sure we see the content of what is
4698+
* committed by the writer (see rb_set_commit_to_write()).
46884699
*/
46894700
smp_rmb();
46904701

kernel/trace/trace.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,22 +1149,22 @@ static void tracing_snapshot_instance_cond(struct trace_array *tr,
11491149
unsigned long flags;
11501150

11511151
if (in_nmi()) {
1152-
internal_trace_puts("*** SNAPSHOT CALLED FROM NMI CONTEXT ***\n");
1153-
internal_trace_puts("*** snapshot is being ignored ***\n");
1152+
trace_array_puts(tr, "*** SNAPSHOT CALLED FROM NMI CONTEXT ***\n");
1153+
trace_array_puts(tr, "*** snapshot is being ignored ***\n");
11541154
return;
11551155
}
11561156

11571157
if (!tr->allocated_snapshot) {
1158-
internal_trace_puts("*** SNAPSHOT NOT ALLOCATED ***\n");
1159-
internal_trace_puts("*** stopping trace here! ***\n");
1160-
tracing_off();
1158+
trace_array_puts(tr, "*** SNAPSHOT NOT ALLOCATED ***\n");
1159+
trace_array_puts(tr, "*** stopping trace here! ***\n");
1160+
tracer_tracing_off(tr);
11611161
return;
11621162
}
11631163

11641164
/* Note, snapshot can not be used when the tracer uses it */
11651165
if (tracer->use_max_tr) {
1166-
internal_trace_puts("*** LATENCY TRACER ACTIVE ***\n");
1167-
internal_trace_puts("*** Can not use snapshot (sorry) ***\n");
1166+
trace_array_puts(tr, "*** LATENCY TRACER ACTIVE ***\n");
1167+
trace_array_puts(tr, "*** Can not use snapshot (sorry) ***\n");
11681168
return;
11691169
}
11701170

@@ -9516,6 +9516,7 @@ static int __remove_instance(struct trace_array *tr)
95169516
tracefs_remove(tr->dir);
95179517
free_percpu(tr->last_func_repeats);
95189518
free_trace_buffers(tr);
9519+
clear_tracing_err_log(tr);
95199520

95209521
for (i = 0; i < tr->nr_topts; i++) {
95219522
kfree(tr->topts[i].topts);
@@ -10393,19 +10394,20 @@ __init static int tracer_alloc_buffers(void)
1039310394

1039410395
void __init ftrace_boot_snapshot(void)
1039510396
{
10397+
#ifdef CONFIG_TRACER_MAX_TRACE
1039610398
struct trace_array *tr;
1039710399

10398-
if (snapshot_at_boot) {
10399-
tracing_snapshot();
10400-
internal_trace_puts("** Boot snapshot taken **\n");
10401-
}
10400+
if (!snapshot_at_boot)
10401+
return;
1040210402

1040310403
list_for_each_entry(tr, &ftrace_trace_arrays, list) {
10404-
if (tr == &global_trace)
10404+
if (!tr->allocated_snapshot)
1040510405
continue;
10406-
trace_array_puts(tr, "** Boot snapshot taken **\n");
10406+
1040710407
tracing_snapshot_instance(tr);
10408+
trace_array_puts(tr, "** Boot snapshot taken **\n");
1040810409
}
10410+
#endif
1040910411
}
1041010412

1041110413
void __init early_trace_init(void)

kernel/trace/trace_events_synth.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,33 +44,44 @@ enum { ERRORS };
4444

4545
static const char *err_text[] = { ERRORS };
4646

47+
DEFINE_MUTEX(lastcmd_mutex);
4748
static char *last_cmd;
4849

4950
static int errpos(const char *str)
5051
{
52+
int ret = 0;
53+
54+
mutex_lock(&lastcmd_mutex);
5155
if (!str || !last_cmd)
52-
return 0;
56+
goto out;
5357

54-
return err_pos(last_cmd, str);
58+
ret = err_pos(last_cmd, str);
59+
out:
60+
mutex_unlock(&lastcmd_mutex);
61+
return ret;
5562
}
5663

5764
static void last_cmd_set(const char *str)
5865
{
5966
if (!str)
6067
return;
6168

69+
mutex_lock(&lastcmd_mutex);
6270
kfree(last_cmd);
63-
6471
last_cmd = kstrdup(str, GFP_KERNEL);
72+
mutex_unlock(&lastcmd_mutex);
6573
}
6674

6775
static void synth_err(u8 err_type, u16 err_pos)
6876
{
77+
mutex_lock(&lastcmd_mutex);
6978
if (!last_cmd)
70-
return;
79+
goto out;
7180

7281
tracing_log_err(NULL, "synthetic_events", last_cmd, err_text,
7382
err_type, err_pos);
83+
out:
84+
mutex_unlock(&lastcmd_mutex);
7485
}
7586

7687
static int create_synth_event(const char *raw_command);

kernel/trace/trace_osnoise.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1296,7 +1296,7 @@ static void notify_new_max_latency(u64 latency)
12961296
rcu_read_lock();
12971297
list_for_each_entry_rcu(inst, &osnoise_instances, list) {
12981298
tr = inst->tr;
1299-
if (tr->max_latency < latency) {
1299+
if (tracer_tracing_is_on(tr) && tr->max_latency < latency) {
13001300
tr->max_latency = latency;
13011301
latency_fsnotify(tr);
13021302
}
@@ -1738,6 +1738,8 @@ static int timerlat_main(void *data)
17381738

17391739
trace_timerlat_sample(&s);
17401740

1741+
notify_new_max_latency(diff);
1742+
17411743
timerlat_dump_stack(time_to_us(diff));
17421744

17431745
tlat->tracing_thread = false;

0 commit comments

Comments
 (0)