Skip to content

Commit 788fa4b

Browse files
committed
tracing: Add guard(ring_buffer_nest)
Some calls to the tracing ring buffer can happen when the ring buffer is already being written to by the same context (for example, a trace_printk() in between a ring_buffer_lock_reserve() and a ring_buffer_unlock_commit()). In order to not trigger the recursion detection, these functions use ring_buffer_nest_start() and ring_buffer_nest_end(). Create a guard() for these functions so that their use cases can be simplified and not need to use goto for the release. Cc: Masami Hiramatsu <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Mathieu Desnoyers <[email protected]> Cc: Andrew Morton <[email protected]> Link: https://lore.kernel.org/[email protected] Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent c89504a commit 788fa4b

File tree

3 files changed

+34
-44
lines changed

3 files changed

+34
-44
lines changed

include/linux/ring_buffer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ int ring_buffer_write(struct trace_buffer *buffer,
144144
void ring_buffer_nest_start(struct trace_buffer *buffer);
145145
void ring_buffer_nest_end(struct trace_buffer *buffer);
146146

147+
DEFINE_GUARD(ring_buffer_nest, struct trace_buffer *,
148+
ring_buffer_nest_start(_T), ring_buffer_nest_end(_T))
149+
147150
struct ring_buffer_event *
148151
ring_buffer_peek(struct trace_buffer *buffer, int cpu, u64 *ts,
149152
unsigned long *lost_events);

kernel/trace/trace.c

Lines changed: 29 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,13 +1160,11 @@ int __trace_array_puts(struct trace_array *tr, unsigned long ip,
11601160

11611161
trace_ctx = tracing_gen_ctx();
11621162
buffer = tr->array_buffer.buffer;
1163-
ring_buffer_nest_start(buffer);
1163+
guard(ring_buffer_nest)(buffer);
11641164
event = __trace_buffer_lock_reserve(buffer, TRACE_PRINT, alloc,
11651165
trace_ctx);
1166-
if (!event) {
1167-
size = 0;
1168-
goto out;
1169-
}
1166+
if (!event)
1167+
return 0;
11701168

11711169
entry = ring_buffer_event_data(event);
11721170
entry->ip = ip;
@@ -1182,8 +1180,6 @@ int __trace_array_puts(struct trace_array *tr, unsigned long ip,
11821180

11831181
__buffer_unlock_commit(buffer, event);
11841182
ftrace_trace_stack(tr, buffer, trace_ctx, 4, NULL);
1185-
out:
1186-
ring_buffer_nest_end(buffer);
11871183
return size;
11881184
}
11891185
EXPORT_SYMBOL_GPL(__trace_array_puts);
@@ -1213,7 +1209,6 @@ int __trace_bputs(unsigned long ip, const char *str)
12131209
struct bputs_entry *entry;
12141210
unsigned int trace_ctx;
12151211
int size = sizeof(struct bputs_entry);
1216-
int ret = 0;
12171212

12181213
if (!printk_binsafe(tr))
12191214
return __trace_puts(ip, str, strlen(str));
@@ -1227,11 +1222,11 @@ int __trace_bputs(unsigned long ip, const char *str)
12271222
trace_ctx = tracing_gen_ctx();
12281223
buffer = tr->array_buffer.buffer;
12291224

1230-
ring_buffer_nest_start(buffer);
1225+
guard(ring_buffer_nest)(buffer);
12311226
event = __trace_buffer_lock_reserve(buffer, TRACE_BPUTS, size,
12321227
trace_ctx);
12331228
if (!event)
1234-
goto out;
1229+
return 0;
12351230

12361231
entry = ring_buffer_event_data(event);
12371232
entry->ip = ip;
@@ -1240,10 +1235,7 @@ int __trace_bputs(unsigned long ip, const char *str)
12401235
__buffer_unlock_commit(buffer, event);
12411236
ftrace_trace_stack(tr, buffer, trace_ctx, 4, NULL);
12421237

1243-
ret = 1;
1244-
out:
1245-
ring_buffer_nest_end(buffer);
1246-
return ret;
1238+
return 1;
12471239
}
12481240
EXPORT_SYMBOL_GPL(__trace_bputs);
12491241

@@ -3397,21 +3389,19 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
33973389

33983390
size = sizeof(*entry) + sizeof(u32) * len;
33993391
buffer = tr->array_buffer.buffer;
3400-
ring_buffer_nest_start(buffer);
3401-
event = __trace_buffer_lock_reserve(buffer, TRACE_BPRINT, size,
3402-
trace_ctx);
3403-
if (!event)
3404-
goto out;
3405-
entry = ring_buffer_event_data(event);
3406-
entry->ip = ip;
3407-
entry->fmt = fmt;
3408-
3409-
memcpy(entry->buf, tbuffer, sizeof(u32) * len);
3410-
__buffer_unlock_commit(buffer, event);
3411-
ftrace_trace_stack(tr, buffer, trace_ctx, 6, NULL);
3392+
scoped_guard(ring_buffer_nest, buffer) {
3393+
event = __trace_buffer_lock_reserve(buffer, TRACE_BPRINT, size,
3394+
trace_ctx);
3395+
if (!event)
3396+
goto out_put;
3397+
entry = ring_buffer_event_data(event);
3398+
entry->ip = ip;
3399+
entry->fmt = fmt;
34123400

3413-
out:
3414-
ring_buffer_nest_end(buffer);
3401+
memcpy(entry->buf, tbuffer, sizeof(u32) * len);
3402+
__buffer_unlock_commit(buffer, event);
3403+
ftrace_trace_stack(tr, buffer, trace_ctx, 6, NULL);
3404+
}
34153405
out_put:
34163406
put_trace_buf();
34173407

@@ -3452,20 +3442,19 @@ int __trace_array_vprintk(struct trace_buffer *buffer,
34523442
len = vscnprintf(tbuffer, TRACE_BUF_SIZE, fmt, args);
34533443

34543444
size = sizeof(*entry) + len + 1;
3455-
ring_buffer_nest_start(buffer);
3456-
event = __trace_buffer_lock_reserve(buffer, TRACE_PRINT, size,
3457-
trace_ctx);
3458-
if (!event)
3459-
goto out;
3460-
entry = ring_buffer_event_data(event);
3461-
entry->ip = ip;
3462-
3463-
memcpy(&entry->buf, tbuffer, len + 1);
3464-
__buffer_unlock_commit(buffer, event);
3465-
ftrace_trace_stack(printk_trace, buffer, trace_ctx, 6, NULL);
3445+
scoped_guard(ring_buffer_nest, buffer) {
3446+
event = __trace_buffer_lock_reserve(buffer, TRACE_PRINT, size,
3447+
trace_ctx);
3448+
if (!event)
3449+
goto out;
3450+
entry = ring_buffer_event_data(event);
3451+
entry->ip = ip;
34663452

3453+
memcpy(&entry->buf, tbuffer, len + 1);
3454+
__buffer_unlock_commit(buffer, event);
3455+
ftrace_trace_stack(printk_trace, buffer, trace_ctx, 6, NULL);
3456+
}
34673457
out:
3468-
ring_buffer_nest_end(buffer);
34693458
put_trace_buf();
34703459

34713460
out_nobuffer:

kernel/trace/trace_events_synth.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -536,12 +536,12 @@ static notrace void trace_event_raw_event_synth(void *__data,
536536
* is being performed within another event.
537537
*/
538538
buffer = trace_file->tr->array_buffer.buffer;
539-
ring_buffer_nest_start(buffer);
539+
guard(ring_buffer_nest)(buffer);
540540

541541
entry = trace_event_buffer_reserve(&fbuffer, trace_file,
542542
sizeof(*entry) + fields_size);
543543
if (!entry)
544-
goto out;
544+
return;
545545

546546
for (i = 0, n_u64 = 0; i < event->n_fields; i++) {
547547
val_idx = var_ref_idx[i];
@@ -584,8 +584,6 @@ static notrace void trace_event_raw_event_synth(void *__data,
584584
}
585585

586586
trace_event_buffer_commit(&fbuffer);
587-
out:
588-
ring_buffer_nest_end(buffer);
589587
}
590588

591589
static void free_synth_event_print_fmt(struct trace_event_call *call)

0 commit comments

Comments
 (0)