Skip to content

Commit 31b265b

Browse files
diandersrostedt
authored andcommitted
tracing: kdb: Fix ftdump to not sleep
As reported back in 2016-11 [1], the "ftdump" kdb command triggers a BUG for "sleeping function called from invalid context". kdb's "ftdump" command wants to call ring_buffer_read_prepare() in atomic context. A very simple solution for this is to add allocation flags to ring_buffer_read_prepare() so kdb can call it without triggering the allocation error. This patch does that. Note that in the original email thread about this, it was suggested that perhaps the solution for kdb was to either preallocate the buffer ahead of time or create our own iterator. I'm hoping that this alternative of adding allocation flags to ring_buffer_read_prepare() can be considered since it means I don't need to duplicate more of the core trace code into "trace_kdb.c" (for either creating my own iterator or re-preparing a ring allocator whose memory was already allocated). NOTE: another option for kdb is to actually figure out how to make it reuse the existing ftrace_dump() function and totally eliminate the duplication. This sounds very appealing and actually works (the "sr z" command can be seen to properly dump the ftrace buffer). The downside here is that ftrace_dump() fully consumes the trace buffer. Unless that is changed I'd rather not use it because it means "ftdump | grep xyz" won't be very useful to search the ftrace buffer since it will throw away the whole trace on the first grep. A future patch to dump only the last few lines of the buffer will also be hard to implement. [1] https://lkml.kernel.org/r/20161117191605.GA21459@google.com Link: http://lkml.kernel.org/r/20190308193205.213659-1-dianders@chromium.org Reported-by: Brian Norris <briannorris@chromium.org> Signed-off-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
1 parent cede666 commit 31b265b

File tree

4 files changed

+12
-7
lines changed

4 files changed

+12
-7
lines changed

include/linux/ring_buffer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts,
128128
unsigned long *lost_events);
129129

130130
struct ring_buffer_iter *
131-
ring_buffer_read_prepare(struct ring_buffer *buffer, int cpu);
131+
ring_buffer_read_prepare(struct ring_buffer *buffer, int cpu, gfp_t flags);
132132
void ring_buffer_read_prepare_sync(void);
133133
void ring_buffer_read_start(struct ring_buffer_iter *iter);
134134
void ring_buffer_read_finish(struct ring_buffer_iter *iter);

kernel/trace/ring_buffer.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4191,6 +4191,7 @@ EXPORT_SYMBOL_GPL(ring_buffer_consume);
41914191
* ring_buffer_read_prepare - Prepare for a non consuming read of the buffer
41924192
* @buffer: The ring buffer to read from
41934193
* @cpu: The cpu buffer to iterate over
4194+
* @flags: gfp flags to use for memory allocation
41944195
*
41954196
* This performs the initial preparations necessary to iterate
41964197
* through the buffer. Memory is allocated, buffer recording
@@ -4208,15 +4209,15 @@ EXPORT_SYMBOL_GPL(ring_buffer_consume);
42084209
* This overall must be paired with ring_buffer_read_finish.
42094210
*/
42104211
struct ring_buffer_iter *
4211-
ring_buffer_read_prepare(struct ring_buffer *buffer, int cpu)
4212+
ring_buffer_read_prepare(struct ring_buffer *buffer, int cpu, gfp_t flags)
42124213
{
42134214
struct ring_buffer_per_cpu *cpu_buffer;
42144215
struct ring_buffer_iter *iter;
42154216

42164217
if (!cpumask_test_cpu(cpu, buffer->cpumask))
42174218
return NULL;
42184219

4219-
iter = kmalloc(sizeof(*iter), GFP_KERNEL);
4220+
iter = kmalloc(sizeof(*iter), flags);
42204221
if (!iter)
42214222
return NULL;
42224223

kernel/trace/trace.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4077,7 +4077,8 @@ __tracing_open(struct inode *inode, struct file *file, bool snapshot)
40774077
if (iter->cpu_file == RING_BUFFER_ALL_CPUS) {
40784078
for_each_tracing_cpu(cpu) {
40794079
iter->buffer_iter[cpu] =
4080-
ring_buffer_read_prepare(iter->trace_buffer->buffer, cpu);
4080+
ring_buffer_read_prepare(iter->trace_buffer->buffer,
4081+
cpu, GFP_KERNEL);
40814082
}
40824083
ring_buffer_read_prepare_sync();
40834084
for_each_tracing_cpu(cpu) {
@@ -4087,7 +4088,8 @@ __tracing_open(struct inode *inode, struct file *file, bool snapshot)
40874088
} else {
40884089
cpu = iter->cpu_file;
40894090
iter->buffer_iter[cpu] =
4090-
ring_buffer_read_prepare(iter->trace_buffer->buffer, cpu);
4091+
ring_buffer_read_prepare(iter->trace_buffer->buffer,
4092+
cpu, GFP_KERNEL);
40914093
ring_buffer_read_prepare_sync();
40924094
ring_buffer_read_start(iter->buffer_iter[cpu]);
40934095
tracing_iter_reset(iter, cpu);

kernel/trace/trace_kdb.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,16 @@ static void ftrace_dump_buf(int skip_lines, long cpu_file)
5151
if (cpu_file == RING_BUFFER_ALL_CPUS) {
5252
for_each_tracing_cpu(cpu) {
5353
iter.buffer_iter[cpu] =
54-
ring_buffer_read_prepare(iter.trace_buffer->buffer, cpu);
54+
ring_buffer_read_prepare(iter.trace_buffer->buffer,
55+
cpu, GFP_ATOMIC);
5556
ring_buffer_read_start(iter.buffer_iter[cpu]);
5657
tracing_iter_reset(&iter, cpu);
5758
}
5859
} else {
5960
iter.cpu_file = cpu_file;
6061
iter.buffer_iter[cpu_file] =
61-
ring_buffer_read_prepare(iter.trace_buffer->buffer, cpu_file);
62+
ring_buffer_read_prepare(iter.trace_buffer->buffer,
63+
cpu_file, GFP_ATOMIC);
6264
ring_buffer_read_start(iter.buffer_iter[cpu_file]);
6365
tracing_iter_reset(&iter, cpu_file);
6466
}

0 commit comments

Comments
 (0)