Skip to content

Commit 41cbc01

Browse files
committed
Merge tag 'trace-v3.20' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull tracing updates from Steven Rostedt: "The updates included in this pull request for ftrace are: o Several clean ups to the code One such clean up was to convert to 64 bit time keeping, in the ring buffer benchmark code. o Adding of __print_array() helper macro for TRACE_EVENT() o Updating the sample/trace_events/ to add samples of different ways to make trace events. Lots of features have been added since the sample code was made, and these features are mostly unknown. Developers have been making their own hacks to do things that are already available. o Performance improvements. Most notably, I found a performance bug where a waiter that is waiting for a full page from the ring buffer will see that a full page is not available, and go to sleep. The sched event caused by it going to sleep would cause it to wake up again. It would see that there was still not a full page, and go back to sleep again, and that would wake it up again, until finally it would see a full page. This change has been marked for stable. Other improvements include removing global locks from fast paths" * tag 'trace-v3.20' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: ring-buffer: Do not wake up a splice waiter when page is not full tracing: Fix unmapping loop in tracing_mark_write tracing: Add samples of DECLARE_EVENT_CLASS() and DEFINE_EVENT() tracing: Add TRACE_EVENT_FN example tracing: Add TRACE_EVENT_CONDITION sample tracing: Update the TRACE_EVENT fields available in the sample code tracing: Separate out initializing top level dir from instances tracing: Make tracing_init_dentry_tr() static trace: Use 64-bit timekeeping tracing: Add array printing helper tracing: Remove newline from trace_printk warning banner tracing: Use IS_ERR() check for return value of tracing_init_dentry() tracing: Remove unneeded includes of debugfs.h and fs.h tracing: Remove taking of trace_types_lock in pipe files tracing: Add ref count to tracer for when they are being read by pipe
2 parents 12df428 + 1e0d671 commit 41cbc01

23 files changed

+582
-164
lines changed

include/linux/ftrace_event.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ const char *ftrace_print_bitmask_seq(struct trace_seq *p, void *bitmask_ptr,
4444
const char *ftrace_print_hex_seq(struct trace_seq *p,
4545
const unsigned char *buf, int len);
4646

47+
const char *ftrace_print_array_seq(struct trace_seq *p,
48+
const void *buf, int buf_len,
49+
size_t el_size);
50+
4751
struct trace_iterator;
4852
struct trace_event;
4953

include/trace/ftrace.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,14 @@
263263
#undef __print_hex
264264
#define __print_hex(buf, buf_len) ftrace_print_hex_seq(p, buf, buf_len)
265265

266+
#undef __print_array
267+
#define __print_array(array, count, el_size) \
268+
({ \
269+
BUILD_BUG_ON(el_size != 1 && el_size != 2 && \
270+
el_size != 4 && el_size != 8); \
271+
ftrace_print_array_seq(p, array, count, el_size); \
272+
})
273+
266274
#undef DECLARE_EVENT_CLASS
267275
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
268276
static notrace enum print_line_t \
@@ -674,6 +682,7 @@ static inline void ftrace_test_probe_##call(void) \
674682
#undef __get_dynamic_array_len
675683
#undef __get_str
676684
#undef __get_bitmask
685+
#undef __print_array
677686

678687
#undef TP_printk
679688
#define TP_printk(fmt, args...) "\"" fmt "\", " __stringify(args)

kernel/trace/ftrace.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5456,7 +5456,7 @@ static __init int ftrace_init_debugfs(void)
54565456
struct dentry *d_tracer;
54575457

54585458
d_tracer = tracing_init_dentry();
5459-
if (!d_tracer)
5459+
if (IS_ERR(d_tracer))
54605460
return 0;
54615461

54625462
ftrace_init_dyn_debugfs(d_tracer);

kernel/trace/ring_buffer.c

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#include <linux/trace_seq.h>
1010
#include <linux/spinlock.h>
1111
#include <linux/irq_work.h>
12-
#include <linux/debugfs.h>
1312
#include <linux/uaccess.h>
1413
#include <linux/hardirq.h>
1514
#include <linux/kthread.h> /* for self test */
@@ -23,7 +22,6 @@
2322
#include <linux/hash.h>
2423
#include <linux/list.h>
2524
#include <linux/cpu.h>
26-
#include <linux/fs.h>
2725

2826
#include <asm/local.h>
2927

@@ -447,7 +445,10 @@ int ring_buffer_print_page_header(struct trace_seq *s)
447445
struct rb_irq_work {
448446
struct irq_work work;
449447
wait_queue_head_t waiters;
448+
wait_queue_head_t full_waiters;
450449
bool waiters_pending;
450+
bool full_waiters_pending;
451+
bool wakeup_full;
451452
};
452453

453454
/*
@@ -529,6 +530,10 @@ static void rb_wake_up_waiters(struct irq_work *work)
529530
struct rb_irq_work *rbwork = container_of(work, struct rb_irq_work, work);
530531

531532
wake_up_all(&rbwork->waiters);
533+
if (rbwork->wakeup_full) {
534+
rbwork->wakeup_full = false;
535+
wake_up_all(&rbwork->full_waiters);
536+
}
532537
}
533538

534539
/**
@@ -553,9 +558,11 @@ int ring_buffer_wait(struct ring_buffer *buffer, int cpu, bool full)
553558
* data in any cpu buffer, or a specific buffer, put the
554559
* caller on the appropriate wait queue.
555560
*/
556-
if (cpu == RING_BUFFER_ALL_CPUS)
561+
if (cpu == RING_BUFFER_ALL_CPUS) {
557562
work = &buffer->irq_work;
558-
else {
563+
/* Full only makes sense on per cpu reads */
564+
full = false;
565+
} else {
559566
if (!cpumask_test_cpu(cpu, buffer->cpumask))
560567
return -ENODEV;
561568
cpu_buffer = buffer->buffers[cpu];
@@ -564,7 +571,10 @@ int ring_buffer_wait(struct ring_buffer *buffer, int cpu, bool full)
564571

565572

566573
while (true) {
567-
prepare_to_wait(&work->waiters, &wait, TASK_INTERRUPTIBLE);
574+
if (full)
575+
prepare_to_wait(&work->full_waiters, &wait, TASK_INTERRUPTIBLE);
576+
else
577+
prepare_to_wait(&work->waiters, &wait, TASK_INTERRUPTIBLE);
568578

569579
/*
570580
* The events can happen in critical sections where
@@ -586,7 +596,10 @@ int ring_buffer_wait(struct ring_buffer *buffer, int cpu, bool full)
586596
* that is necessary is that the wake up happens after
587597
* a task has been queued. It's OK for spurious wake ups.
588598
*/
589-
work->waiters_pending = true;
599+
if (full)
600+
work->full_waiters_pending = true;
601+
else
602+
work->waiters_pending = true;
590603

591604
if (signal_pending(current)) {
592605
ret = -EINTR;
@@ -615,7 +628,10 @@ int ring_buffer_wait(struct ring_buffer *buffer, int cpu, bool full)
615628
schedule();
616629
}
617630

618-
finish_wait(&work->waiters, &wait);
631+
if (full)
632+
finish_wait(&work->full_waiters, &wait);
633+
else
634+
finish_wait(&work->waiters, &wait);
619635

620636
return ret;
621637
}
@@ -1230,6 +1246,7 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int nr_pages, int cpu)
12301246
init_completion(&cpu_buffer->update_done);
12311247
init_irq_work(&cpu_buffer->irq_work.work, rb_wake_up_waiters);
12321248
init_waitqueue_head(&cpu_buffer->irq_work.waiters);
1249+
init_waitqueue_head(&cpu_buffer->irq_work.full_waiters);
12331250

12341251
bpage = kzalloc_node(ALIGN(sizeof(*bpage), cache_line_size()),
12351252
GFP_KERNEL, cpu_to_node(cpu));
@@ -2801,6 +2818,8 @@ static void rb_commit(struct ring_buffer_per_cpu *cpu_buffer,
28012818
static __always_inline void
28022819
rb_wakeups(struct ring_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer)
28032820
{
2821+
bool pagebusy;
2822+
28042823
if (buffer->irq_work.waiters_pending) {
28052824
buffer->irq_work.waiters_pending = false;
28062825
/* irq_work_queue() supplies it's own memory barriers */
@@ -2812,6 +2831,15 @@ rb_wakeups(struct ring_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer)
28122831
/* irq_work_queue() supplies it's own memory barriers */
28132832
irq_work_queue(&cpu_buffer->irq_work.work);
28142833
}
2834+
2835+
pagebusy = cpu_buffer->reader_page == cpu_buffer->commit_page;
2836+
2837+
if (!pagebusy && cpu_buffer->irq_work.full_waiters_pending) {
2838+
cpu_buffer->irq_work.wakeup_full = true;
2839+
cpu_buffer->irq_work.full_waiters_pending = false;
2840+
/* irq_work_queue() supplies it's own memory barriers */
2841+
irq_work_queue(&cpu_buffer->irq_work.work);
2842+
}
28152843
}
28162844

28172845
/**

kernel/trace/ring_buffer_benchmark.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include <linux/completion.h>
88
#include <linux/kthread.h>
99
#include <linux/module.h>
10-
#include <linux/time.h>
10+
#include <linux/ktime.h>
1111
#include <asm/local.h>
1212

1313
struct rb_page {
@@ -17,7 +17,7 @@ struct rb_page {
1717
};
1818

1919
/* run time and sleep time in seconds */
20-
#define RUN_TIME 10
20+
#define RUN_TIME 10ULL
2121
#define SLEEP_TIME 10
2222

2323
/* number of events for writer to wake up the reader */
@@ -212,8 +212,7 @@ static void ring_buffer_consumer(void)
212212

213213
static void ring_buffer_producer(void)
214214
{
215-
struct timeval start_tv;
216-
struct timeval end_tv;
215+
ktime_t start_time, end_time, timeout;
217216
unsigned long long time;
218217
unsigned long long entries;
219218
unsigned long long overruns;
@@ -227,7 +226,8 @@ static void ring_buffer_producer(void)
227226
* make the system stall)
228227
*/
229228
trace_printk("Starting ring buffer hammer\n");
230-
do_gettimeofday(&start_tv);
229+
start_time = ktime_get();
230+
timeout = ktime_add_ns(start_time, RUN_TIME * NSEC_PER_SEC);
231231
do {
232232
struct ring_buffer_event *event;
233233
int *entry;
@@ -244,7 +244,7 @@ static void ring_buffer_producer(void)
244244
ring_buffer_unlock_commit(buffer, event);
245245
}
246246
}
247-
do_gettimeofday(&end_tv);
247+
end_time = ktime_get();
248248

249249
cnt++;
250250
if (consumer && !(cnt % wakeup_interval))
@@ -264,7 +264,7 @@ static void ring_buffer_producer(void)
264264
cond_resched();
265265
#endif
266266

267-
} while (end_tv.tv_sec < (start_tv.tv_sec + RUN_TIME) && !kill_test);
267+
} while (ktime_before(end_time, timeout) && !kill_test);
268268
trace_printk("End ring buffer hammer\n");
269269

270270
if (consumer) {
@@ -280,9 +280,7 @@ static void ring_buffer_producer(void)
280280
wait_for_completion(&read_done);
281281
}
282282

283-
time = end_tv.tv_sec - start_tv.tv_sec;
284-
time *= USEC_PER_SEC;
285-
time += (long long)((long)end_tv.tv_usec - (long)start_tv.tv_usec);
283+
time = ktime_us_delta(end_time, start_time);
286284

287285
entries = ring_buffer_entries(buffer);
288286
overruns = ring_buffer_overruns(buffer);

0 commit comments

Comments
 (0)