]>
Commit | Line | Data |
---|---|---|
7691b2d1 GKH |
1 | From d01343244abdedd18303d0323b518ed9cdcb1988 Mon Sep 17 00:00:00 2001 |
2 | From: Steven Rostedt <srostedt@redhat.com> | |
3 | Date: Tue, 12 Oct 2010 12:06:43 -0400 | |
4 | Subject: ring-buffer: Fix typo of time extends per page | |
5 | ||
6 | From: Steven Rostedt <srostedt@redhat.com> | |
7 | ||
8 | commit d01343244abdedd18303d0323b518ed9cdcb1988 upstream. | |
9 | ||
10 | Time stamps for the ring buffer are created by the difference between | |
11 | two events. Each page of the ring buffer holds a full 64 bit timestamp. | |
12 | Each event has a 27 bit delta stamp from the last event. The unit of time | |
13 | is nanoseconds, so 27 bits can hold ~134 milliseconds. If two events | |
14 | happen more than 134 milliseconds apart, a time extend is inserted | |
15 | to add more bits for the delta. The time extend has 59 bits, which | |
16 | is good for ~18 years. | |
17 | ||
18 | Currently the time extend is committed separately from the event. | |
19 | If an event is discarded before it is committed, due to filtering, | |
20 | the time extend still exists. If all events are being filtered, then | |
21 | after ~134 milliseconds a new time extend will be added to the buffer. | |
22 | ||
23 | This can only happen till the end of the page. Since each page holds | |
24 | a full timestamp, there is no reason to add a time extend to the | |
25 | beginning of a page. Time extends can only fill a page that has actual | |
26 | data at the beginning, so there is no fear that time extends will fill | |
27 | more than a page without any data. | |
28 | ||
29 | When reading an event, a loop is made to skip over time extends | |
30 | since they are only used to maintain the time stamp and are never | |
31 | given to the caller. As a paranoid check to prevent the loop running | |
32 | forever, with the knowledge that time extends may only fill a page, | |
33 | a check is made that tests the iteration of the loop, and if the | |
34 | iteration is more than the number of time extends that can fit in a page | |
35 | a warning is printed and the ring buffer is disabled (all of ftrace | |
36 | is also disabled with it). | |
37 | ||
38 | There is another event type that is called a TIMESTAMP which can | |
39 | hold 64 bits of data in the theoretical case that two events happen | |
40 | 18 years apart. This code has not been implemented, but the name | |
41 | of this event exists, as well as the structure for it. The | |
42 | size of a TIMESTAMP is 16 bytes, where as a time extend is only | |
43 | 8 bytes. The macro used to calculate how many time extends can fit on | |
44 | a page used the TIMESTAMP size instead of the time extend size | |
45 | cutting the amount in half. | |
46 | ||
47 | The following test case can easily trigger the warning since we only | |
48 | need to have half the page filled with time extends to trigger the | |
49 | warning: | |
50 | ||
51 | # cd /sys/kernel/debug/tracing/ | |
52 | # echo function > current_tracer | |
53 | # echo 'common_pid < 0' > events/ftrace/function/filter | |
54 | # echo > trace | |
55 | # echo 1 > trace_marker | |
56 | # sleep 120 | |
57 | # cat trace | |
58 | ||
59 | Enabling the function tracer and then setting the filter to only trace | |
60 | functions where the process id is negative (no events), then clearing | |
61 | the trace buffer to ensure that we have nothing in the buffer, | |
62 | then write to trace_marker to add an event to the beginning of a page, | |
63 | sleep for 2 minutes (only 35 seconds is probably needed, but this | |
64 | guarantees the bug), and then finally reading the trace which will | |
65 | trigger the bug. | |
66 | ||
67 | This patch fixes the typo and prevents the false positive of that warning. | |
68 | ||
69 | Reported-by: Hans J. Koch <hjk@linutronix.de> | |
70 | Tested-by: Hans J. Koch <hjk@linutronix.de> | |
71 | Cc: Thomas Gleixner <tglx@linutronix.de> | |
72 | Signed-off-by: Steven Rostedt <rostedt@goodmis.org> | |
73 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
74 | ||
75 | --- | |
76 | kernel/trace/ring_buffer.c | 2 +- | |
77 | 1 file changed, 1 insertion(+), 1 deletion(-) | |
78 | ||
79 | --- a/kernel/trace/ring_buffer.c | |
80 | +++ b/kernel/trace/ring_buffer.c | |
81 | @@ -405,7 +405,7 @@ static inline int test_time_stamp(u64 de | |
82 | #define BUF_MAX_DATA_SIZE (BUF_PAGE_SIZE - (sizeof(u32) * 2)) | |
83 | ||
84 | /* Max number of timestamps that can fit on a page */ | |
85 | -#define RB_TIMESTAMPS_PER_PAGE (BUF_PAGE_SIZE / RB_LEN_TIME_STAMP) | |
86 | +#define RB_TIMESTAMPS_PER_PAGE (BUF_PAGE_SIZE / RB_LEN_TIME_EXTEND) | |
87 | ||
88 | int ring_buffer_print_page_header(struct trace_seq *s) | |
89 | { |