Unified trace buffer
Subsystems (8)
Steven Rostedt
maintainerv3 cover Unified trace buffer
[ NOTE function comments have not been updated. Comments within the
code has.]
This version I change the event header to what Peter Zijlstra requested. The buffer alignment is now 4 from 8. The minimum event is 8 bytes. The event header is now:
struct event_header {
u32 type:2, len:3, time_delta:27;
u32 array[];
};The length of the record is determined as:
if (data size > 28 bytes)
lenght = event->array[0] + sizeof(event_header);
else
length = event->len << 4 + sizeof(event_header);
For data
if (date size > 28 bytes)
data = &event->array[0];
else
data = &event->array[1];
There are now only 4 internal data types:
0 - Padding
1 - time extent
2 - time stamp
3 - data
This is for internal buffer management only. Other event types should be pushed to a higher layer, and stored in the data field.
The timing is basically the same as v2 but I added a reader side ring_buffer_normalize_time_stamp() operation. As a test, I mult the timestamp to -1, in both set and normalize operations. Whether this actually tests anything is another story ;-)
I actually like this header and structure the best. And this may be what I start working on for real.
So please speak up on this one.
I'm going to take a break from this and start doing my real work. This will let others soak it up for a bit.
-- Steve
Steven Rostedt
maintainerRFC PATCH v3 1/2 Unified trace buffer
This is probably very buggy. I ran it as a back end for ftrace but only tested the irqsoff and ftrace tracers. The selftests are busted with it.
But this is an attempt to get a unified buffering system that was talked about at the LPC meeting.
Now that it boots and runs (albeit, a bit buggy), I decided to post it. This is some idea that I had to handle this.
I tried to make it as simple as possible.
I'm not going to explain all the stuff I'm doing here, since this code is under a lot of flux (RFC, POC work), and I don't want to keep updating this change log. When we finally agree on something, I'll make this change log worthy.
If you want to know what this patch does, the code below explains it :-p
--- include/linux/ring_buffer.h | 175 ++++++ kernel/trace/Kconfig | 3 kernel/trace/Makefile | 1 kernel/trace/ring_buffer.c | 1218 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1397 insertions(+)
include/linux/ring_buffer.h new file +175 -0
@@ -0,0 +1,175 @@ +#ifndef _LINUX_RING_BUFFER_H +#define _LINUX_RING_BUFFER_H + +#include <linux/mm.h> +#include <linux/seq_file.h> + +struct ring_buffer ; +struct ring_buffer_iter ; + +/* +* Don't reference this struct directly, use the inline items below. +*/ +struct ring_buffer_event { +u32 type:2 , len:3 , time_delta:27 ; +u32 array[]; +} __attribute__((__packed__ )); + +enum { +RB_TYPE_PADDING ,/* Left over page padding +* array is ignored +* size is variable depending on +*/ +RB_TYPE_TIME_EXTENT ,/* Extent the time delta +* array[0] = time delta (28 .. 59) +* size = 8 bytes +*/ +/* FIXME: RB_TYPE_TIME_STAMP not implemented */ +RB_TYPE_TIME_STAMP ,/* Sync time stamp with external clock +* array[0] = tv_nsec +* array[1] = tv_sec +* size = 16 bytes +*/ + +RB_TYPE_DATA ,/* Data record +* If len is zero: +* array[0] holds the actual length +* array[1..(length+3)/4] holds data +* else +* length = len << 2 +* array[0..(length+3)/4] holds data +*/ +}; + +#define RB_EVNT_HDR_SIZE (sizeof(struct ring_buffer_event)) +#define RB_ALIGNMENT_SHIFT 2 +#define RB_ALIGNMENT (1 << RB_ALIGNMENT_SHIFT) +#define RB_MAX_SMALL_DATA (28) + +enum { +RB_LEN_TIME_EXTENT =8 , +RB_LEN_TIME_STAMP =16 , +}; + +/** +* ring_buffer_event_length - return the length of the event +* @event: the event to get the length of +*/ +static inline unsigned +ring_buffer_event_length (struct ring_buffer_event *event) +{ +unsigned length; + +switch (event->type) { +case RB_TYPE_PADDING : +/* undefined */ +return -1 ; + +case RB_TYPE_TIME_EXTENT : +return RB_LEN_TIME_EXTENT ; + +case RB_TYPE_TIME_STAMP : +return RB_LEN_TIME_STAMP ; + +case RB_TYPE_DATA : +if (event->len) + length = event->len <<RB_ALIGNMENT_SHIFT ; +else + length = event->array[0 ]; +return length +RB_EVNT_HDR_SIZE ; +default : +BUG (); + } +/* not hit */ +return 0 ; +} + +/** +* ring_buffer_event_time_delta - return the delta timestamp of the event +* @event: the event to get the delta timestamp of +* +* The delta timestamp is the 27 bit timestamp since the last event. +*/ +static inline unsigned +ring_buffer_event_time_delta (struct ring_buffer_event *event) +{ +return event->time_delta; +} + +/** +* ring_buffer_event_data - return the data of the event +* @event: the event to get the data from +* +* Note, if the length of the event is more than 256 bytes, the +* length field is stored in the body. We need to return +* after the length field in that case. +*/ +static inline void * +ring_buffer_event_data (struct ring_buffer_event *event) +{ +BUG_ON (event->type !=RB_TYPE_DATA ); +/* If length is in len field, then array[0] has the data */ +if (event->len) +return (void *)&event->array[0 ]; +/* Otherwise length is in array[0] and array[1] has the data */ +return (void *)&event->array[1 ]; +} + +void ring_buffer_lock (struct ring_buffer *buffer,unsigned long *flags); +void ring_buffer_unlock (struct ring_buffer *buffer,unsigned long flags); + +/* +* size is in bytes for each per CPU buffer. +*/ +struct ring_buffer * +ring_buffer_alloc (unsigned long size,unsigned flags); +void ring_buffer_free (struct ring_buffer *buffer); + +int ring_buffer_resize (struct ring_buffer *buffer,unsigned long size); + +void *ring_buffer_lock_reserve (struct ring_buffer *buffer, +unsigned long length, +unsigned long *flags); +int ring_buffer_unlock_commit (struct ring_buffer *buffer, +void *data,unsigned long flags); +void *ring_buffer_write (struct ring_buffer *buffer, +unsigned long length,void *data); + +struct ring_buffer_event * +ring_buffer_consume (struct ring_buffer *buffer,int cpu,u64 *ts); + +struct ring_buffer_iter * +ring_buffer_read_start (struct ring_buffer *buffer,int cpu); +void ring_buffer_read_finish (struct ring_buffer_iter *iter); + +struct ring_buffer_event * +ring_buffer_peek (struct ring_buffer *buffer,int cpu,u64 *ts); +struct ring_buffer_event * +ring_buffer_iter_peek (struct ring_buffer_iter *iter,u64 *ts); +struct ring_buffer_event * +ring_buffer_read (struct ring_buffer_iter *iter,u64 *ts); +void ring_buffer_iter_reset (struct ring_buffer_iter *iter); +int ring_buffer_iter_empty (struct ring_buffer_iter *iter); + +unsigned long ring_buffer_size (struct ring_buffer *buffer); + +void ring_buffer_reset_cpu (struct ring_buffer *buffer,int cpu); +void ring_buffer_reset (struct ring_buffer *buffer); + +int ring_buffer_swap_cpu (struct ring_buffer *buffer_a, +struct ring_buffer *buffer_b,int cpu); + +int ring_buffer_empty (struct ring_buffer *buffer); +int ring_buffer_empty_cpu (struct ring_buffer *buffer,int cpu); + +void ring_buffer_disable (struct ring_buffer *buffer); +void ring_buffer_enable (struct ring_buffer *buffer); + +unsigned long ring_buffer_entries (struct ring_buffer *buffer); +unsigned long ring_buffer_overruns (struct ring_buffer *buffer); + +enum ring_buffer_flags { +RB_FL_OVERWRITE =1 <<0 , +}; + +#endif /* _LINUX_RING_BUFFER_H */
kernel/trace/ring_buffer.c new file +1218 -0
1,218 lines not on this page · raw message
kernel/trace/Kconfig +3 -0
@@ -15,6 +15,9 @@ config TRACING select DEBUG_FS select STACKTRACE +config RING_BUFFER + bool "ring buffer" + config FTRACE bool "Kernel Function Tracer" depends on HAVE_FTRACE
kernel/trace/Makefile +1 -0
@@ -11,6 +11,7 @@ obj-y += trace_selftest_dynamic.o endif obj-$(CONFIG_FTRACE) += libftrace.o +obj-$(CONFIG_RING_BUFFER) += ring_buffer.o obj-$(CONFIG_TRACING) += trace.o obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
Steven Rostedt
maintainerRFC PATCH v4 1/1 Unified trace buffer
This version has been cleaned up a bit. I've been running it as a back end to ftrace, and it has been handling pretty well.
I did not implement the GTOD sync part and will leave that for later. But this is the basic design that I like and will be the basis of my future work.
--- include/linux/ring_buffer.h | 178 ++++++ kernel/trace/Kconfig | 4 kernel/trace/Makefile | 1 kernel/trace/ring_buffer.c | 1252 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1435 insertions(+)
include/linux/ring_buffer.h new file +178 -0
@@ -0,0 +1,178 @@ +#ifndef _LINUX_RING_BUFFER_H +#define _LINUX_RING_BUFFER_H + +#include <linux/mm.h> +#include <linux/seq_file.h> + +struct ring_buffer ; +struct ring_buffer_iter ; + +/* +* Don't reference this struct directly, use the inline items below. +*/ +struct ring_buffer_event { +u32 type:2 , len:3 , time_delta:27 ; +u32 array[]; +} __attribute__((__packed__ )); + +enum { +RB_TYPE_PADDING ,/* Left over page padding +* array is ignored +* size is variable depending on +*/ +RB_TYPE_TIME_EXTENT ,/* Extent the time delta +* array[0] = time delta (28 .. 59) +* size = 8 bytes +*/ +/* FIXME: RB_TYPE_TIME_STAMP not implemented */ +RB_TYPE_TIME_STAMP ,/* Sync time stamp with external clock +* array[0] = tv_nsec +* array[1] = tv_sec +* size = 16 bytes +*/ + +RB_TYPE_DATA ,/* Data record +* If len is zero: +* array[0] holds the actual length +* array[1..(length+3)/4] holds data +* else +* length = len << 2 +* array[0..(length+3)/4] holds data +*/ +}; + +#define RB_EVNT_HDR_SIZE (sizeof(struct ring_buffer_event)) +#define RB_ALIGNMENT_SHIFT 2 +#define RB_ALIGNMENT (1 << RB_ALIGNMENT_SHIFT) +#define RB_MAX_SMALL_DATA (28) + +enum { +RB_LEN_TIME_EXTENT =8 , +RB_LEN_TIME_STAMP =16 , +}; + +/** +* ring_buffer_event_length - return the length of the event +* @event: the event to get the length of +*/ +static inline unsigned +ring_buffer_event_length (struct ring_buffer_event *event) +{ +unsigned length; + +switch (event->type) { +case RB_TYPE_PADDING : +/* undefined */ +return -1 ; + +case RB_TYPE_TIME_EXTENT : +return RB_LEN_TIME_EXTENT ; + +case RB_TYPE_TIME_STAMP : +return RB_LEN_TIME_STAMP ; + +case RB_TYPE_DATA : +if (event->len) + length = event->len <<RB_ALIGNMENT_SHIFT ; +else + length = event->array[0 ]; +return length +RB_EVNT_HDR_SIZE ; +default : +BUG (); + } +/* not hit */ +return 0 ; +} + +/** +* ring_buffer_event_time_delta - return the delta timestamp of the event +* @event: the event to get the delta timestamp of +* +* The delta timestamp is the 27 bit timestamp since the last event. +*/ +static inline unsigned +ring_buffer_event_time_delta (struct ring_buffer_event *event) +{ +return event->time_delta; +} + +/** +* ring_buffer_event_data - return the data of the event +* @event: the event to get the data from +*/ +static inline void * +ring_buffer_event_data (struct ring_buffer_event *event) +{ +BUG_ON (event->type !=RB_TYPE_DATA ); +/* If length is in len field, then array[0] has the data */ +if (event->len) +return (void *)&event->array[0 ]; +/* Otherwise length is in array[0] and array[1] has the data */ +return (void *)&event->array[1 ]; +} + +void ring_buffer_lock (struct ring_buffer *buffer,unsigned long *flags); +void ring_buffer_unlock (struct ring_buffer *buffer,unsigned long flags); + +/* +* size is in bytes for each per CPU buffer. +*/ +struct ring_buffer * +ring_buffer_alloc (unsigned long size,unsigned flags); +void ring_buffer_free (struct ring_buffer *buffer); + +int ring_buffer_resize (struct ring_buffer *buffer,unsigned long size); + +struct ring_buffer_event * +ring_buffer_lock_reserve (struct ring_buffer *buffer, +unsigned long length, +unsigned long *flags); +int ring_buffer_unlock_commit (struct ring_buffer *buffer, +struct ring_buffer_event *event, +unsigned long flags); +int ring_buffer_write (struct ring_buffer *buffer, +unsigned long length,void *data); + +struct ring_buffer_event * +ring_buffer_peek (struct ring_buffer *buffer,int cpu,u64 *ts); +struct ring_buffer_event * +ring_buffer_consume (struct ring_buffer *buffer,int cpu,u64 *ts); + +struct ring_buffer_iter * +ring_buffer_read_start (struct ring_buffer *buffer,int cpu); +void ring_buffer_read_finish (struct ring_buffer_iter *iter); + +struct ring_buffer_event * +ring_buffer_iter_peek (struct ring_buffer_iter *iter,u64 *ts); +struct ring_buffer_event * +ring_buffer_read (struct ring_buffer_iter *iter,u64 *ts); +void ring_buffer_iter_reset (struct ring_buffer_iter *iter); +int ring_buffer_iter_empty (struct ring_buffer_iter *iter); + +unsigned long ring_buffer_size (struct ring_buffer *buffer); + +void ring_buffer_reset_cpu (struct ring_buffer *buffer,int cpu); +void ring_buffer_reset (struct ring_buffer *buffer); + +int ring_buffer_swap_cpu (struct ring_buffer *buffer_a, +struct ring_buffer *buffer_b,int cpu); + +int ring_buffer_empty (struct ring_buffer *buffer); +int ring_buffer_empty_cpu (struct ring_buffer *buffer,int cpu); + +void ring_buffer_record_disable (struct ring_buffer *buffer); +void ring_buffer_record_enable (struct ring_buffer *buffer); +void ring_buffer_record_disable_cpu (struct ring_buffer *buffer,int cpu); +void ring_buffer_record_enable_cpu (struct ring_buffer *buffer,int cpu); + +unsigned long ring_buffer_entries (struct ring_buffer *buffer); +unsigned long ring_buffer_overruns (struct ring_buffer *buffer); + +u64 ring_buffer_time_stamp (int cpu); +void ring_buffer_normalize_time_stamp (int cpu,u64 *ts); + +enum ring_buffer_flags { +RB_FL_OVERWRITE =1 <<0 , +}; + +#endif /* _LINUX_RING_BUFFER_H */
kernel/trace/ring_buffer.c new file +1252 -0
1,252 lines not on this page · raw message
kernel/trace/Kconfig +4 -0
@@ -10,10 +10,14 @@ config HAVE_DYNAMIC_FTRACE config TRACER_MAX_TRACE bool +config RING_BUFFER + bool + config TRACING bool select DEBUG_FS select STACKTRACE + select RING_BUFFER config FTRACE bool "Kernel Function Tracer"
kernel/trace/Makefile +1 -0
@@ -11,6 +11,7 @@ obj-y += trace_selftest_dynamic.o endif obj-$(CONFIG_FTRACE) += libftrace.o +obj-$(CONFIG_RING_BUFFER) += ring_buffer.o obj-$(CONFIG_TRACING) += trace.o obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
Hi Steven,
Quoted 2 lines · Steven Rostedt
This version has been cleaned up a bit. I've been running it as a back end to ftrace, and it has been handling pretty well.
Thank you for your great work.
It seems good to me(especially, encapsulating events :)).
I have one request of enhancement.
Quoted 3 lines
kernel/trace/ring_buffer.c new file +3
-0+static struct ring_buffer_per_cpu * +ring_buffer_allocate_cpu_buffer (struct ring_buffer *buffer,int cpu) +{
[...]
kernel/trace/ring_buffer.c line 110
Quoted 3 lines
kernel/trace/ring_buffer.c new file +3
-0+ cpu_buffer->pages =kzalloc_node (ALIGN (sizeof (void *) * pages, +cache_line_size ()),GFP_KERNEL , +cpu_to_node (cpu));
Here, you are using a slab object for page managing array, the largest object size is 128KB(x86-64), so it can contain 16K pages = 64MB.
As I had improved relayfs, in some rare case(on 64bit arch), we'd like to use larger buffer than 64MB.
http://sourceware.org/ml/systemtap/2008-q2/msg00103.html
So, I think similar hack can be applicable.
Would it be acceptable for the next version?
Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Steven Rostedt
maintainerQuoted 8 lines · Masami Hiramatsu
Hi Steven,
Quoted 2 lines · Steven Rostedt
This version has been cleaned up a bit. I've been running it as a back end to ftrace, and it has been handling pretty well.
Thank you for your great work.
It seems good tome(especially, encapsulating events :)).
Thanks!
Quoted 15 lines
I have one request of enhancement.
Quoted 3 lines
kernel/trace/ring_buffer.c new file +3
-0+static struct ring_buffer_per_cpu * +ring_buffer_allocate_cpu_buffer (struct ring_buffer *buffer,int cpu) +{[...]
kernel/trace/ring_buffer.c line 110
Quoted 3 lines
kernel/trace/ring_buffer.c new file +3
-0+ cpu_buffer->pages =kzalloc_node (ALIGN (sizeof (void *) * pages, +cache_line_size ()),GFP_KERNEL , +cpu_to_node (cpu));Here, you are using a slab object for page managing array, the largest object size is 128KB(x86-64), so it can contain 16K pages = 64MB.
Quoted 8 lines
As I had improved relayfs, in some rare case(on 64bit arch), we'd like to use larger buffer than 64MB.
http://sourceware.org/ml/systemtap/2008-q2/msg00103.html
So, I think similar hack can be applicable.
Would it be acceptable for the next version?
I would like to avoid using vmalloc as much as possible, but I do see the limitation here. Here's my compromise.
Instead of using vmalloc if the page array is greater than one page, how about using vmalloc if the page array is greater than KMALLOC_MAX_SIZE?
This would let us keep the vmap area free unless we have no choice.
-- Steve
Quoted 32 lines · Steven Rostedt
Quoted 7 lines · Masami Hiramatsu
Hi Steven,
Quoted 2 lines · Steven Rostedt
This version has been cleaned up a bit. I've been running it as a back end to ftrace, and it has been handling pretty well.
Thank you for your great work.
It seems good tome(especially, encapsulating events :)).Thanks!
Quoted 20 lines
I have one request of enhancement.
Quoted 3 lines
kernel/trace/ring_buffer.c new file +3
-0+static struct ring_buffer_per_cpu * +ring_buffer_allocate_cpu_buffer (struct ring_buffer *buffer,int cpu) +{[...]
kernel/trace/ring_buffer.c line 110
Quoted 3 lines
kernel/trace/ring_buffer.c new file +3
-0+ cpu_buffer->pages =kzalloc_node (ALIGN (sizeof (void *) * pages, +cache_line_size ()),GFP_KERNEL , +cpu_to_node (cpu));Here, you are using a slab object for page managing array, the largest object size is 128KB(x86-64), so it can contain 16K pages = 64MB.
As I had improved relayfs, in some rare case(on 64bit arch), we'd like to use larger buffer than 64MB.
http://sourceware.org/ml/systemtap/2008-q2/msg00103.html
So, I think similar hack can be applicable.
Quoted 7 lines
Quoted 1 line
Would it be acceptable for the next version?
I would like to avoid using vmalloc as much as possible, but I do see the limitation here. Here's my compromise.
Instead of using vmalloc if the page array is greater than one page, how about using vmalloc if the page array is greater than
KMALLOC_MAX_SIZE?This would let us keep the vmap area free unless we have no choice.
Hmm, that's a good idea.
In most cases, per-cpu buffer may be less than 64MB, so I think it is reasonable.
Thank you,
Quoted 3 lines
-- Steve
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Quoted 41 lines · * Steven Rostedt ([email protected]) wrote:
Quoted 8 lines · Masami Hiramatsu
Hi Steven,
Quoted 2 lines · Steven Rostedt
This version has been cleaned up a bit. I've been running it as a back end to ftrace, and it has been handling pretty well.
Thank you for your great work.
It seems good tome(especially, encapsulating events :)).Thanks!
Quoted 15 lines
I have one request of enhancement.
Quoted 3 lines
kernel/trace/ring_buffer.c new file +3
-0+static struct ring_buffer_per_cpu * +ring_buffer_allocate_cpu_buffer (struct ring_buffer *buffer,int cpu) +{[...]
kernel/trace/ring_buffer.c line 110
Quoted 3 lines
kernel/trace/ring_buffer.c new file +3
-0+ cpu_buffer->pages =kzalloc_node (ALIGN (sizeof (void *) * pages, +cache_line_size ()),GFP_KERNEL , +cpu_to_node (cpu));Here, you are using a slab object for page managing array, the largest object size is 128KB(x86-64), so it can contain 16K pages = 64MB.
Quoted 8 lines
As I had improved relayfs, in some rare case(on 64bit arch), we'd like to use larger buffer than 64MB.
http://sourceware.org/ml/systemtap/2008-q2/msg00103.html
So, I think similar hack can be applicable.
Would it be acceptable for the next version?
I would like to avoid using vmalloc as much as possible, but I do see the limitation here. Here's my compromise.
Quoted 8 lines
Instead of using vmalloc if the page array is greater than one page, how about using vmalloc if the page array is greater than
KMALLOC_MAX_SIZE?This would let us keep the vmap area free unless we have no choice.
-- Steve
You could also fallback on a 2-level page array when buffer size is > 64MB. The cost is mainly a supplementary pointer dereference, but one more should not make sure a big difference overall.
Mathieu
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Quoted 46 lines · Mathieu Desnoyers
Quoted 45 lines · * Steven Rostedt ([email protected]) wrote:
Quoted 8 lines · Masami Hiramatsu
Hi Steven,
Quoted 2 lines · Steven Rostedt
This version has been cleaned up a bit. I've been running it as a back end to ftrace, and it has been handling pretty well.
Thank you for your great work.
It seems good tome(especially, encapsulating events :)).Thanks!
Quoted 15 lines
I have one request of enhancement.
Quoted 3 lines
kernel/trace/ring_buffer.c new file +3
-0+static struct ring_buffer_per_cpu * +ring_buffer_allocate_cpu_buffer (struct ring_buffer *buffer,int cpu) +{[...]
kernel/trace/ring_buffer.c line 110
Quoted 3 lines
kernel/trace/ring_buffer.c new file +3
-0+ cpu_buffer->pages =kzalloc_node (ALIGN (sizeof (void *) * pages, +cache_line_size ()),GFP_KERNEL , +cpu_to_node (cpu));Here, you are using a slab object for page managing array, the largest object size is 128KB(x86-64), so it can contain 16K pages = 64MB.
Quoted 8 lines
As I had improved relayfs, in some rare case(on 64bit arch), we'd like to use larger buffer than 64MB.
http://sourceware.org/ml/systemtap/2008-q2/msg00103.html
So, I think similar hack can be applicable.
Would it be acceptable for the next version?
I would like to avoid using vmalloc as much as possible, but I do see the limitation here. Here's my compromise.
Instead of using vmalloc if the page array is greater than one page, how about using vmalloc if the page array is greater than
KMALLOC_MAX_SIZE?
Quoted 8 lines
Quoted 4 lines
This would let us keep the vmap area free unless we have no choice.
-- Steve
You could also fallback on a 2-level page array when buffer size is > 64MB. The cost is mainly a supplementary pointer dereference, but one more should not make sure a big difference overall.
I'm still not sure why we don't just link the pages using the page frames, we don't need the random access, do we?
Steven Rostedt
maintainerQuoted 8 lines · Peter Zijlstra
Quoted 4 lines · Mathieu Desnoyers
You could also fallback on a 2-level page array when buffer size is > 64MB. The cost is mainly a supplementary pointer dereference, but one more should not make sure a big difference overall.
I'm still not sure why we don't just link the pages using the page frames, we don't need the random access, do we?
Yeah we can go back to that (as ftrace does).
1) It can be very error prone. I will need to encapsulate the logic more.
2) I'm still not sure if crash can handle it.
I was going to reply to Masami with this answer, but it makes things more complex. For v1 (non RFC v1) I wanted to start simple. v2 can have this enhancement.
-- Steve
Quoted 7 lines · Steven Rostedt
Quoted 6 lines · Peter Zijlstra
Quoted 4 lines · Mathieu Desnoyers
You could also fallback on a 2-level page array when buffer size is > 64MB. The cost is mainly a supplementary pointer dereference, but one more should not make sure a big difference overall.
Quoted 6 lines
Quoted 2 lines
I'm still not sure why we don't just link the pages using the page frames, we don't need the random access, do we?
Yeah we can go back to that (as ftrace does).
1) It can be very error prone. I will need to encapsulate the logic more.
Sure.
Quoted 1 line
2) I'm still not sure if crash can handle it.
It ought to, and if it can't it should be fixed. Having easy access to the pageframes is vital to debugging VM issues. So I'd not bother about this issue too much.
Quoted 3 lines
I was going to reply to Masami with this answer, but it makes things more complex. For v1 (non RFC v1) I wanted to start simple. v2 can have this enhancement.
Right - I just object to having anything vmalloc.
Quoted 20 lines · Peter Zijlstra
Quoted 10 lines · Steven Rostedt
Quoted 6 lines · Peter Zijlstra
Quoted 3 lines · Mathieu Desnoyers
You could also fallback on a 2-level page array when buffer size is > 64MB. The cost is mainly a supplementary pointer dereference, but one more should not make sure a big difference overall.
I'm still not sure why we don't just link the pages using the page frames, we don't need the random access, do we?
Yeah we can go back to that (as ftrace does).
1) It can be very error prone. I will need to encapsulate the logic more.
Sure.
Quoted 1 line
2) I'm still not sure if crash can handle it.
It ought to, and if it can't it should be fixed. Having easy access to the pageframes is vital to debugging VM issues. So I'd not bother about this issue too much.
Quoted 5 lines
Quoted 3 lines
I was going to reply to Masami with this answer, but it makes things more complex. For v1 (non RFC v1) I wanted to start simple. v2 can have this enhancement.
Right - I just object to having anything vmalloc.
I just requested that the expansion of buffer size limitation too. :)
I don't stick with vmalloc. If that (page frame chain?) can achieve better performance, I agree that trace buffer uses it.
Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Steven Rostedt
maintainerQuoted 5 lines · Masami Hiramatsu
Quoted 4 lines · Peter Zijlstra
Quoted 3 lines
I was going to reply to Masami with this answer, but it makes things more complex. For v1 (non RFC v1) I wanted to start simple. v2 can have this enhancement.
Quoted 7 lines
Quoted 1 line
Right - I just object to having anything vmalloc.
I just requested that the expansion of buffer size limitation too. :)
I don't stick with vmalloc. If that (page frame chain?) can achieve better performance, I agree that trace buffer uses it.
v5 is out with this implementation. It may or may not be better performance, but the difference is most likely negligible.
Anyway, I'm happing with this last release, and hopefully it can get into 2.6.28. This would mean I can start basing ftrace on top of it.
-- Steve
Steven Rostedt
maintainerQuoted 7 lines · Peter Zijlstra
Quoted 4 lines
You could also fallback on a 2-level page array when buffer size is > 64MB. The cost is mainly a supplementary pointer dereference, but one more should not make sure a big difference overall.
I'm still not sure why we don't just link the pages using the page frames, we don't need the random access, do we?
Hmm, but this does make changing the buffer size much easier. I'll think about it and perhaps try it out. If I can tidy it up nicer than the ftrace code, then I may include it for v1.
-- Steve
Quoted 52 lines · * Peter Zijlstra ([email protected]) wrote:
Quoted 51 lines · Mathieu Desnoyers
Quoted 49 lines · * Steven Rostedt ([email protected]) wrote:
Quoted 8 lines · Masami Hiramatsu
Hi Steven,
Quoted 2 lines · Steven Rostedt
This version has been cleaned up a bit. I've been running it as a back end to ftrace, and it has been handling pretty well.
Thank you for your great work.
It seems good tome(especially, encapsulating events :)).Thanks!
Quoted 15 lines
I have one request of enhancement.
Quoted 3 lines
kernel/trace/ring_buffer.c new file +3
-0+static struct ring_buffer_per_cpu * +ring_buffer_allocate_cpu_buffer (struct ring_buffer *buffer,int cpu) +{[...]
kernel/trace/ring_buffer.c line 110
Quoted 3 lines
kernel/trace/ring_buffer.c new file +3
-0+ cpu_buffer->pages =kzalloc_node (ALIGN (sizeof (void *) * pages, +cache_line_size ()),GFP_KERNEL , +cpu_to_node (cpu));Here, you are using a slab object for page managing array, the largest object size is 128KB(x86-64), so it can contain 16K pages = 64MB.
Quoted 8 lines
As I had improved relayfs, in some rare case(on 64bit arch), we'd like to use larger buffer than 64MB.
http://sourceware.org/ml/systemtap/2008-q2/msg00103.html
So, I think similar hack can be applicable.
Would it be acceptable for the next version?
I would like to avoid using vmalloc as much as possible, but I do see the limitation here. Here's my compromise.
Instead of using vmalloc if the page array is greater than one page, how about using vmalloc if the page array is greater than
KMALLOC_MAX_SIZE?This would let us keep the vmap area free unless we have no choice.
-- Steve
Quoted 7 lines
Quoted 3 lines
You could also fallback on a 2-level page array when buffer size is > 64MB. The cost is mainly a supplementary pointer dereference, but one more should not make sure a big difference overall.
I'm still not sure why we don't just link the pages using the page frames, we don't need the random access, do we?
Yes, that's a brilliant idea :)
Mathieu
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Steven Rostedt
maintainerPATCH v5 1/1 Unified trace buffer
In reply to Masami Hiramatsu[
Note the removal of the RFC in the subject.
I am happy with this version. It handles everything I need for ftrace.
New since last version:
- Fixed timing bug. I did not add the deltas properly when reading the buffer.
- Removed "-1" time stamp normalize test. This made the clock go backwards!
- Removed page pointer array and replaced it with the ftrace page struct link list trick. Since this is my second time writing this code (first with ftrace), it is actually much cleaner than the ftrace code.
- Implemented buffer resizing. By using the page link list trick, this became much simpler.
Note, the GOTD part is still not implemented, but can be done later without affecting this interface.
]
This is a unified tracing buffer that implements a ring buffer that hopefully everyone will eventually be able to use.
The events recorded into the buffer have the following structure:
struct ring_buffer_event {
u32 type:2, len:3, time_delta:27;
u32 array[];
};The minimum size of an event is 8 bytes. All events are 4 byte aligned inside the buffer.
There are 4 types (all internal use for the ring buffer, only the data type is exported to the interface users).
RB_TYPE_PADDING: this type is used to note extra space at the end
of a buffer page.
RB_TYPE_TIME_EXTENT: This type is used when the time between events
is greater than the 27 bit delta can hold. We add another 32 bits, and record that in its own event (8 byte size).
RB_TYPE_TIME_STAMP: (Not implemented yet). This will hold data to
help keep the buffer timestamps in sync.
RB_TYPE_DATA: The event actually holds user data.
The "len" field is only three bits. Since the data must be 4 byte aligned, this field is shifted left by 2, giving a max length of 28 bytes. If the data load is greater than 28 bytes, the first array field holds the full length of the data load and the len field is set to zero.
Example, data size of 7 bytes:
type = RB_TYPE_DATA len = 2 time_delta: <time-stamp> - <prev_event-time-stamp> array[0..1]: <7 bytes of data> <1 byte empty>
This event is saved in 12 bytes of the buffer.
An event with 82 bytes of data:
type = RB_TYPE_DATA
len = 0
time_delta: <time-stamp> - <prev_event-time-stamp> array[0]: 84 (Note the alignment) array[1..14]: <82 bytes of data> <2 bytes empty>
The above event is saved in 92 bytes (if my math is correct). 82 bytes of data, 2 bytes empty, 4 byte header, 4 byte length.
Do not reference the above event struct directly. Use the following functions to gain access to the event table, since the ring_buffer_event structure may change in the future.
ring_buffer_event_length(event): get the length of the event.
This is the size of the memory used to record this event, and not the size of the data pay load.
ring_buffer_time_delta(event): get the time delta of the event
This returns the delta time stamp since the last event.
Note: Even though this is in the header, there should
be no reason to access this directly, accept for debugging.
ring_buffer_event_data(event): get the data from the event
This is the function to use to get the actual data from the event. Note, it is only a pointer to the data inside the buffer. This data must be copied to another location otherwise you risk it being written over in the buffer.
ring_buffer_lock: A way to lock the entire buffer.ring_buffer_unlock: unlock the buffer.
ring_buffer_alloc: create a new ring buffer. Can choose between
overwrite or consumer/producer mode. Overwrite will overwrite old data, where as consumer producer will throw away new data if the consumer catches up with the producer. The consumer/producer is the default.
ring_buffer_free: free the ring buffer.
ring_buffer_resize: resize the buffer. Changes the size of each cpu
buffer. Note, it is up to the caller to provide that the buffer is not being used while this is happening. This requirement may go away but do not count on it.
ring_buffer_lock_reserve: locks the ring buffer and allocates an
entry on the buffer to write to.ring_buffer_unlock_commit: unlocks the ring buffer and commits it to
the buffer.
ring_buffer_write: writes some data into the ring buffer.
ring_buffer_peek: Look at a next item in the cpu buffer.ring_buffer_consume: get the next item in the cpu buffer and
consume it. That is, this function increments the head pointer.
ring_buffer_read_start: Start an iterator of a cpu buffer.
For now, this disables the cpu buffer, until you issue a finish. This is just because we do not want the iterator to be overwritten. This restriction may change in the future. But note, this is used for static reading of a buffer which is usually done "after" a trace. Live readings would want to use the ring_buffer_consume above, which will not disable the ring buffer.
ring_buffer_read_finish: Finishes the read iterator and reenables
the ring buffer.
ring_buffer_iter_peek: Look at the next item in the cpu iterator.ring_buffer_read: Read the iterator and increment it.ring_buffer_iter_reset: Reset the iterator to point to the beginning
of the cpu buffer.ring_buffer_iter_empty: Returns true if the iterator is at the end
of the cpu buffer.
ring_buffer_size: returns the size in bytes of each cpu buffer.
Note, the real size is this times the number of CPUs.
ring_buffer_reset_cpu: Sets the cpu buffer to emptyring_buffer_reset: sets all cpu buffers to empty
ring_buffer_swap_cpu: swaps a cpu buffer from one buffer with a
cpu buffer of another buffer. This is handy when you want to take a snap shot of a running trace on just one cpu. Having a backup buffer, to swap with facilitates this. Ftrace max latencies use this.
ring_buffer_empty: Returns true if the ring buffer is empty.ring_buffer_empty_cpu: Returns true if the cpu buffer is empty.
ring_buffer_record_disable: disable all cpu buffers (read only) ring_buffer_record_disable_cpu: disable a single cpu buffer (read only)ring_buffer_record_enable: enable all cpu buffers. ring_buffer_record_enabl_cpu: enable a single cpu buffer.
ring_buffer_entries: The number of entries in a ring buffer.ring_buffer_overruns: The number of entries removed due to writing wrap.
ring_buffer_time_stamp: Get the time stamp used by the ring buffer ring_buffer_normalize_time_stamp: normalize the ring buffer time stamp
into nanosecs.
I still need to implement the GTOD feature. But we need support from the cpu frequency infrastructure. But this can be done at a later time without affecting the ring buffer interface.
--- include/linux/ring_buffer.h | 178 +++++ kernel/trace/Kconfig | 4 kernel/trace/Makefile | 1 kernel/trace/ring_buffer.c | 1491 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1674 insertions(+)
include/linux/ring_buffer.h new file +178 -0
@@ -0,0 +1,178 @@ +#ifndef _LINUX_RING_BUFFER_H +#define _LINUX_RING_BUFFER_H + +#include <linux/mm.h> +#include <linux/seq_file.h> + +struct ring_buffer ; +struct ring_buffer_iter ; + +/* +* Don't reference this struct directly, use the inline items below. +*/ +struct ring_buffer_event { +u32 type:2 , len:3 , time_delta:27 ; +u32 array[]; +} __attribute__((__packed__ )); + +enum { +RB_TYPE_PADDING ,/* Left over page padding +* array is ignored +* size is variable depending on +*/ +RB_TYPE_TIME_EXTENT ,/* Extent the time delta +* array[0] = time delta (28 .. 59) +* size = 8 bytes +*/ +/* FIXME: RB_TYPE_TIME_STAMP not implemented */ +RB_TYPE_TIME_STAMP ,/* Sync time stamp with external clock +* array[0] = tv_nsec +* array[1] = tv_sec +* size = 16 bytes +*/ + +RB_TYPE_DATA ,/* Data record +* If len is zero: +* array[0] holds the actual length +* array[1..(length+3)/4] holds data +* else +* length = len << 2 +* array[0..(length+3)/4] holds data +*/ +}; + +#define RB_EVNT_HDR_SIZE (sizeof(struct ring_buffer_event)) +#define RB_ALIGNMENT_SHIFT 2 +#define RB_ALIGNMENT (1 << RB_ALIGNMENT_SHIFT) +#define RB_MAX_SMALL_DATA (28) + +enum { +RB_LEN_TIME_EXTENT =8 , +RB_LEN_TIME_STAMP =16 , +}; + +/** +* ring_buffer_event_length - return the length of the event +* @event: the event to get the length of +*/ +static inline unsigned +ring_buffer_event_length (struct ring_buffer_event *event) +{ +unsigned length; + +switch (event->type) { +case RB_TYPE_PADDING : +/* undefined */ +return -1 ; + +case RB_TYPE_TIME_EXTENT : +return RB_LEN_TIME_EXTENT ; + +case RB_TYPE_TIME_STAMP : +return RB_LEN_TIME_STAMP ; + +case RB_TYPE_DATA : +if (event->len) + length = event->len <<RB_ALIGNMENT_SHIFT ; +else + length = event->array[0 ]; +return length +RB_EVNT_HDR_SIZE ; +default : +BUG (); + } +/* not hit */ +return 0 ; +} + +/** +* ring_buffer_event_time_delta - return the delta timestamp of the event +* @event: the event to get the delta timestamp of +* +* The delta timestamp is the 27 bit timestamp since the last event. +*/ +static inline unsigned +ring_buffer_event_time_delta (struct ring_buffer_event *event) +{ +return event->time_delta; +} + +/** +* ring_buffer_event_data - return the data of the event +* @event: the event to get the data from +*/ +static inline void * +ring_buffer_event_data (struct ring_buffer_event *event) +{ +BUG_ON (event->type !=RB_TYPE_DATA ); +/* If length is in len field, then array[0] has the data */ +if (event->len) +return (void *)&event->array[0 ]; +/* Otherwise length is in array[0] and array[1] has the data */ +return (void *)&event->array[1 ]; +} + +void ring_buffer_lock (struct ring_buffer *buffer,unsigned long *flags); +void ring_buffer_unlock (struct ring_buffer *buffer,unsigned long flags); + +/* +* size is in bytes for each per CPU buffer. +*/ +struct ring_buffer * +ring_buffer_alloc (unsigned long size,unsigned flags); +void ring_buffer_free (struct ring_buffer *buffer); + +int ring_buffer_resize (struct ring_buffer *buffer,unsigned long size); + +struct ring_buffer_event * +ring_buffer_lock_reserve (struct ring_buffer *buffer, +unsigned long length, +unsigned long *flags); +int ring_buffer_unlock_commit (struct ring_buffer *buffer, +struct ring_buffer_event *event, +unsigned long flags); +int ring_buffer_write (struct ring_buffer *buffer, +unsigned long length,void *data); + +struct ring_buffer_event * +ring_buffer_peek (struct ring_buffer *buffer,int cpu,u64 *ts); +struct ring_buffer_event * +ring_buffer_consume (struct ring_buffer *buffer,int cpu,u64 *ts); + +struct ring_buffer_iter * +ring_buffer_read_start (struct ring_buffer *buffer,int cpu); +void ring_buffer_read_finish (struct ring_buffer_iter *iter); + +struct ring_buffer_event * +ring_buffer_iter_peek (struct ring_buffer_iter *iter,u64 *ts); +struct ring_buffer_event * +ring_buffer_read (struct ring_buffer_iter *iter,u64 *ts); +void ring_buffer_iter_reset (struct ring_buffer_iter *iter); +int ring_buffer_iter_empty (struct ring_buffer_iter *iter); + +unsigned long ring_buffer_size (struct ring_buffer *buffer); + +void ring_buffer_reset_cpu (struct ring_buffer *buffer,int cpu); +void ring_buffer_reset (struct ring_buffer *buffer); + +int ring_buffer_swap_cpu (struct ring_buffer *buffer_a, +struct ring_buffer *buffer_b,int cpu); + +int ring_buffer_empty (struct ring_buffer *buffer); +int ring_buffer_empty_cpu (struct ring_buffer *buffer,int cpu); + +void ring_buffer_record_disable (struct ring_buffer *buffer); +void ring_buffer_record_enable (struct ring_buffer *buffer); +void ring_buffer_record_disable_cpu (struct ring_buffer *buffer,int cpu); +void ring_buffer_record_enable_cpu (struct ring_buffer *buffer,int cpu); + +unsigned long ring_buffer_entries (struct ring_buffer *buffer); +unsigned long ring_buffer_overruns (struct ring_buffer *buffer); + +u64 ring_buffer_time_stamp (int cpu); +void ring_buffer_normalize_time_stamp (int cpu,u64 *ts); + +enum ring_buffer_flags { +RB_FL_OVERWRITE =1 <<0 , +}; + +#endif /* _LINUX_RING_BUFFER_H */
kernel/trace/ring_buffer.c new file +1491 -0
1,491 lines not on this page · raw message
kernel/trace/Kconfig +4 -0
@@ -10,10 +10,14 @@ config HAVE_DYNAMIC_FTRACE config TRACER_MAX_TRACE bool +config RING_BUFFER + bool + config TRACING bool select DEBUG_FS select STACKTRACE + select RING_BUFFER config FTRACE bool "Kernel Function Tracer"
kernel/trace/Makefile +1 -0
@@ -11,6 +11,7 @@ obj-y += trace_selftest_dynamic.o endif obj-$(CONFIG_FTRACE) += libftrace.o +obj-$(CONFIG_RING_BUFFER) += ring_buffer.o obj-$(CONFIG_TRACING) += trace.o obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
Em Fri, Sep 26, 2008 at 01:11:57PM -0400, Steven Rostedt escreveu:
Quoted 199 lines
[
Note the removal of the RFC in the subject.
I am happy with this version. It handles everything I need for ftrace.New since last version:
- Fixed timing bug. I did not add the deltas properly when reading the buffer.
- Removed "-1" time stamp normalize test. This made the clock go backwards!
- Removed page pointer array and replaced it with the ftrace page struct link list trick. Since this is my second time writing this code (first with ftrace), it is actually much cleaner than the ftrace code.
- Implemented buffer resizing. By using the page link list trick, this became much simpler.
Note, the GOTD part is still not implemented, but can be done later without affecting this interface.
]
This is a unified tracing buffer that implements a ring buffer that hopefully everyone will eventually be able to use.
The events recorded into the buffer have the following structure:
struct ring_buffer_event { u32 type:2, len:3, time_delta:27; u32 array[]; };The minimum size of an event is 8 bytes. All events are 4 byte aligned inside the buffer.
There are 4 types (all internal use for the ring buffer, only the data type is exported to the interface users).
RB_TYPE_PADDING: this type is used to note extra space at the end
of a buffer page.
RB_TYPE_TIME_EXTENT: This type is used when the time between events
is greater than the 27 bit delta can hold. We add another 32 bits, and record that in its own event (8 byte size).
RB_TYPE_TIME_STAMP: (Not implemented yet). This will hold data to
help keep the buffer timestamps in sync.
RB_TYPE_DATA: The event actually holds user data.The "len" field is only three bits. Since the data must be 4 byte aligned, this field is shifted left by 2, giving a max length of 28 bytes. If the data load is greater than 28 bytes, the first array field holds the full length of the data load and the len field is set to zero.
Example, data size of 7 bytes:
type = RB_TYPE_DATA len = 2 time_delta: <time-stamp> - <prev_event-time-stamp> array[0..1]: <7 bytes of data> <1 byte empty>This event is saved in 12 bytes of the buffer.
An event with 82 bytes of data:
type =
RB_TYPE_DATA
len = 0
time_delta: <time-stamp> - <prev_event-time-stamp> array[0]: 84 (Note the alignment) array[1..14]: <82 bytes of data> <2 bytes empty>The above event is saved in 92 bytes (if my math is correct). 82 bytes of data, 2 bytes empty, 4 byte header, 4 byte length.
Do not reference the above event struct directly. Use the following functions to gain access to the event table, since the
ring_buffer_eventstructure may change in the future.
ring_buffer_event_length(event): get the length of the event.
This is the size of the memory used to record this event, and not the size of the data pay load.
ring_buffer_time_delta(event): get the time delta of the event
This returns the delta time stamp since the last event.
Note: Even though this is in the header, there should
be no reason to access this directly, accept for debugging.
ring_buffer_event_data(event): get the data from the event
This is the function to use to get the actual data from the event. Note, it is only a pointer to the data inside the buffer. This data must be copied to another location otherwise you risk it being written over in the buffer.
ring_buffer_lock: A way to lock the entire buffer.ring_buffer_unlock: unlock the buffer.
ring_buffer_alloc: create a new ring buffer. Can choose between
overwrite or consumer/producer mode. Overwrite will overwrite old data, where as consumer producer will throw away new data if the consumer catches up with the producer. The consumer/producer is the default.
ring_buffer_free: free the ring buffer.
ring_buffer_resize: resize the buffer. Changes the size of each cpu
buffer. Note, it is up to the caller to provide that the buffer is not being used while this is happening. This requirement may go away but do not count on it.
ring_buffer_lock_reserve: locks the ring buffer and allocates an
entry on the buffer to write to.ring_buffer_unlock_commit: unlocks the ring buffer and commits it to
the buffer.
ring_buffer_write: writes some data into the ring buffer.
ring_buffer_peek: Look at a next item in the cpu buffer.ring_buffer_consume: get the next item in the cpu buffer and
consume it. That is, this function increments the head pointer.
ring_buffer_read_start: Start an iterator of a cpu buffer.
For now, this disables the cpu buffer, until you issue a finish. This is just because we do not want the iterator to be overwritten. This restriction may change in the future. But note, this is used for static reading of a buffer which is usually done "after" a trace. Live readings would want to use thering_buffer_consumeabove, which will not disable the ring buffer.
ring_buffer_read_finish: Finishes the read iterator and reenables
the ring buffer.
ring_buffer_iter_peek: Look at the next item in the cpu iterator.ring_buffer_read: Read the iterator and increment it.ring_buffer_iter_reset: Reset the iterator to point to the beginning
of the cpu buffer.ring_buffer_iter_empty: Returns true if the iterator is at the end
of the cpu buffer.
ring_buffer_size: returns the size in bytes of each cpu buffer.
Note, the real size is this times the number of CPUs.
ring_buffer_reset_cpu: Sets the cpu buffer to emptyring_buffer_reset: sets all cpu buffers to empty
ring_buffer_swap_cpu: swaps a cpu buffer from one buffer with a
cpu buffer of another buffer. This is handy when you want to take a snap shot of a running trace on just one cpu. Having a backup buffer, to swap with facilitates this. Ftrace max latencies use this.
ring_buffer_empty: Returns true if the ring buffer is empty.ring_buffer_empty_cpu: Returns true if the cpu buffer is empty.
ring_buffer_record_disable: disable all cpu buffers (read only)ring_buffer_record_disable_cpu: disable a single cpu buffer (read only)ring_buffer_record_enable: enable all cpu buffers.ring_buffer_record_enabl_cpu: enable a single cpu buffer.
ring_buffer_entries: The number of entries in a ring buffer.ring_buffer_overruns: The number of entries removed due to writing wrap.
ring_buffer_time_stamp: Get the time stamp used by the ring bufferring_buffer_normalize_time_stamp: normalize the ring buffer time stamp
into nanosecs.I still need to implement the GTOD feature. But we need support from the cpu frequency infrastructure. But this can be done at a later time without affecting the ring buffer interface.
Signed-off-by Steven Rostedt <[email protected]>--- include/linux/ring_buffer.h | 178 +++++ kernel/trace/Kconfig | 4 kernel/trace/Makefile | 1 kernel/trace/ring_buffer.c | 1491 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1674 insertions(+)Index:
linux-trace.git/include/linux/ring_buffer.h
===================================================================include/linux/ring_buffer.h new file +6
-0@@ -0,0 +1,178 @@ +#ifndef _LINUX_RING_BUFFER_H +#define _LINUX_RING_BUFFER_H + +#include <linux/mm.h> +#include <linux/seq_file.h> +
include/linux/ring_buffer.h line 16
Quoted 10 lines
include/linux/ring_buffer.h new file +10
-0+struct ring_buffer ; +struct ring_buffer_iter ; + +/* +* Don't reference this struct directly, use the inline items below. +*/ +struct ring_buffer_event { +u32 type:2 , len:3 , time_delta:27 ; +u32 array[]; +} __attribute__((__packed__ ));
Why do you need __packed__ here? With or without it the layout is the same:
[acme@doppio examples]$ pahole packed
struct ring_buffer_event {
u32 type:2; /* 0:30 4 */
u32 len:3; /* 0:27 4 */
u32 time_delta:27; /* 0: 0 4 */
u32 array[0]; /* 4 0 */
/* size: 4, cachelines: 1, members: 4 */
/* last cacheline: 4 bytes */
};- Arnaldo
Quoted 3 lines · Arnaldo Carvalho de Melo
Why do you need
__packed__here? With or without it the layout is the same:
Indeed. And on some architectures 'packed' will actually mean that the compiler may think that it's unaligned, and then generate much worse code to access the fields. So if you align things anyway (and you do), then 'packed' is the wrong thing to do.
Linus
Steven Rostedt
maintainerQuoted 6 lines · Linus Torvalds
Quoted 2 lines · Arnaldo Carvalho de Melo
Why do you need
__packed__here? With or without it the layout is the
Quoted 8 lines
From just being paranoid.
Quoted 1 line
same:
Indeed. And on some architectures 'packed' will actually mean that the compiler may think that it's unaligned, and then generate much worse code to access the fields. So if you align things anyway (and you do), then 'packed' is the wrong thing to do.
OK, I'm making v6 now with various cleanups. I'll nuke it on that one.
-- Steve
Quoted 6 lines · Steven Rostedt
Quoted 4 lines
Indeed. And on some architectures 'packed' will actually mean that the compiler may think that it's unaligned, and then generate much worse code to access the fields. So if you align things anyway (and you do), then 'packed' is the wrong thing to do.
OK, I'm making v6 now with various cleanups. I'll nuke it on that one.
btw., now that it's getting into shape, could you please fix the ftrace portion:
Quoted 7 lines
Subject: [RFC PATCH 2/2 v3] ftrace: make work with new ring buffer
Note: This patch is a proof of concept, and breaks a lot of functionality of ftrace.
This patch simply makes ftrace work with the developmental ring buffer.
... to not have known bugs, so that we could try it in tip/ftrace and make sure it works well in practice?
it's a ton of changes already, it would be nice to get to some stable known-working state and do delta patches from that point on, and keep its 'works well' quality.
Ingo
Steven Rostedt
maintainerQuoted 10 lines · Ingo Molnar
Quoted 7 lines · Steven Rostedt
Subject: [RFC PATCH 2/2 v3] ftrace: make work with new ring buffer
Note: This patch is a proof of concept, and breaks a lot of functionality of ftrace.
This patch simply makes ftrace work with the developmental ring buffer.
Quoted 6 lines
... to not have known bugs, so that we could try it in tip/ftrace and make sure it works well in practice?
it's a ton of changes already, it would be nice to get to some stable known-working state and do delta patches from that point on, and keep its 'works well' quality.
OK, the patch that I was using was against Linus's tree. I'll port it over to linux-tip on Monday and get it past the "proof of concept" stage. Actually, the verison I have on my desk works pretty well. The main issues to solve is that some other tracers and the self test stick their noses into the buffering system, which would need to be fixed.
There's also some bugs in the status numbers printed in the latency_trace header. But I have not hit any bugs with the buffering itself.
I'll clean all this up and send out a patch on Monday. My wife is mandating that I do not do anymore work over the weekend ;-)
-- Steve
Steven Rostedt
maintainerPATCH v6 1/1 Unified trace buffer
In reply to Steven Rostedt[
Changes since v5:
- removed packed attribute from event structure.
- added parenthesis around ~TS_MASK
- fixed some comments in header
- fixed ret value on ring_buffer_write on errors.
- added check_pages when modifying the size of cpu buffers
]
This is a unified tracing buffer that implements a ring buffer that hopefully everyone will eventually be able to use.
The events recorded into the buffer have the following structure:
struct ring_buffer_event {
u32 type:2, len:3, time_delta:27;
u32 array[];
};The minimum size of an event is 8 bytes. All events are 4 byte aligned inside the buffer.
There are 4 types (all internal use for the ring buffer, only the data type is exported to the interface users).
RB_TYPE_PADDING: this type is used to note extra space at the end
of a buffer page.
RB_TYPE_TIME_EXTENT: This type is used when the time between events
is greater than the 27 bit delta can hold. We add another 32 bits, and record that in its own event (8 byte size).
RB_TYPE_TIME_STAMP: (Not implemented yet). This will hold data to
help keep the buffer timestamps in sync.
RB_TYPE_DATA: The event actually holds user data.
The "len" field is only three bits. Since the data must be 4 byte aligned, this field is shifted left by 2, giving a max length of 28 bytes. If the data load is greater than 28 bytes, the first array field holds the full length of the data load and the len field is set to zero.
Example, data size of 7 bytes:
type = RB_TYPE_DATA len = 2 time_delta: <time-stamp> - <prev_event-time-stamp> array[0..1]: <7 bytes of data> <1 byte empty>
This event is saved in 12 bytes of the buffer.
An event with 82 bytes of data:
type = RB_TYPE_DATA
len = 0
time_delta: <time-stamp> - <prev_event-time-stamp> array[0]: 84 (Note the alignment) array[1..14]: <82 bytes of data> <2 bytes empty>
The above event is saved in 92 bytes (if my math is correct). 82 bytes of data, 2 bytes empty, 4 byte header, 4 byte length.
Do not reference the above event struct directly. Use the following functions to gain access to the event table, since the ring_buffer_event structure may change in the future.
ring_buffer_event_length(event): get the length of the event.
This is the size of the memory used to record this event, and not the size of the data pay load.
ring_buffer_time_delta(event): get the time delta of the event
This returns the delta time stamp since the last event.
Note: Even though this is in the header, there should
be no reason to access this directly, accept for debugging.
ring_buffer_event_data(event): get the data from the event
This is the function to use to get the actual data from the event. Note, it is only a pointer to the data inside the buffer. This data must be copied to another location otherwise you risk it being written over in the buffer.
ring_buffer_lock: A way to lock the entire buffer.ring_buffer_unlock: unlock the buffer.
ring_buffer_alloc: create a new ring buffer. Can choose between
overwrite or consumer/producer mode. Overwrite will overwrite old data, where as consumer producer will throw away new data if the consumer catches up with the producer. The consumer/producer is the default.
ring_buffer_free: free the ring buffer.
ring_buffer_resize: resize the buffer. Changes the size of each cpu
buffer. Note, it is up to the caller to provide that the buffer is not being used while this is happening. This requirement may go away but do not count on it.
ring_buffer_lock_reserve: locks the ring buffer and allocates an
entry on the buffer to write to.ring_buffer_unlock_commit: unlocks the ring buffer and commits it to
the buffer.
ring_buffer_write: writes some data into the ring buffer.
ring_buffer_peek: Look at a next item in the cpu buffer.ring_buffer_consume: get the next item in the cpu buffer and
consume it. That is, this function increments the head pointer.
ring_buffer_read_start: Start an iterator of a cpu buffer.
For now, this disables the cpu buffer, until you issue a finish. This is just because we do not want the iterator to be overwritten. This restriction may change in the future. But note, this is used for static reading of a buffer which is usually done "after" a trace. Live readings would want to use the ring_buffer_consume above, which will not disable the ring buffer.
ring_buffer_read_finish: Finishes the read iterator and reenables
the ring buffer.
ring_buffer_iter_peek: Look at the next item in the cpu iterator.ring_buffer_read: Read the iterator and increment it.ring_buffer_iter_reset: Reset the iterator to point to the beginning
of the cpu buffer.ring_buffer_iter_empty: Returns true if the iterator is at the end
of the cpu buffer.
ring_buffer_size: returns the size in bytes of each cpu buffer.
Note, the real size is this times the number of CPUs.
ring_buffer_reset_cpu: Sets the cpu buffer to emptyring_buffer_reset: sets all cpu buffers to empty
ring_buffer_swap_cpu: swaps a cpu buffer from one buffer with a
cpu buffer of another buffer. This is handy when you want to take a snap shot of a running trace on just one cpu. Having a backup buffer, to swap with facilitates this. Ftrace max latencies use this.
ring_buffer_empty: Returns true if the ring buffer is empty.ring_buffer_empty_cpu: Returns true if the cpu buffer is empty.
ring_buffer_record_disable: disable all cpu buffers (read only) ring_buffer_record_disable_cpu: disable a single cpu buffer (read only)ring_buffer_record_enable: enable all cpu buffers. ring_buffer_record_enabl_cpu: enable a single cpu buffer.
ring_buffer_entries: The number of entries in a ring buffer.ring_buffer_overruns: The number of entries removed due to writing wrap.
ring_buffer_time_stamp: Get the time stamp used by the ring buffer ring_buffer_normalize_time_stamp: normalize the ring buffer time stamp
into nanosecs.
I still need to implement the GTOD feature. But we need support from the cpu frequency infrastructure. But this can be done at a later time without affecting the ring buffer interface.
--- include/linux/ring_buffer.h | 179 +++++ kernel/trace/Kconfig | 4 kernel/trace/Makefile | 1 kernel/trace/ring_buffer.c | 1496 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1680 insertions(+)
include/linux/ring_buffer.h new file +179 -0
@@ -0,0 +1,179 @@ +#ifndef _LINUX_RING_BUFFER_H +#define _LINUX_RING_BUFFER_H + +#include <linux/mm.h> +#include <linux/seq_file.h> + +struct ring_buffer ; +struct ring_buffer_iter ; + +/* +* Don't reference this struct directly, use the inline items below. +*/ +struct ring_buffer_event { +u32 type:2 , len:3 , time_delta:27 ; +u32 array[]; +}; + +enum { +RB_TYPE_PADDING ,/* Left over page padding +* array is ignored +* size is variable depending on +* how much padding is needed +*/ +RB_TYPE_TIME_EXTENT ,/* Extent the time delta +* array[0] = time delta (28 .. 59) +* size = 8 bytes +*/ +/* FIXME: RB_TYPE_TIME_STAMP not implemented */ +RB_TYPE_TIME_STAMP ,/* Sync time stamp with external clock +* array[0] = tv_nsec +* array[1] = tv_sec +* size = 16 bytes +*/ + +RB_TYPE_DATA ,/* Data record +* If len is zero: +* array[0] holds the actual length +* array[1..(length+3)/4-1] holds data +* else +* length = len << 2 +* array[0..(length+3)/4] holds data +*/ +}; + +#define RB_EVNT_HDR_SIZE (sizeof(struct ring_buffer_event)) +#define RB_ALIGNMENT_SHIFT 2 +#define RB_ALIGNMENT (1 << RB_ALIGNMENT_SHIFT) +#define RB_MAX_SMALL_DATA (28) + +enum { +RB_LEN_TIME_EXTENT =8 , +RB_LEN_TIME_STAMP =16 , +}; + +/** +* ring_buffer_event_length - return the length of the event +* @event: the event to get the length of +*/ +static inline unsigned +ring_buffer_event_length (struct ring_buffer_event *event) +{ +unsigned length; + +switch (event->type) { +case RB_TYPE_PADDING : +/* undefined */ +return -1 ; + +case RB_TYPE_TIME_EXTENT : +return RB_LEN_TIME_EXTENT ; + +case RB_TYPE_TIME_STAMP : +return RB_LEN_TIME_STAMP ; + +case RB_TYPE_DATA : +if (event->len) + length = event->len <<RB_ALIGNMENT_SHIFT ; +else + length = event->array[0 ]; +return length +RB_EVNT_HDR_SIZE ; +default : +BUG (); + } +/* not hit */ +return 0 ; +} + +/** +* ring_buffer_event_time_delta - return the delta timestamp of the event +* @event: the event to get the delta timestamp of +* +* The delta timestamp is the 27 bit timestamp since the last event. +*/ +static inline unsigned +ring_buffer_event_time_delta (struct ring_buffer_event *event) +{ +return event->time_delta; +} + +/** +* ring_buffer_event_data - return the data of the event +* @event: the event to get the data from +*/ +static inline void * +ring_buffer_event_data (struct ring_buffer_event *event) +{ +BUG_ON (event->type !=RB_TYPE_DATA ); +/* If length is in len field, then array[0] has the data */ +if (event->len) +return (void *)&event->array[0 ]; +/* Otherwise length is in array[0] and array[1] has the data */ +return (void *)&event->array[1 ]; +} + +void ring_buffer_lock (struct ring_buffer *buffer,unsigned long *flags); +void ring_buffer_unlock (struct ring_buffer *buffer,unsigned long flags); + +/* +* size is in bytes for each per CPU buffer. +*/ +struct ring_buffer * +ring_buffer_alloc (unsigned long size,unsigned flags); +void ring_buffer_free (struct ring_buffer *buffer); + +int ring_buffer_resize (struct ring_buffer *buffer,unsigned long size); + +struct ring_buffer_event * +ring_buffer_lock_reserve (struct ring_buffer *buffer, +unsigned long length, +unsigned long *flags); +int ring_buffer_unlock_commit (struct ring_buffer *buffer, +struct ring_buffer_event *event, +unsigned long flags); +int ring_buffer_write (struct ring_buffer *buffer, +unsigned long length,void *data); + +struct ring_buffer_event * +ring_buffer_peek (struct ring_buffer *buffer,int cpu,u64 *ts); +struct ring_buffer_event * +ring_buffer_consume (struct ring_buffer *buffer,int cpu,u64 *ts); + +struct ring_buffer_iter * +ring_buffer_read_start (struct ring_buffer *buffer,int cpu); +void ring_buffer_read_finish (struct ring_buffer_iter *iter); + +struct ring_buffer_event * +ring_buffer_iter_peek (struct ring_buffer_iter *iter,u64 *ts); +struct ring_buffer_event * +ring_buffer_read (struct ring_buffer_iter *iter,u64 *ts); +void ring_buffer_iter_reset (struct ring_buffer_iter *iter); +int ring_buffer_iter_empty (struct ring_buffer_iter *iter); + +unsigned long ring_buffer_size (struct ring_buffer *buffer); + +void ring_buffer_reset_cpu (struct ring_buffer *buffer,int cpu); +void ring_buffer_reset (struct ring_buffer *buffer); + +int ring_buffer_swap_cpu (struct ring_buffer *buffer_a, +struct ring_buffer *buffer_b,int cpu); + +int ring_buffer_empty (struct ring_buffer *buffer); +int ring_buffer_empty_cpu (struct ring_buffer *buffer,int cpu); + +void ring_buffer_record_disable (struct ring_buffer *buffer); +void ring_buffer_record_enable (struct ring_buffer *buffer); +void ring_buffer_record_disable_cpu (struct ring_buffer *buffer,int cpu); +void ring_buffer_record_enable_cpu (struct ring_buffer *buffer,int cpu); + +unsigned long ring_buffer_entries (struct ring_buffer *buffer); +unsigned long ring_buffer_overruns (struct ring_buffer *buffer); + +u64 ring_buffer_time_stamp (int cpu); +void ring_buffer_normalize_time_stamp (int cpu,u64 *ts); + +enum ring_buffer_flags { +RB_FL_OVERWRITE =1 <<0 , +}; + +#endif /* _LINUX_RING_BUFFER_H */
kernel/trace/ring_buffer.c new file +1496 -0
1,496 lines not on this page · raw message
kernel/trace/Kconfig +4 -0
@@ -10,10 +10,14 @@ config HAVE_DYNAMIC_FTRACE config TRACER_MAX_TRACE bool +config RING_BUFFER + bool + config TRACING bool select DEBUG_FS select STACKTRACE + select RING_BUFFER config FTRACE bool "Kernel Function Tracer"
kernel/trace/Makefile +1 -0
@@ -11,6 +11,7 @@ obj-y += trace_selftest_dynamic.o endif obj-$(CONFIG_FTRACE) += libftrace.o +obj-$(CONFIG_RING_BUFFER) += ring_buffer.o obj-$(CONFIG_TRACING) += trace.o obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
Quoted 5 lines · Steven Rostedt
ring_buffer_alloc: create a new ring buffer. Can choose between overwrite or consumer/producer mode. Overwrite will overwrite old data, where as consumer producer will throw away new data if the consumer catches up with the producer. The consumer/producer is the default.
Forgive me if I've gotten this wrong but the terminology seems backwards Here, I would think we only throw away new data if the producer catches up with the consumer, if the consumer catches up with the producer we're reading data as fast as it's being written.
Quoted 7 lines
ring_buffer_write: writes some data into the ring buffer.
ring_buffer_peek: Look at a next item in the cpu buffer.ring_buffer_consume: get the next item in the cpu buffer and consume it. That is, this function increments the head pointer.
Here too, I would think that consuming data would modify the tail pointer.
Quoted 2 lines
Signed-off-by Steven Rostedt <[email protected]>
Just trying to understand the terminology before I look at the code so I'm sorry if I have just completely misunderstood.
-Richard Holden
Steven Rostedt
maintainerQuoted 8 lines · Richard Holden
Quoted 5 lines · Steven Rostedt
ring_buffer_alloc: create a new ring buffer. Can choose between overwrite or consumer/producer mode. Overwrite will overwrite old data, where as consumer producer will throw away new data if the consumer catches up with the producer. The consumer/producer is the default.
Quoted 4 lines
Forgive me if I've gotten this wrong but the terminology seems backwards Here, I would think we only throw away new data if the producer catches up with the consumer, if the consumer catches up with the producer we're reading data as fast as it's being written.
Argh! Yes. I'm the one that is backwards ;-)
Yeah, that is what I meant. Don't you know? You are suppose to understand what I mean, not what I say :)
Quoted 10 lines
Quoted 8 lines
ring_buffer_write: writes some data into the ring buffer.
ring_buffer_peek: Look at a next item in the cpu buffer.ring_buffer_consume: get the next item in the cpu buffer and consume it. That is, this function increments the head pointer.Here too, I would think that consuming data would modify the tail pointer.
I always get confused with the translation of what the head/tail to producer/consumer.
Here I have the producer adding to the tail, and the consumer reading from the head. Perhaps this is backwards? I could change it.
s/head/foobar/g
s/tail/head/g
s/foobar/tail/g
That could do it.
Quoted 5 lines
Quoted 2 lines
Signed-off-by Steven Rostedt <[email protected]>Just trying to understand the terminology before I look at the code so I'm sorry if I have just completely misunderstood.
Sure, thanks.
-- Steve
kernel/trace/ring_buffer.c line 49
Quoted 6 lines · Steven Rostedt
kernel/trace/ring_buffer.c new file +6
-0+struct buffer_page { +u64 time_stamp; +unsigned char body[]; +}; + +#define BUF_PAGE_SIZE (PAGE_SIZE - sizeof(u64))
Since you're already using the page frame, you can stick this per page timestamp in there as well, and get the full page for data.
You can either use a struct page overlay like slob does, or add a u64 in the union that contains struct {private, mapping}.
Quoted 12 lines · Peter Zijlstra
kernel/trace/ring_buffer.c line 49
Quoted 6 lines · Steven Rostedt
kernel/trace/ring_buffer.c new file +6
-0+struct buffer_page { +u64 time_stamp; +unsigned char body[]; +}; + +#define BUF_PAGE_SIZE (PAGE_SIZE - sizeof(u64))Since you're already using the page frame, you can stick this per page timestamp in there as well, and get the full page for data.
Quoted 2 lines
You can either use a struct page overlay like slob does, or add a u64 in the union that contains struct {private, mapping}.
What did you guys think of Mathieu's idea of sticking the buffer length in the header here, rather than using padding events? Seemed cleaner to me.
Steven Rostedt
maintainerQuoted 13 lines · Martin Bligh
Quoted 12 lines · Peter Zijlstra
kernel/trace/ring_buffer.c line 49
Quoted 6 lines · Steven Rostedt
kernel/trace/ring_buffer.c new file +6
-0+struct buffer_page { +u64 time_stamp; +unsigned char body[]; +}; + +#define BUF_PAGE_SIZE (PAGE_SIZE - sizeof(u64))Since you're already using the page frame, you can stick this per page timestamp in there as well, and get the full page for data.
Quoted 6 lines
Quoted 2 lines
You can either use a struct page overlay like slob does, or add a u64 in the union that contains struct {private, mapping}.
What did you guys think of Mathieu's idea of sticking the buffer length in the header here, rather than using padding events? Seemed cleaner to me.
Actually I like the padding. This way when I move the event pointer forward, I only need to compare it to a constant (PAGE_SIZE), or test to see if the event is padding. Placing this into the buffer page, I will have to always compare it to that pointer.
But I guess I could change it to that if needed. That doesn't affect the API, as it is only internal.
I'm almost done with v7, perhaps I might try that with v8 to see if I like it better.
-- Steve
Steven Rostedt
maintainerQuoted 5 lines · Martin Bligh
What did you guys think of Mathieu's idea of sticking the buffer length in the header here, rather than using padding events? Seemed cleaner to me.
OK, I just implemented the size field in the page struct. Seems to work well. I'm still keeping the padded event, so in the future, if we ever map these pages to userspace or files, these holes will have a type.
Will post later today, need to actually enter a real life for a bit.
-- Steve
kernel/trace/ring_buffer.c line 81
Quoted 11 lines · Steven Rostedt
kernel/trace/ring_buffer.c new file +11
-0+struct ring_buffer { +unsigned long size; +unsigned pages; +unsigned flags; +int cpus; +atomic_t record_disabled; + +struct mutex mutex; + +/* FIXME: this should be online CPUS */ +struct ring_buffer_per_cpu *buffers[NR_CPUS ];
actually nr_possible makes sense, and you might consider always allocating buffers (and keeping them for offlined cpus) to avoid massive allocations/frees cpu-hotplug events.
Mike Travis has been going over the kernel removing constructs like this, and replacing them with dynamically allocated arrays of nr_possible.
Quoted 1 line
+};
Quoted 17 lines · Peter Zijlstra
kernel/trace/ring_buffer.c line 81
Quoted 11 lines · Steven Rostedt
kernel/trace/ring_buffer.c new file +11
-0+struct ring_buffer { +unsigned long size; +unsigned pages; +unsigned flags; +int cpus; +atomic_t record_disabled; + +struct mutex mutex; + +/* FIXME: this should be online CPUS */ +struct ring_buffer_per_cpu *buffers[NR_CPUS ];actually
nr_possiblemakes sense, and you might consider always allocating buffers (and keeping them for offlined cpus) to avoid massive allocations/frees cpu-hotplug events.
Quoted 5 lines
Mike Travis has been going over the kernel removing constructs like this, and replacing them with dynamically allocated arrays of
nr_possible.Quoted 1 line
+};
The other thing to consider is using a percpu variable.
Cheers,
Mike
Steven Rostedt
maintainerQuoted 18 lines · Mike Travis
Quoted 17 lines · Peter Zijlstra
kernel/trace/ring_buffer.c line 81
Quoted 11 lines · Steven Rostedt
kernel/trace/ring_buffer.c new file +11
-0+struct ring_buffer { +unsigned long size; +unsigned pages; +unsigned flags; +int cpus; +atomic_t record_disabled; + +struct mutex mutex; + +/* FIXME: this should be online CPUS */ +struct ring_buffer_per_cpu *buffers[NR_CPUS ];actually
nr_possiblemakes sense, and you might consider always allocating buffers (and keeping them for offlined cpus) to avoid massive allocations/frees cpu-hotplug events.
Quoted 7 lines
Quoted 5 lines
Mike Travis has been going over the kernel removing constructs like this, and replacing them with dynamically allocated arrays of
nr_possible.Quoted 1 line
+};
The other thing to consider is using a percpu variable.
This structure is allocated on request.
-- Steve
Quoted 23 lines · Steven Rostedt
Quoted 21 lines · Mike Travis
Quoted 20 lines · Peter Zijlstra
kernel/trace/ring_buffer.c line 81
Quoted 11 lines · Steven Rostedt
kernel/trace/ring_buffer.c new file +11
-0+struct ring_buffer { +unsigned long size; +unsigned pages; +unsigned flags; +int cpus; +atomic_t record_disabled; + +struct mutex mutex; + +/* FIXME: this should be online CPUS */ +struct ring_buffer_per_cpu *buffers[NR_CPUS ];actually
nr_possiblemakes sense, and you might consider always allocating buffers (and keeping them for offlined cpus) to avoid massive allocations/frees cpu-hotplug events.Mike Travis has been going over the kernel removing constructs like this, and replacing them with dynamically allocated arrays of
nr_possible.
Quoted 6 lines
Quoted 2 lines
Quoted 1 line
Quoted 1 line
+};
The other thing to consider is using a percpu variable.
This structure is allocated on request.
-- Steve
Ahh, then it would need the yet to be added cpu_alloc() from Christoph.
Your best bet then is to allocate based on nr_cpu_ids.
Cheers,
Mike
Steven Rostedt
maintainerQuoted 9 lines · Mike Travis
Quoted 5 lines · Steven Rostedt
Quoted 1 line
The other thing to consider is using a percpu variable.
This structure is allocated on request.
-- Steve
Ahh, then it would need the yet to be added
cpu_alloc()from Christoph.
We can always change this later.
Quoted 2 lines
Your best bet then is to allocate based on
nr_cpu_ids.
Actually in this case I chose num_possible_cpus(). Reason being is that later I may add an interface to allow the user to select which CPUs they want to trace, and this will only allocate a subset of CPU buffers. (not going to implement that in the first release).
But to lay the ground work, I set a buffers->cpumask to be that of all the cpus with buffers allocated. For now that mask is set to cpu_possible_map. Since num_possible_cpus() is defined as cpus_weight_nr(cpu_possible_map) I figured that was the better choice.
-- Steve
Quoted 18 lines · Steven Rostedt
Quoted 7 lines · Mike Travis
Quoted 4 lines · Steven Rostedt
Quoted 1 line
The other thing to consider is using a percpu variable.
This structure is allocated on request.
-- Steve
Ahh, then it would need the yet to be added
cpu_alloc()from Christoph.We can always change this later.
Quoted 1 line
Your best bet then is to allocate based on
nr_cpu_ids.Actually in this case I chose
num_possible_cpus(). Reason being is that later I may add an interface to allow the user to select which CPUs they want to trace, and this will only allocate a subset of CPU buffers. (not going to implement that in the first release).
Quoted 6 lines
But to lay the ground work, I set a
buffers->cpumaskto be that of all the cpus with buffers allocated. For now that mask is set tocpu_possible_map. Sincenum_possible_cpus()is defined ascpus_weight_nr(cpu_possible_map)I figured that was the better choice.-- Steve
One problem though, it's *theoretically* possible for num_possible to be less than nr_cpu_ids and a cpu index may extend past the end of your allocated array. This would happen if the cpu indices are allocated some other way than as each cpu is discovered. For example, a system might want a group of cpus in one section (say by node, or socket) and then a hole in the cpu_possible_map until the next group. nr_cpu_ids is guaranteed to be the highest possible cpu + 1.
Cheers,
Mike
Steven Rostedt
maintainerQuoted 9 lines · Mike Travis
Quoted 7 lines · Steven Rostedt
But to lay the ground work, I set a
buffers->cpumaskto be that of all the cpus with buffers allocated. For now that mask is set tocpu_possible_map. Sincenum_possible_cpus()is defined ascpus_weight_nr(cpu_possible_map)I figured that was the better choice.-- Steve
Quoted 7 lines
One problem though, it's *theoretically* possible for
num_possibleto be less thannr_cpu_idsand a cpu index may extend past the end of your allocated array. This would happen if the cpu indices are allocated some other way than as each cpu is discovered. For example, a system might want a group of cpus in one section (say by node, or socket) and then a hole in thecpu_possible_mapuntil the next group.nr_cpu_idsis guaranteed to be the highest possible cpu + 1.
Thanks for the explanation. I'll change buffer->cpus to be set to nr_cpu_ids.
-- Steve
kernel/trace/ring_buffer.c line 96
Quoted 6 lines · Steven Rostedt
kernel/trace/ring_buffer.c new file +6
-0+#define CHECK_COND (buffer, cond) \ + if (unlikely(cond)) { \ + atomic_inc(&buffer->record_disabled); \ + WARN_ON(1); \ + return -1; \ + }
Arjan, any preferences wrt kerneloops.org?
Quoted 9 lines · On Fri, 26 Sep 2008 21:17:13 +0200 Peter Zijlstra <[email protected]> wrote:
kernel/trace/ring_buffer.c line 96
Quoted 6 lines · Steven Rostedt
kernel/trace/ring_buffer.c new file +6
-0+#define CHECK_COND (buffer, cond) \ + if (unlikely(cond)) { \ + atomic_inc(&buffer->record_disabled); \ + WARN_ON(1); \ + return -1; \ + }Arjan, any preferences wrt kerneloops.org?
this works; if you also want to print something use WARN() instead
Quoted 1 line
Signature · 3 lines
Arjan van de Ven Intel Open Source Technology Centre For development, discussion and tips for power savings, visit http://www.lesswatts.org
kernel/trace/ring_buffer.c line 278
Quoted 9 lines · Steven Rostedt
(quoted diff) +2
-0+static void +rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned
nr_pages)kernel/trace/ring_buffer.c new file +6
-0+{ +struct page *page; +struct list_head *p; +unsigned i; + +atomic_inc (&cpu_buffer->record_disabled);
You probably want synchronize_sched() here (and similar other places) to ensure any active writer on the corresponding cpu is actually stopped.
Which suggests you want to use something like ring_buffer_lock_cpu() and implement that as above.
Quoted 16 lines
kernel/trace/ring_buffer.c new file +16
-0+for (i =0 ; i < nr_pages; i++) { +BUG_ON (list_empty (&cpu_buffer->pages)); + p = cpu_buffer->pages.next; + page = list_entry(p, struct page, lru); +list_del_init (&page->lru); +__free_page (page); + } +BUG_ON (list_empty (&cpu_buffer->pages)); + +__ring_buffer_reset_cpu (cpu_buffer); + +check_pages (cpu_buffer); + +atomic_dec (&cpu_buffer->record_disabled); + +}
Quoted 13 lines · Peter Zijlstra
kernel/trace/ring_buffer.c line 278
Quoted 9 lines · Steven Rostedt
(quoted diff) +2
-0+static void +rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned
nr_pages)kernel/trace/ring_buffer.c new file +6
-0+{ +struct page *page; +struct list_head *p; +unsigned i; + +atomic_inc (&cpu_buffer->record_disabled);You probably want
synchronize_sched()here (and similar other places) to ensure any active writer on the corresponding cpu is actually stopped.
Would it really be done in the buffer layer?
I think it should be done by each tracer, because buffer layer can't ensure truly active writers have stopped.
Thank you,
Quoted 21 lines
Which suggests you want to use something like
ring_buffer_lock_cpu()and implement that as above.Quoted 16 lines
kernel/trace/ring_buffer.c new file +16
-0+for (i =0 ; i < nr_pages; i++) { +BUG_ON (list_empty (&cpu_buffer->pages)); + p = cpu_buffer->pages.next; + page = list_entry(p, struct page, lru); +list_del_init (&page->lru); +__free_page (page); + } +BUG_ON (list_empty (&cpu_buffer->pages)); + +__ring_buffer_reset_cpu (cpu_buffer); + +check_pages (cpu_buffer); + +atomic_dec (&cpu_buffer->record_disabled); + +}
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Steven Rostedt
maintainerQuoted 15 lines · Masami Hiramatsu
Quoted 13 lines · Peter Zijlstra
kernel/trace/ring_buffer.c line 278
Quoted 9 lines · Steven Rostedt
(quoted diff) +2
-0+static void +rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned
nr_pages)kernel/trace/ring_buffer.c new file +6
-0+{ +struct page *page; +struct list_head *p; +unsigned i; + +atomic_inc (&cpu_buffer->record_disabled);You probably want
synchronize_sched()here (and similar other places) to ensure any active writer on the corresponding cpu is actually stopped.
Quoted 4 lines
Would it really be done in the buffer layer?
I think it should be done by each tracer, because buffer layer can't ensure truly active writers have stopped.
Actually it can ;-)
Since all writes to the buffer at least disable preemption, by issuing a synchronize_sched, we can guarantee that after disabling the record, all activity will be done.
-- Steve
Steven Rostedt
maintainerPATCH v7 1/1 Unified trace buffer
In reply to Steven Rostedt[
Changes since v6:
- Added shift debug test to test both normalization of timestamp, but also the large time deltas. ftrace records too quickly to get large deltas :-/
- Fixed some minor issues with keeping track of time.
- used slob hack to put more information in the page struct and now have the full buffer page free for data. Thanks to Peter Zijlstra for suggesting the idea.
- have the buffer use a cpu mask (initialized to cpu_possible_map) to allocate for cpu usage.
- fixed entries counting.
- use DIV_ROUND_UP macro (also suggested by Peter)
]
This is a unified tracing buffer that implements a ring buffer that hopefully everyone will eventually be able to use.
The events recorded into the buffer have the following structure:
struct ring_buffer_event {
u32 type:2, len:3, time_delta:27;
u32 array[];
};The minimum size of an event is 8 bytes. All events are 4 byte aligned inside the buffer.
There are 4 types (all internal use for the ring buffer, only the data type is exported to the interface users).
RB_TYPE_PADDING: this type is used to note extra space at the end
of a buffer page.
RB_TYPE_TIME_EXTENT: This type is used when the time between events
is greater than the 27 bit delta can hold. We add another 32 bits, and record that in its own event (8 byte size).
RB_TYPE_TIME_STAMP: (Not implemented yet). This will hold data to
help keep the buffer timestamps in sync.
RB_TYPE_DATA: The event actually holds user data.
The "len" field is only three bits. Since the data must be 4 byte aligned, this field is shifted left by 2, giving a max length of 28 bytes. If the data load is greater than 28 bytes, the first array field holds the full length of the data load and the len field is set to zero.
Example, data size of 7 bytes:
type = RB_TYPE_DATA len = 2 time_delta: <time-stamp> - <prev_event-time-stamp> array[0..1]: <7 bytes of data> <1 byte empty>
This event is saved in 12 bytes of the buffer.
An event with 82 bytes of data:
type = RB_TYPE_DATA
len = 0
time_delta: <time-stamp> - <prev_event-time-stamp> array[0]: 84 (Note the alignment) array[1..14]: <82 bytes of data> <2 bytes empty>
The above event is saved in 92 bytes (if my math is correct). 82 bytes of data, 2 bytes empty, 4 byte header, 4 byte length.
Do not reference the above event struct directly. Use the following functions to gain access to the event table, since the ring_buffer_event structure may change in the future.
ring_buffer_event_length(event): get the length of the event.
This is the size of the memory used to record this event, and not the size of the data pay load.
ring_buffer_time_delta(event): get the time delta of the event
This returns the delta time stamp since the last event.
Note: Even though this is in the header, there should
be no reason to access this directly, accept for debugging.
ring_buffer_event_data(event): get the data from the event
This is the function to use to get the actual data from the event. Note, it is only a pointer to the data inside the buffer. This data must be copied to another location otherwise you risk it being written over in the buffer.
ring_buffer_lock: A way to lock the entire buffer.ring_buffer_unlock: unlock the buffer.
ring_buffer_alloc: create a new ring buffer. Can choose between
overwrite or consumer/producer mode. Overwrite will overwrite old data, where as consumer producer will throw away new data if the consumer catches up with the producer. The consumer/producer is the default.
ring_buffer_free: free the ring buffer.
ring_buffer_resize: resize the buffer. Changes the size of each cpu
buffer. Note, it is up to the caller to provide that the buffer is not being used while this is happening. This requirement may go away but do not count on it.
ring_buffer_lock_reserve: locks the ring buffer and allocates an
entry on the buffer to write to.ring_buffer_unlock_commit: unlocks the ring buffer and commits it to
the buffer.
ring_buffer_write: writes some data into the ring buffer.
ring_buffer_peek: Look at a next item in the cpu buffer.ring_buffer_consume: get the next item in the cpu buffer and
consume it. That is, this function increments the head pointer.
ring_buffer_read_start: Start an iterator of a cpu buffer.
For now, this disables the cpu buffer, until you issue a finish. This is just because we do not want the iterator to be overwritten. This restriction may change in the future. But note, this is used for static reading of a buffer which is usually done "after" a trace. Live readings would want to use the ring_buffer_consume above, which will not disable the ring buffer.
ring_buffer_read_finish: Finishes the read iterator and reenables
the ring buffer.
ring_buffer_iter_peek: Look at the next item in the cpu iterator.ring_buffer_read: Read the iterator and increment it.ring_buffer_iter_reset: Reset the iterator to point to the beginning
of the cpu buffer.ring_buffer_iter_empty: Returns true if the iterator is at the end
of the cpu buffer.
ring_buffer_size: returns the size in bytes of each cpu buffer.
Note, the real size is this times the number of CPUs.
ring_buffer_reset_cpu: Sets the cpu buffer to emptyring_buffer_reset: sets all cpu buffers to empty
ring_buffer_swap_cpu: swaps a cpu buffer from one buffer with a
cpu buffer of another buffer. This is handy when you want to take a snap shot of a running trace on just one cpu. Having a backup buffer, to swap with facilitates this. Ftrace max latencies use this.
ring_buffer_empty: Returns true if the ring buffer is empty.ring_buffer_empty_cpu: Returns true if the cpu buffer is empty.
ring_buffer_record_disable: disable all cpu buffers (read only) ring_buffer_record_disable_cpu: disable a single cpu buffer (read only)ring_buffer_record_enable: enable all cpu buffers. ring_buffer_record_enabl_cpu: enable a single cpu buffer.
ring_buffer_entries: The number of entries in a ring buffer.ring_buffer_overruns: The number of entries removed due to writing wrap.
ring_buffer_time_stamp: Get the time stamp used by the ring buffer ring_buffer_normalize_time_stamp: normalize the ring buffer time stamp
into nanosecs.
I still need to implement the GTOD feature. But we need support from the cpu frequency infrastructure. But this can be done at a later time without affecting the ring buffer interface.
--- include/linux/ring_buffer.h | 179 +++++ kernel/trace/Kconfig | 4 kernel/trace/Makefile | 1 kernel/trace/ring_buffer.c | 1525 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1709 insertions(+)
include/linux/ring_buffer.h new file +179 -0
@@ -0,0 +1,179 @@ +#ifndef _LINUX_RING_BUFFER_H +#define _LINUX_RING_BUFFER_H + +#include <linux/mm.h> +#include <linux/seq_file.h> + +struct ring_buffer ; +struct ring_buffer_iter ; + +/* +* Don't reference this struct directly, use the inline items below. +*/ +struct ring_buffer_event { +u32 type:2 , len:3 , time_delta:27 ; +u32 array[]; +}; + +enum { +RB_TYPE_PADDING ,/* Left over page padding +* array is ignored +* size is variable depending on +* how much padding is needed +*/ +RB_TYPE_TIME_EXTENT ,/* Extent the time delta +* array[0] = time delta (28 .. 59) +* size = 8 bytes +*/ +/* FIXME: RB_TYPE_TIME_STAMP not implemented */ +RB_TYPE_TIME_STAMP ,/* Sync time stamp with external clock +* array[0] = tv_nsec +* array[1] = tv_sec +* size = 16 bytes +*/ + +RB_TYPE_DATA ,/* Data record +* If len is zero: +* array[0] holds the actual length +* array[1..(length+3)/4-1] holds data +* else +* length = len << 2 +* array[0..(length+3)/4] holds data +*/ +}; + +#define RB_EVNT_HDR_SIZE (sizeof(struct ring_buffer_event)) +#define RB_ALIGNMENT_SHIFT 2 +#define RB_ALIGNMENT (1 << RB_ALIGNMENT_SHIFT) +#define RB_MAX_SMALL_DATA (28) + +enum { +RB_LEN_TIME_EXTENT =8 , +RB_LEN_TIME_STAMP =16 , +}; + +/** +* ring_buffer_event_length - return the length of the event +* @event: the event to get the length of +*/ +static inline unsigned +ring_buffer_event_length (struct ring_buffer_event *event) +{ +unsigned length; + +switch (event->type) { +case RB_TYPE_PADDING : +/* undefined */ +return -1 ; + +case RB_TYPE_TIME_EXTENT : +return RB_LEN_TIME_EXTENT ; + +case RB_TYPE_TIME_STAMP : +return RB_LEN_TIME_STAMP ; + +case RB_TYPE_DATA : +if (event->len) + length = event->len <<RB_ALIGNMENT_SHIFT ; +else + length = event->array[0 ]; +return length +RB_EVNT_HDR_SIZE ; +default : +BUG (); + } +/* not hit */ +return 0 ; +} + +/** +* ring_buffer_event_time_delta - return the delta timestamp of the event +* @event: the event to get the delta timestamp of +* +* The delta timestamp is the 27 bit timestamp since the last event. +*/ +static inline unsigned +ring_buffer_event_time_delta (struct ring_buffer_event *event) +{ +return event->time_delta; +} + +/** +* ring_buffer_event_data - return the data of the event +* @event: the event to get the data from +*/ +static inline void * +ring_buffer_event_data (struct ring_buffer_event *event) +{ +BUG_ON (event->type !=RB_TYPE_DATA ); +/* If length is in len field, then array[0] has the data */ +if (event->len) +return (void *)&event->array[0 ]; +/* Otherwise length is in array[0] and array[1] has the data */ +return (void *)&event->array[1 ]; +} + +void ring_buffer_lock (struct ring_buffer *buffer,unsigned long *flags); +void ring_buffer_unlock (struct ring_buffer *buffer,unsigned long flags); + +/* +* size is in bytes for each per CPU buffer. +*/ +struct ring_buffer * +ring_buffer_alloc (unsigned long size,unsigned flags); +void ring_buffer_free (struct ring_buffer *buffer); + +int ring_buffer_resize (struct ring_buffer *buffer,unsigned long size); + +struct ring_buffer_event * +ring_buffer_lock_reserve (struct ring_buffer *buffer, +unsigned long length, +unsigned long *flags); +int ring_buffer_unlock_commit (struct ring_buffer *buffer, +struct ring_buffer_event *event, +unsigned long flags); +int ring_buffer_write (struct ring_buffer *buffer, +unsigned long length,void *data); + +struct ring_buffer_event * +ring_buffer_peek (struct ring_buffer *buffer,int cpu,u64 *ts); +struct ring_buffer_event * +ring_buffer_consume (struct ring_buffer *buffer,int cpu,u64 *ts); + +struct ring_buffer_iter * +ring_buffer_read_start (struct ring_buffer *buffer,int cpu); +void ring_buffer_read_finish (struct ring_buffer_iter *iter); + +struct ring_buffer_event * +ring_buffer_iter_peek (struct ring_buffer_iter *iter,u64 *ts); +struct ring_buffer_event * +ring_buffer_read (struct ring_buffer_iter *iter,u64 *ts); +void ring_buffer_iter_reset (struct ring_buffer_iter *iter); +int ring_buffer_iter_empty (struct ring_buffer_iter *iter); + +unsigned long ring_buffer_size (struct ring_buffer *buffer); + +void ring_buffer_reset_cpu (struct ring_buffer *buffer,int cpu); +void ring_buffer_reset (struct ring_buffer *buffer); + +int ring_buffer_swap_cpu (struct ring_buffer *buffer_a, +struct ring_buffer *buffer_b,int cpu); + +int ring_buffer_empty (struct ring_buffer *buffer); +int ring_buffer_empty_cpu (struct ring_buffer *buffer,int cpu); + +void ring_buffer_record_disable (struct ring_buffer *buffer); +void ring_buffer_record_enable (struct ring_buffer *buffer); +void ring_buffer_record_disable_cpu (struct ring_buffer *buffer,int cpu); +void ring_buffer_record_enable_cpu (struct ring_buffer *buffer,int cpu); + +unsigned long ring_buffer_entries (struct ring_buffer *buffer); +unsigned long ring_buffer_overruns (struct ring_buffer *buffer); + +u64 ring_buffer_time_stamp (int cpu); +void ring_buffer_normalize_time_stamp (int cpu,u64 *ts); + +enum ring_buffer_flags { +RB_FL_OVERWRITE =1 <<0 , +}; + +#endif /* _LINUX_RING_BUFFER_H */
kernel/trace/ring_buffer.c new file +1525 -0
1,525 lines not on this page · raw message
kernel/trace/Kconfig +4 -0
@@ -10,10 +10,14 @@ config HAVE_DYNAMIC_FTRACE config TRACER_MAX_TRACE bool +config RING_BUFFER + bool + config TRACING bool select DEBUG_FS select STACKTRACE + select RING_BUFFER config FTRACE bool "Kernel Function Tracer"
kernel/trace/Makefile +1 -0
@@ -11,6 +11,7 @@ obj-y += trace_selftest_dynamic.o endif obj-$(CONFIG_FTRACE) += libftrace.o +obj-$(CONFIG_RING_BUFFER) += ring_buffer.o obj-$(CONFIG_TRACING) += trace.o obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
Steven Rostedt
maintainerPATCH v8 1/1 Unified trace buffer
[
Changes since v7:
- added the size of data in the page into the page frame. Suggested by Martin Bligh and Mathieu Desnoyers
- Converted all static functions to be named with a rb_ prefix. This may conflict with rbtree functions in the future, but if this does happen, we will need to rename the functions in this file. The rb_ prefixed functions here are all static, so it only affects this code. Thanks to Arnaldo Carvalho de Melo.
- Added some synchronized_sched() where record_disabled is incremented. There are other places that expect the caller to handle it. Suggested by Peter Zijlstra.
- Use nr_cpu_ids for max cpu. Thanks to Mike Travis.
]
This is a unified tracing buffer that implements a ring buffer that hopefully everyone will eventually be able to use.
The events recorded into the buffer have the following structure:
struct ring_buffer_event {
u32 type:2, len:3, time_delta:27;
u32 array[];
};The minimum size of an event is 8 bytes. All events are 4 byte aligned inside the buffer.
There are 4 types (all internal use for the ring buffer, only the data type is exported to the interface users).
RB_TYPE_PADDING: this type is used to note extra space at the end
of a buffer page.
RB_TYPE_TIME_EXTENT: This type is used when the time between events
is greater than the 27 bit delta can hold. We add another 32 bits, and record that in its own event (8 byte size).
RB_TYPE_TIME_STAMP: (Not implemented yet). This will hold data to
help keep the buffer timestamps in sync.
RB_TYPE_DATA: The event actually holds user data.
The "len" field is only three bits. Since the data must be 4 byte aligned, this field is shifted left by 2, giving a max length of 28 bytes. If the data load is greater than 28 bytes, the first array field holds the full length of the data load and the len field is set to zero.
Example, data size of 7 bytes:
type = RB_TYPE_DATA len = 2 time_delta: <time-stamp> - <prev_event-time-stamp> array[0..1]: <7 bytes of data> <1 byte empty>
This event is saved in 12 bytes of the buffer.
An event with 82 bytes of data:
type = RB_TYPE_DATA
len = 0
time_delta: <time-stamp> - <prev_event-time-stamp> array[0]: 84 (Note the alignment) array[1..14]: <82 bytes of data> <2 bytes empty>
The above event is saved in 92 bytes (if my math is correct). 82 bytes of data, 2 bytes empty, 4 byte header, 4 byte length.
Do not reference the above event struct directly. Use the following functions to gain access to the event table, since the ring_buffer_event structure may change in the future.
ring_buffer_event_length(event): get the length of the event.
This is the size of the memory used to record this event, and not the size of the data pay load.
ring_buffer_time_delta(event): get the time delta of the event
This returns the delta time stamp since the last event.
Note: Even though this is in the header, there should
be no reason to access this directly, accept for debugging.
ring_buffer_event_data(event): get the data from the event
This is the function to use to get the actual data from the event. Note, it is only a pointer to the data inside the buffer. This data must be copied to another location otherwise you risk it being written over in the buffer.
ring_buffer_lock: A way to lock the entire buffer.ring_buffer_unlock: unlock the buffer.
ring_buffer_alloc: create a new ring buffer. Can choose between
overwrite or consumer/producer mode. Overwrite will overwrite old data, where as consumer producer will throw away new data if the consumer catches up with the producer. The consumer/producer is the default.
ring_buffer_free: free the ring buffer.
ring_buffer_resize: resize the buffer. Changes the size of each cpu
buffer. Note, it is up to the caller to provide that the buffer is not being used while this is happening. This requirement may go away but do not count on it.
ring_buffer_lock_reserve: locks the ring buffer and allocates an
entry on the buffer to write to.ring_buffer_unlock_commit: unlocks the ring buffer and commits it to
the buffer.
ring_buffer_write: writes some data into the ring buffer.
ring_buffer_peek: Look at a next item in the cpu buffer.ring_buffer_consume: get the next item in the cpu buffer and
consume it. That is, this function increments the head pointer.
ring_buffer_read_start: Start an iterator of a cpu buffer.
For now, this disables the cpu buffer, until you issue a finish. This is just because we do not want the iterator to be overwritten. This restriction may change in the future. But note, this is used for static reading of a buffer which is usually done "after" a trace. Live readings would want to use the ring_buffer_consume above, which will not disable the ring buffer.
ring_buffer_read_finish: Finishes the read iterator and reenables
the ring buffer.
ring_buffer_iter_peek: Look at the next item in the cpu iterator.ring_buffer_read: Read the iterator and increment it.ring_buffer_iter_reset: Reset the iterator to point to the beginning
of the cpu buffer.ring_buffer_iter_empty: Returns true if the iterator is at the end
of the cpu buffer.
ring_buffer_size: returns the size in bytes of each cpu buffer.
Note, the real size is this times the number of CPUs.
ring_buffer_reset_cpu: Sets the cpu buffer to emptyring_buffer_reset: sets all cpu buffers to empty
ring_buffer_swap_cpu: swaps a cpu buffer from one buffer with a
cpu buffer of another buffer. This is handy when you want to take a snap shot of a running trace on just one cpu. Having a backup buffer, to swap with facilitates this. Ftrace max latencies use this.
ring_buffer_empty: Returns true if the ring buffer is empty.ring_buffer_empty_cpu: Returns true if the cpu buffer is empty.
ring_buffer_record_disable: disable all cpu buffers (read only) ring_buffer_record_disable_cpu: disable a single cpu buffer (read only)ring_buffer_record_enable: enable all cpu buffers. ring_buffer_record_enabl_cpu: enable a single cpu buffer.
ring_buffer_entries: The number of entries in a ring buffer.ring_buffer_overruns: The number of entries removed due to writing wrap.
ring_buffer_time_stamp: Get the time stamp used by the ring buffer ring_buffer_normalize_time_stamp: normalize the ring buffer time stamp
into nanosecs.
I still need to implement the GTOD feature. But we need support from the cpu frequency infrastructure. But this can be done at a later time without affecting the ring buffer interface.
--- include/linux/ring_buffer.h | 179 ++++ kernel/trace/Kconfig | 4 kernel/trace/Makefile | 1 kernel/trace/ring_buffer.c | 1584 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1768 insertions(+)
include/linux/ring_buffer.h new file +179 -0
@@ -0,0 +1,179 @@ +#ifndef _LINUX_RING_BUFFER_H +#define _LINUX_RING_BUFFER_H + +#include <linux/mm.h> +#include <linux/seq_file.h> + +struct ring_buffer ; +struct ring_buffer_iter ; + +/* +* Don't reference this struct directly, use the inline items below. +*/ +struct ring_buffer_event { +u32 type:2 , len:3 , time_delta:27 ; +u32 array[]; +}; + +enum { +RB_TYPE_PADDING ,/* Left over page padding +* array is ignored +* size is variable depending on +* how much padding is needed +*/ +RB_TYPE_TIME_EXTENT ,/* Extent the time delta +* array[0] = time delta (28 .. 59) +* size = 8 bytes +*/ +/* FIXME: RB_TYPE_TIME_STAMP not implemented */ +RB_TYPE_TIME_STAMP ,/* Sync time stamp with external clock +* array[0] = tv_nsec +* array[1] = tv_sec +* size = 16 bytes +*/ + +RB_TYPE_DATA ,/* Data record +* If len is zero: +* array[0] holds the actual length +* array[1..(length+3)/4-1] holds data +* else +* length = len << 2 +* array[0..(length+3)/4] holds data +*/ +}; + +#define RB_EVNT_HDR_SIZE (sizeof(struct ring_buffer_event)) +#define RB_ALIGNMENT_SHIFT 2 +#define RB_ALIGNMENT (1 << RB_ALIGNMENT_SHIFT) +#define RB_MAX_SMALL_DATA (28) + +enum { +RB_LEN_TIME_EXTENT =8 , +RB_LEN_TIME_STAMP =16 , +}; + +/** +* ring_buffer_event_length - return the length of the event +* @event: the event to get the length of +*/ +static inline unsigned +ring_buffer_event_length (struct ring_buffer_event *event) +{ +unsigned length; + +switch (event->type) { +case RB_TYPE_PADDING : +/* undefined */ +return -1 ; + +case RB_TYPE_TIME_EXTENT : +return RB_LEN_TIME_EXTENT ; + +case RB_TYPE_TIME_STAMP : +return RB_LEN_TIME_STAMP ; + +case RB_TYPE_DATA : +if (event->len) + length = event->len <<RB_ALIGNMENT_SHIFT ; +else + length = event->array[0 ]; +return length +RB_EVNT_HDR_SIZE ; +default : +BUG (); + } +/* not hit */ +return 0 ; +} + +/** +* ring_buffer_event_time_delta - return the delta timestamp of the event +* @event: the event to get the delta timestamp of +* +* The delta timestamp is the 27 bit timestamp since the last event. +*/ +static inline unsigned +ring_buffer_event_time_delta (struct ring_buffer_event *event) +{ +return event->time_delta; +} + +/** +* ring_buffer_event_data - return the data of the event +* @event: the event to get the data from +*/ +static inline void * +ring_buffer_event_data (struct ring_buffer_event *event) +{ +BUG_ON (event->type !=RB_TYPE_DATA ); +/* If length is in len field, then array[0] has the data */ +if (event->len) +return (void *)&event->array[0 ]; +/* Otherwise length is in array[0] and array[1] has the data */ +return (void *)&event->array[1 ]; +} + +void ring_buffer_lock (struct ring_buffer *buffer,unsigned long *flags); +void ring_buffer_unlock (struct ring_buffer *buffer,unsigned long flags); + +/* +* size is in bytes for each per CPU buffer. +*/ +struct ring_buffer * +ring_buffer_alloc (unsigned long size,unsigned flags); +void ring_buffer_free (struct ring_buffer *buffer); + +int ring_buffer_resize (struct ring_buffer *buffer,unsigned long size); + +struct ring_buffer_event * +ring_buffer_lock_reserve (struct ring_buffer *buffer, +unsigned long length, +unsigned long *flags); +int ring_buffer_unlock_commit (struct ring_buffer *buffer, +struct ring_buffer_event *event, +unsigned long flags); +int ring_buffer_write (struct ring_buffer *buffer, +unsigned long length,void *data); + +struct ring_buffer_event * +ring_buffer_peek (struct ring_buffer *buffer,int cpu,u64 *ts); +struct ring_buffer_event * +ring_buffer_consume (struct ring_buffer *buffer,int cpu,u64 *ts); + +struct ring_buffer_iter * +ring_buffer_read_start (struct ring_buffer *buffer,int cpu); +void ring_buffer_read_finish (struct ring_buffer_iter *iter); + +struct ring_buffer_event * +ring_buffer_iter_peek (struct ring_buffer_iter *iter,u64 *ts); +struct ring_buffer_event * +ring_buffer_read (struct ring_buffer_iter *iter,u64 *ts); +void ring_buffer_iter_reset (struct ring_buffer_iter *iter); +int ring_buffer_iter_empty (struct ring_buffer_iter *iter); + +unsigned long ring_buffer_size (struct ring_buffer *buffer); + +void ring_buffer_reset_cpu (struct ring_buffer *buffer,int cpu); +void ring_buffer_reset (struct ring_buffer *buffer); + +int ring_buffer_swap_cpu (struct ring_buffer *buffer_a, +struct ring_buffer *buffer_b,int cpu); + +int ring_buffer_empty (struct ring_buffer *buffer); +int ring_buffer_empty_cpu (struct ring_buffer *buffer,int cpu); + +void ring_buffer_record_disable (struct ring_buffer *buffer); +void ring_buffer_record_enable (struct ring_buffer *buffer); +void ring_buffer_record_disable_cpu (struct ring_buffer *buffer,int cpu); +void ring_buffer_record_enable_cpu (struct ring_buffer *buffer,int cpu); + +unsigned long ring_buffer_entries (struct ring_buffer *buffer); +unsigned long ring_buffer_overruns (struct ring_buffer *buffer); + +u64 ring_buffer_time_stamp (int cpu); +void ring_buffer_normalize_time_stamp (int cpu,u64 *ts); + +enum ring_buffer_flags { +RB_FL_OVERWRITE =1 <<0 , +}; + +#endif /* _LINUX_RING_BUFFER_H */
kernel/trace/ring_buffer.c new file +1584 -0
1,584 lines not on this page · raw message
kernel/trace/Kconfig +4 -0
@@ -10,10 +10,14 @@ config HAVE_DYNAMIC_FTRACE config TRACER_MAX_TRACE bool +config RING_BUFFER + bool + config TRACING bool select DEBUG_FS select STACKTRACE + select RING_BUFFER config FTRACE bool "Kernel Function Tracer"
kernel/trace/Makefile +1 -0
@@ -11,6 +11,7 @@ obj-y += trace_selftest_dynamic.o endif obj-$(CONFIG_FTRACE) += libftrace.o +obj-$(CONFIG_RING_BUFFER) += ring_buffer.o obj-$(CONFIG_TRACING) += trace.o obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
Steven Rostedt
maintainerPATCH v9 1/1 Unified trace buffer
[
Changes since version 8:
Two major bug fixes!
- Had mix of referencing the pages link list with both page->lru and buffer_page->list. Perhaps they luckily were lined up. But I have no idea why this didn't totally crash my box.
- Missed a write stamp update that would cause funny times
]
From: Steven Rostedt <[email protected]>
Subject: Unified trace buffer
This is a unified tracing buffer that implements a ring buffer that hopefully everyone will eventually be able to use.
The events recorded into the buffer have the following structure:
struct ring_buffer_event {
u32 type:2, len:3, time_delta:27;
u32 array[];
};The minimum size of an event is 8 bytes. All events are 4 byte aligned inside the buffer.
There are 4 types (all internal use for the ring buffer, only the data type is exported to the interface users).
RB_TYPE_PADDING: this type is used to note extra space at the end
of a buffer page.
RB_TYPE_TIME_EXTENT: This type is used when the time between events
is greater than the 27 bit delta can hold. We add another 32 bits, and record that in its own event (8 byte size).
RB_TYPE_TIME_STAMP: (Not implemented yet). This will hold data to
help keep the buffer timestamps in sync.
RB_TYPE_DATA: The event actually holds user data.
The "len" field is only three bits. Since the data must be 4 byte aligned, this field is shifted left by 2, giving a max length of 28 bytes. If the data load is greater than 28 bytes, the first array field holds the full length of the data load and the len field is set to zero.
Example, data size of 7 bytes:
type = RB_TYPE_DATA len = 2 time_delta: <time-stamp> - <prev_event-time-stamp> array[0..1]: <7 bytes of data> <1 byte empty>
This event is saved in 12 bytes of the buffer.
An event with 82 bytes of data:
type = RB_TYPE_DATA
len = 0
time_delta: <time-stamp> - <prev_event-time-stamp> array[0]: 84 (Note the alignment) array[1..14]: <82 bytes of data> <2 bytes empty>
The above event is saved in 92 bytes (if my math is correct). 82 bytes of data, 2 bytes empty, 4 byte header, 4 byte length.
Do not reference the above event struct directly. Use the following functions to gain access to the event table, since the ring_buffer_event structure may change in the future.
ring_buffer_event_length(event): get the length of the event.
This is the size of the memory used to record this event, and not the size of the data pay load.
ring_buffer_time_delta(event): get the time delta of the event
This returns the delta time stamp since the last event.
Note: Even though this is in the header, there should
be no reason to access this directly, accept for debugging.
ring_buffer_event_data(event): get the data from the event
This is the function to use to get the actual data from the event. Note, it is only a pointer to the data inside the buffer. This data must be copied to another location otherwise you risk it being written over in the buffer.
ring_buffer_lock: A way to lock the entire buffer.ring_buffer_unlock: unlock the buffer.
ring_buffer_alloc: create a new ring buffer. Can choose between
overwrite or consumer/producer mode. Overwrite will overwrite old data, where as consumer producer will throw away new data if the consumer catches up with the producer. The consumer/producer is the default.
ring_buffer_free: free the ring buffer.
ring_buffer_resize: resize the buffer. Changes the size of each cpu
buffer. Note, it is up to the caller to provide that the buffer is not being used while this is happening. This requirement may go away but do not count on it.
ring_buffer_lock_reserve: locks the ring buffer and allocates an
entry on the buffer to write to.ring_buffer_unlock_commit: unlocks the ring buffer and commits it to
the buffer.
ring_buffer_write: writes some data into the ring buffer.
ring_buffer_peek: Look at a next item in the cpu buffer.ring_buffer_consume: get the next item in the cpu buffer and
consume it. That is, this function increments the head pointer.
ring_buffer_read_start: Start an iterator of a cpu buffer.
For now, this disables the cpu buffer, until you issue a finish. This is just because we do not want the iterator to be overwritten. This restriction may change in the future. But note, this is used for static reading of a buffer which is usually done "after" a trace. Live readings would want to use the ring_buffer_consume above, which will not disable the ring buffer.
ring_buffer_read_finish: Finishes the read iterator and reenables
the ring buffer.
ring_buffer_iter_peek: Look at the next item in the cpu iterator.ring_buffer_read: Read the iterator and increment it.ring_buffer_iter_reset: Reset the iterator to point to the beginning
of the cpu buffer.ring_buffer_iter_empty: Returns true if the iterator is at the end
of the cpu buffer.
ring_buffer_size: returns the size in bytes of each cpu buffer.
Note, the real size is this times the number of CPUs.
ring_buffer_reset_cpu: Sets the cpu buffer to emptyring_buffer_reset: sets all cpu buffers to empty
ring_buffer_swap_cpu: swaps a cpu buffer from one buffer with a
cpu buffer of another buffer. This is handy when you want to take a snap shot of a running trace on just one cpu. Having a backup buffer, to swap with facilitates this. Ftrace max latencies use this.
ring_buffer_empty: Returns true if the ring buffer is empty.ring_buffer_empty_cpu: Returns true if the cpu buffer is empty.
ring_buffer_record_disable: disable all cpu buffers (read only) ring_buffer_record_disable_cpu: disable a single cpu buffer (read only)ring_buffer_record_enable: enable all cpu buffers. ring_buffer_record_enabl_cpu: enable a single cpu buffer.
ring_buffer_entries: The number of entries in a ring buffer.ring_buffer_overruns: The number of entries removed due to writing wrap.
ring_buffer_time_stamp: Get the time stamp used by the ring buffer ring_buffer_normalize_time_stamp: normalize the ring buffer time stamp
into nanosecs.
I still need to implement the GTOD feature. But we need support from the cpu frequency infrastructure. But this can be done at a later time without affecting the ring buffer interface.
--- include/linux/ring_buffer.h | 179 ++++ kernel/trace/Kconfig | 4 kernel/trace/Makefile | 1 kernel/trace/ring_buffer.c | 1594 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1778 insertions(+)
include/linux/ring_buffer.h new file +179 -0
@@ -0,0 +1,179 @@ +#ifndef _LINUX_RING_BUFFER_H +#define _LINUX_RING_BUFFER_H + +#include <linux/mm.h> +#include <linux/seq_file.h> + +struct ring_buffer ; +struct ring_buffer_iter ; + +/* +* Don't reference this struct directly, use the inline items below. +*/ +struct ring_buffer_event { +u32 type:2 , len:3 , time_delta:27 ; +u32 array[]; +}; + +enum { +RB_TYPE_PADDING ,/* Left over page padding +* array is ignored +* size is variable depending on +* how much padding is needed +*/ +RB_TYPE_TIME_EXTENT ,/* Extent the time delta +* array[0] = time delta (28 .. 59) +* size = 8 bytes +*/ +/* FIXME: RB_TYPE_TIME_STAMP not implemented */ +RB_TYPE_TIME_STAMP ,/* Sync time stamp with external clock +* array[0] = tv_nsec +* array[1] = tv_sec +* size = 16 bytes +*/ + +RB_TYPE_DATA ,/* Data record +* If len is zero: +* array[0] holds the actual length +* array[1..(length+3)/4-1] holds data +* else +* length = len << 2 +* array[0..(length+3)/4] holds data +*/ +}; + +#define RB_EVNT_HDR_SIZE (sizeof(struct ring_buffer_event)) +#define RB_ALIGNMENT_SHIFT 2 +#define RB_ALIGNMENT (1 << RB_ALIGNMENT_SHIFT) +#define RB_MAX_SMALL_DATA (28) + +enum { +RB_LEN_TIME_EXTENT =8 , +RB_LEN_TIME_STAMP =16 , +}; + +/** +* ring_buffer_event_length - return the length of the event +* @event: the event to get the length of +*/ +static inline unsigned +ring_buffer_event_length (struct ring_buffer_event *event) +{ +unsigned length; + +switch (event->type) { +case RB_TYPE_PADDING : +/* undefined */ +return -1 ; + +case RB_TYPE_TIME_EXTENT : +return RB_LEN_TIME_EXTENT ; + +case RB_TYPE_TIME_STAMP : +return RB_LEN_TIME_STAMP ; + +case RB_TYPE_DATA : +if (event->len) + length = event->len <<RB_ALIGNMENT_SHIFT ; +else + length = event->array[0 ]; +return length +RB_EVNT_HDR_SIZE ; +default : +BUG (); + } +/* not hit */ +return 0 ; +} + +/** +* ring_buffer_event_time_delta - return the delta timestamp of the event +* @event: the event to get the delta timestamp of +* +* The delta timestamp is the 27 bit timestamp since the last event. +*/ +static inline unsigned +ring_buffer_event_time_delta (struct ring_buffer_event *event) +{ +return event->time_delta; +} + +/** +* ring_buffer_event_data - return the data of the event +* @event: the event to get the data from +*/ +static inline void * +ring_buffer_event_data (struct ring_buffer_event *event) +{ +BUG_ON (event->type !=RB_TYPE_DATA ); +/* If length is in len field, then array[0] has the data */ +if (event->len) +return (void *)&event->array[0 ]; +/* Otherwise length is in array[0] and array[1] has the data */ +return (void *)&event->array[1 ]; +} + +void ring_buffer_lock (struct ring_buffer *buffer,unsigned long *flags); +void ring_buffer_unlock (struct ring_buffer *buffer,unsigned long flags); + +/* +* size is in bytes for each per CPU buffer. +*/ +struct ring_buffer * +ring_buffer_alloc (unsigned long size,unsigned flags); +void ring_buffer_free (struct ring_buffer *buffer); + +int ring_buffer_resize (struct ring_buffer *buffer,unsigned long size); + +struct ring_buffer_event * +ring_buffer_lock_reserve (struct ring_buffer *buffer, +unsigned long length, +unsigned long *flags); +int ring_buffer_unlock_commit (struct ring_buffer *buffer, +struct ring_buffer_event *event, +unsigned long flags); +int ring_buffer_write (struct ring_buffer *buffer, +unsigned long length,void *data); + +struct ring_buffer_event * +ring_buffer_peek (struct ring_buffer *buffer,int cpu,u64 *ts); +struct ring_buffer_event * +ring_buffer_consume (struct ring_buffer *buffer,int cpu,u64 *ts); + +struct ring_buffer_iter * +ring_buffer_read_start (struct ring_buffer *buffer,int cpu); +void ring_buffer_read_finish (struct ring_buffer_iter *iter); + +struct ring_buffer_event * +ring_buffer_iter_peek (struct ring_buffer_iter *iter,u64 *ts); +struct ring_buffer_event * +ring_buffer_read (struct ring_buffer_iter *iter,u64 *ts); +void ring_buffer_iter_reset (struct ring_buffer_iter *iter); +int ring_buffer_iter_empty (struct ring_buffer_iter *iter); + +unsigned long ring_buffer_size (struct ring_buffer *buffer); + +void ring_buffer_reset_cpu (struct ring_buffer *buffer,int cpu); +void ring_buffer_reset (struct ring_buffer *buffer); + +int ring_buffer_swap_cpu (struct ring_buffer *buffer_a, +struct ring_buffer *buffer_b,int cpu); + +int ring_buffer_empty (struct ring_buffer *buffer); +int ring_buffer_empty_cpu (struct ring_buffer *buffer,int cpu); + +void ring_buffer_record_disable (struct ring_buffer *buffer); +void ring_buffer_record_enable (struct ring_buffer *buffer); +void ring_buffer_record_disable_cpu (struct ring_buffer *buffer,int cpu); +void ring_buffer_record_enable_cpu (struct ring_buffer *buffer,int cpu); + +unsigned long ring_buffer_entries (struct ring_buffer *buffer); +unsigned long ring_buffer_overruns (struct ring_buffer *buffer); + +u64 ring_buffer_time_stamp (int cpu); +void ring_buffer_normalize_time_stamp (int cpu,u64 *ts); + +enum ring_buffer_flags { +RB_FL_OVERWRITE =1 <<0 , +}; + +#endif /* _LINUX_RING_BUFFER_H */
kernel/trace/ring_buffer.c new file +1594 -0
1,594 lines not on this page · raw message
kernel/trace/Kconfig +4 -0
@@ -10,10 +10,14 @@ config HAVE_DYNAMIC_FTRACE config TRACER_MAX_TRACE bool +config RING_BUFFER + bool + config TRACING bool select DEBUG_FS select STACKTRACE + select RING_BUFFER config FTRACE bool "Kernel Function Tracer"
kernel/trace/Makefile +1 -0
@@ -11,6 +11,7 @@ obj-y += trace_selftest_dynamic.o endif obj-$(CONFIG_FTRACE) += libftrace.o +obj-$(CONFIG_RING_BUFFER) += ring_buffer.o obj-$(CONFIG_TRACING) += trace.o obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
small nitpicking review, nothing structural yet:
include/linux/ring_buffer.h line 19
Quoted 3 lines · Steven Rostedt
Index:
linux-trace.git/include/linux/ring_buffer.hinclude/linux/ring_buffer.h new file +2
-0+enum { +RB_TYPE_PADDING ,/* Left over page padding
RB_ clashes with red-black tree namespace. (on the thought level)
include/linux/ring_buffer.h line 48
Quoted 3 lines
include/linux/ring_buffer.h new file +3
-0+#define RB_ALIGNMENT_SHIFT 2 +#define RB_ALIGNMENT (1 << RB_ALIGNMENT_SHIFT) +#define RB_MAX_SMALL_DATA (28)
no need to put numeric literals into parenthesis.
Quoted 17 lines
include/linux/ring_buffer.h new file +17
-0+static inline unsigned +ring_buffer_event_length (struct ring_buffer_event *event) +{ +unsigned length; + +switch (event->type) { +case RB_TYPE_PADDING : +/* undefined */ +return -1 ; + +case RB_TYPE_TIME_EXTENT : +return RB_LEN_TIME_EXTENT ; + +case RB_TYPE_TIME_STAMP : +return RB_LEN_TIME_STAMP ; + +case RB_TYPE_DATA :
include/linux/ring_buffer.h line 85
Quoted 10 lines
include/linux/ring_buffer.h new file +10
-0+if (event->len) + length = event->len <<RB_ALIGNMENT_SHIFT ; +else + length = event->array[0 ]; +return length +RB_EVNT_HDR_SIZE ; +default : +BUG (); + } +/* not hit */ +return 0 ;
too large, please uninline.
include/linux/ring_buffer.h line 113
Quoted 10 lines
include/linux/ring_buffer.h new file +10
-0+static inline void * +ring_buffer_event_data (struct ring_buffer_event *event) +{ +BUG_ON (event->type !=RB_TYPE_DATA ); +/* If length is in len field, then array[0] has the data */ +if (event->len) +return (void *)&event->array[0 ]; +/* Otherwise length is in array[0] and array[1] has the data */ +return (void *)&event->array[1 ]; +}
ditto.
kernel/trace/ring_buffer.c line 34
Quoted 5 lines
kernel/trace/ring_buffer.c new file +5
-0+/* FIXME!!! */ +u64 ring_buffer_time_stamp (int cpu) +{ +/* shift to debug/test normalization and TIME_EXTENTS */ +return sched_clock () <<DEBUG_SHIFT ;
[ duly noted ;-) ]
kernel/trace/ring_buffer.c line 36
Quoted 2 lines
kernel/trace/ring_buffer.c new file +2
-0+} +void ring_buffer_normalize_time_stamp (int cpu,u64 *ts)
needs extra newline above.
kernel/trace/ring_buffer.c line 85
Quoted 7 lines
kernel/trace/ring_buffer.c new file +7
-0+/* +* head_page == tail_page && head == tail then buffer is empty. +*/ +struct ring_buffer_per_cpu { +int cpu; +struct ring_buffer *buffer; +raw_spinlock_t lock;
hm, should not be raw, at least initially. I am 95% sure we'll see lockups, we always did when we iterated ftrace's buffer implementation ;-)
Quoted 8 lines
kernel/trace/ring_buffer.c new file +8
-0+struct ring_buffer { +unsigned long size; +unsigned pages; +unsigned flags; +int cpus; +cpumask_t cpumask; +atomic_t record_disabled; +
kernel/trace/ring_buffer.c line 116
Quoted 10 lines
kernel/trace/ring_buffer.c new file +10
-0+struct mutex mutex; + +struct ring_buffer_per_cpu **buffers; +}; + +struct ring_buffer_iter { +struct ring_buffer_per_cpu *cpu_buffer; +unsigned long head; +struct buffer_page *head_page; +u64 read_stamp;
please use consistent vertical whitespaces. Above, in the struct ring_buffer definition, you can add another tab to most of the vars - that will also make the '**buffers' line look nice.
same for all structs across this file. In my experience, a 50% vertical break works best - the one you used here in 'struct ring_buffer_iter'.
kernel/trace/ring_buffer.c line 124
Quoted 8 lines
kernel/trace/ring_buffer.c new file +8
-0+}; + +#define CHECK_COND (buffer, cond) \ + if (unlikely(cond)) { \ + atomic_inc(&buffer->record_disabled); \ + WARN_ON(1); \ + return -1; \ + }
please name it RINGBUFFER_BUG_ON() / RINGBUFFER_WARN_ON(), so that we dont have to memorize another set of debug names. [ See DEBUG_LOCKS_WARN_ON() in include/linux/debug_locks.h ]
you can change it to:
kernel/trace/ring_buffer.c line 161
Quoted 8 lines
kernel/trace/ring_buffer.c new file +8
-0+static int +rb_allocate_pages (struct ring_buffer_per_cpu *cpu_buffer,unsigned nr_pages) +{ +struct list_head *head = &cpu_buffer->pages; +LIST_HEAD (pages); +struct buffer_page *page, *tmp; +unsigned long addr; +unsigned i;
please apply ftrace's standard reverse christmas tree style and move the 'pages' line down two lines.
kernel/trace/ring_buffer.c line 382
Quoted 9 lines
kernel/trace/ring_buffer.c new file +9
-0+int ring_buffer_resize (struct ring_buffer *buffer,unsigned long size) +{ +struct ring_buffer_per_cpu *cpu_buffer; +unsigned long buffer_size; +LIST_HEAD (pages); +unsigned long addr; +unsigned nr_pages, rm_pages, new_pages; +struct buffer_page *page, *tmp; +int i, cpu;
ditto.
kernel/trace/ring_buffer.c line 470
Quoted 5 lines
kernel/trace/ring_buffer.c new file +5
-0+static inline void *rb_page_index (struct buffer_page *page,unsigned index) +{ +void *addr; + + addr =page_address (&page->page);
'addr' initialization can move to the definition line - you save two lines.
kernel/trace/ring_buffer.c line 478
Quoted 8 lines
kernel/trace/ring_buffer.c new file +8
-0+return addr + index; +} + +static inline struct ring_buffer_event * +rb_head_event (struct ring_buffer_per_cpu *cpu_buffer) +{ +return rb_page_index (cpu_buffer->head_page, + cpu_buffer->head);
can all move to the same return line.
kernel/trace/ring_buffer.c line 485
Quoted 7 lines
kernel/trace/ring_buffer.c new file +7
-0+} + +static inline struct ring_buffer_event * +rb_iter_head_event (struct ring_buffer_iter *iter) +{ +return rb_page_index (iter->head_page, + iter->head);
ditto.
kernel/trace/ring_buffer.c line 502
Quoted 4 lines
kernel/trace/ring_buffer.c new file +4
-0+for (head =0 ; head <rb_head_size (cpu_buffer); + head +=ring_buffer_event_length (event)) { + event =rb_page_index (cpu_buffer->head_page, head); +BUG_ON (rb_null_event (event));
( optional:when there's a multi-line loop then i generally try to insert
an extra newline when starting the body - to make sure the iterator and the body stands apart visually. Matter of taste. )
Quoted 50 lines
kernel/trace/ring_buffer.c new file +50
-0+static struct ring_buffer_event * +rb_reserve_next_event (struct ring_buffer_per_cpu *cpu_buffer, +unsigned type,unsigned long length) +{ +u64 ts, delta; +struct ring_buffer_event *event; +static int once; + + ts =ring_buffer_time_stamp (cpu_buffer->cpu); + +if (cpu_buffer->tail) { + delta = ts - cpu_buffer->write_stamp; + +if (test_time_stamp (delta)) { +if (unlikely (delta > (1ULL <<59 ) && !once++)) { +printk (KERN_WARNING "Delta way too big! %llu" +" ts=%llu write stamp = %llu\n" , + delta, ts, cpu_buffer->write_stamp); +WARN_ON (1 ); + } +/* +* The delta is too big, we to add a +* new timestamp. +*/ + event =__rb_reserve_next (cpu_buffer, +RB_TYPE_TIME_EXTENT , +RB_LEN_TIME_EXTENT , + &ts); +if (!event) +return NULL ; + +/* check to see if we went to the next page */ +if (cpu_buffer->tail) { +/* Still on same page, update timestamp */ + event->time_delta = delta &TS_MASK ; + event->array[0 ] = delta >>TS_SHIFT ; +/* commit the time event */ + cpu_buffer->tail += +ring_buffer_event_length (event); + cpu_buffer->write_stamp = ts; + delta =0 ; + } + } + }else { +rb_add_stamp (cpu_buffer, &ts); + delta =0 ; + } + + event =__rb_reserve_next (cpu_buffer, type, length, &ts); +if (!event)
kernel/trace/ring_buffer.c line 720
Quoted 10 lines
kernel/trace/ring_buffer.c new file +10
-0+return NULL ; + +/* If the reserve went to the next page, our delta is zero */ +if (!cpu_buffer->tail) + delta =0 ; + + event->time_delta = delta; + +return event; +}
this function is too long, please split it up. The first condition's body could go into a separate function i guess.
include/linux/ring_buffer.h line 27
Quoted 4 lines
include/linux/ring_buffer.h new file +4
-0+ RB_TYPE_TIME_EXTENT, /* Extent the time delta +* array[0] = time delta (28 .. 59) +* size = 8 bytes +*/
please use standard comment style:
/*
* Comment
*/
Ingo
Steven Rostedt
maintainerHi Ingo,
Thanks for the review!
Quoted 10 lines · Ingo Molnar
small nitpicking review, nothing structural yet:
include/linux/ring_buffer.h line 19
Quoted 3 lines · Steven Rostedt
Index:
linux-trace.git/include/linux/ring_buffer.hinclude/linux/ring_buffer.h new file +2
-0+enum { +RB_TYPE_PADDING ,/* Left over page padding
RB_clashes with red-black tree namespace. (on the thought level)
Yeah, Linus pointed this out with the rb_ static function names. But since the functions are static I kept them as is. But here we have global names.
Would RNGBF_ be OK, or do you have any other ideas?
Quoted 6 lines
include/linux/ring_buffer.h line 48
Quoted 4 lines
include/linux/ring_buffer.h new file +3
-0+#define RB_ALIGNMENT_SHIFT 2 +#define RB_ALIGNMENT (1 << RB_ALIGNMENT_SHIFT) +#define RB_MAX_SMALL_DATA (28)no need to put numeric literals into parenthesis.
Ah, I think I had it more complex and changed it to a literal without removing the parenthesis.
Quoted 22 lines
Quoted 22 lines
include/linux/ring_buffer.h new file +21
-0+static inline unsigned +ring_buffer_event_length (struct ring_buffer_event *event) +{ +unsigned length; + +switch (event->type) { +case RB_TYPE_PADDING : +/* undefined */ +return -1 ; + +case RB_TYPE_TIME_EXTENT : +return RB_LEN_TIME_EXTENT ; + +case RB_TYPE_TIME_STAMP : +return RB_LEN_TIME_STAMP ; + +case RB_TYPE_DATA : +if (event->len) + length = event->len <<RB_ALIGNMENT_SHIFT ; +else + length = event->array[0 ];
Quoted 8 lines
include/linux/ring_buffer.h line 85
Quoted 6 lines
include/linux/ring_buffer.h new file +6
-0+return length +RB_EVNT_HDR_SIZE ; +default : +BUG (); + } +/* not hit */ +return 0 ;too large, please uninline.
I calculated this on x86_64 to add 78 bytes. Is that still too big?
Quoted 13 lines
include/linux/ring_buffer.h line 113
Quoted 11 lines
include/linux/ring_buffer.h new file +10
-0+static inline void * +ring_buffer_event_data (struct ring_buffer_event *event) +{ +BUG_ON (event->type !=RB_TYPE_DATA ); +/* If length is in len field, then array[0] has the data */ +if (event->len) +return (void *)&event->array[0 ]; +/* Otherwise length is in array[0] and array[1] has the data */ +return (void *)&event->array[1 ]; +}ditto.
No biggy. I thought this would be nicer as inline. But I have no problem changing this.
Quoted 9 lines
kernel/trace/ring_buffer.c line 34
Quoted 6 lines
kernel/trace/ring_buffer.c new file +5
-0+/* FIXME!!! */ +u64 ring_buffer_time_stamp (int cpu) +{ +/* shift to debug/test normalization and TIME_EXTENTS */ +return sched_clock () <<DEBUG_SHIFT ;[ duly noted ;-) ]
Quoted 4 lines
kernel/trace/ring_buffer.c line 36
Quoted 2 lines
kernel/trace/ring_buffer.c new file +2
-0+} +void ring_buffer_normalize_time_stamp (int cpu,u64 *ts)needs extra newline above.
Yeah, I kept them bounded just to stress the "FIXME" part ;-)
Quoted 12 lines
kernel/trace/ring_buffer.c line 85
Quoted 8 lines
kernel/trace/ring_buffer.c new file +7
-0+/* +* head_page == tail_page && head == tail then buffer is empty. +*/ +struct ring_buffer_per_cpu { +int cpu; +struct ring_buffer *buffer; +raw_spinlock_t lock;hm, should not be raw, at least initially. I am 95% sure we'll see lockups, we always did when we iterated ftrace's buffer implementation ;-)
It was to prevent lockdep from checking the locks from inside. We had issues with ftroce and lockdep in the past, because ftrace would trace the internals of lockdep, and lockdep would then recurse back into itself to trace. If lockdep itself can get away with not using raw_spinlocks, then this will be OK to make back to spinlock.
Quoted 15 lines
Quoted 15 lines
kernel/trace/ring_buffer.c new file +14
-0+struct ring_buffer { +unsigned long size; +unsigned pages; +unsigned flags; +int cpus; +cpumask_t cpumask; +atomic_t record_disabled; + +struct mutex mutex; + +struct ring_buffer_per_cpu **buffers; +}; + +struct ring_buffer_iter {
Quoted 8 lines
kernel/trace/ring_buffer.c line 116
Quoted 4 lines
kernel/trace/ring_buffer.c new file +4
-0+struct ring_buffer_per_cpu *cpu_buffer; +unsigned long head; +struct buffer_page *head_page; +u64 read_stamp;please use consistent vertical whitespaces. Above, in the struct
ring_bufferdefinition, you can add another tab to most of the vars - that will also make the '**buffers' line look nice.
OK, will fix.
Quoted 4 lines
same for all structs across this file. In my experience, a 50% vertical break works best - the one you used here in 'struct
ring_buffer_iter'.
Quoted 12 lines
kernel/trace/ring_buffer.c line 124
Quoted 8 lines
kernel/trace/ring_buffer.c new file +8
-0+}; + +#define CHECK_COND (buffer, cond) \ + if (unlikely(cond)) { \ + atomic_inc(&buffer->record_disabled); \ + WARN_ON(1); \ + return -1; \ + }please name it
RINGBUFFER_BUG_ON()/RINGBUFFER_WARN_ON(), so that we dont have to memorize another set of debug names. [ SeeDEBUG_LOCKS_WARN_ON()ininclude/linux/debug_locks.h]
OK, this was a direct copy from what was used in ftrace.
Quoted 14 lines
you can change it to:
kernel/trace/ring_buffer.c line 161
Quoted 8 lines
kernel/trace/ring_buffer.c new file +8
-0+static int +rb_allocate_pages (struct ring_buffer_per_cpu *cpu_buffer,unsigned nr_pages) +{ +struct list_head *head = &cpu_buffer->pages; +LIST_HEAD (pages); +struct buffer_page *page, *tmp; +unsigned long addr; +unsigned i;please apply ftrace's standard reverse christmas tree style and move the 'pages' line down two lines.
Heh, this was directly from a bug I had and laziness ;-)
I originally just had struct list_head pages (and no *tmp), which kept the christmas tree format. But later found that you need to initialize list heads (duh!), and never moved it.
Quoted 12 lines
kernel/trace/ring_buffer.c line 382
Quoted 10 lines
kernel/trace/ring_buffer.c new file +9
-0+int ring_buffer_resize (struct ring_buffer *buffer,unsigned long size) +{ +struct ring_buffer_per_cpu *cpu_buffer; +unsigned long buffer_size; +LIST_HEAD (pages); +unsigned long addr; +unsigned nr_pages, rm_pages, new_pages; +struct buffer_page *page, *tmp; +int i, cpu;ditto.
Same reason.
Quoted 9 lines
kernel/trace/ring_buffer.c line 470
Quoted 6 lines
kernel/trace/ring_buffer.c new file +5
-0+static inline void *rb_page_index (struct buffer_page *page,unsigned index) +{ +void *addr; + + addr =page_address (&page->page);'addr' initialization can move to the definition line - you save two lines.
Will fix.
Quoted 11 lines
kernel/trace/ring_buffer.c line 478
Quoted 9 lines
kernel/trace/ring_buffer.c new file +8
-0+return addr + index; +} + +static inline struct ring_buffer_event * +rb_head_event (struct ring_buffer_per_cpu *cpu_buffer) +{ +return rb_page_index (cpu_buffer->head_page, + cpu_buffer->head);can all move to the same return line.
Ah, this was caused by my s/ring_buffer_page_index/rb_page_index/ run.
Quoted 10 lines
kernel/trace/ring_buffer.c line 485
Quoted 8 lines
kernel/trace/ring_buffer.c new file +7
-0+} + +static inline struct ring_buffer_event * +rb_iter_head_event (struct ring_buffer_iter *iter) +{ +return rb_page_index (iter->head_page, + iter->head);ditto.
Will fix.
Quoted 9 lines
kernel/trace/ring_buffer.c line 502
Quoted 5 lines
kernel/trace/ring_buffer.c new file +4
-0+for (head =0 ; head <rb_head_size (cpu_buffer); + head +=ring_buffer_event_length (event)) { + event =rb_page_index (cpu_buffer->head_page, head); +BUG_ON (rb_null_event (event));( optional:when there's a multi-line loop then i generally try to insert
an extra newline when starting the body - to make sure the iterator and the body stands apart visually. Matter of taste. )
Will fix, I have no preference.
Quoted 56 lines
Quoted 56 lines
kernel/trace/ring_buffer.c new file +55
-0+static struct ring_buffer_event * +rb_reserve_next_event (struct ring_buffer_per_cpu *cpu_buffer, +unsigned type,unsigned long length) +{ +u64 ts, delta; +struct ring_buffer_event *event; +static int once; + + ts =ring_buffer_time_stamp (cpu_buffer->cpu); + +if (cpu_buffer->tail) { + delta = ts - cpu_buffer->write_stamp; + +if (test_time_stamp (delta)) { +if (unlikely (delta > (1ULL <<59 ) && !once++)) { +printk (KERN_WARNING "Delta way too big! %llu" +" ts=%llu write stamp = %llu\n" , + delta, ts, cpu_buffer->write_stamp); +WARN_ON (1 ); + } +/* +* The delta is too big, we to add a +* new timestamp. +*/ + event =__rb_reserve_next (cpu_buffer, +RB_TYPE_TIME_EXTENT , +RB_LEN_TIME_EXTENT , + &ts); +if (!event) +return NULL ; + +/* check to see if we went to the next page */ +if (cpu_buffer->tail) { +/* Still on same page, update timestamp */ + event->time_delta = delta &TS_MASK ; + event->array[0 ] = delta >>TS_SHIFT ; +/* commit the time event */ + cpu_buffer->tail += +ring_buffer_event_length (event); + cpu_buffer->write_stamp = ts; + delta =0 ; + } + } + }else { +rb_add_stamp (cpu_buffer, &ts); + delta =0 ; + } + + event =__rb_reserve_next (cpu_buffer, type, length, &ts); +if (!event) +return NULL ; + +/* If the reserve went to the next page, our delta is zero */ +if (!cpu_buffer->tail) + delta =0 ;
Quoted 8 lines
kernel/trace/ring_buffer.c line 720
Quoted 5 lines
kernel/trace/ring_buffer.c new file +5
-0+ + event->time_delta = delta; + +return event; +}this function is too long, please split it up. The first condition's body could go into a separate function i guess.
Will fix.
Quoted 11 lines
include/linux/ring_buffer.h line 27
Quoted 5 lines
include/linux/ring_buffer.h new file +4
-0+ RB_TYPE_TIME_EXTENT, /* Extent the time delta +* array[0] = time delta (28 .. 59) +* size = 8 bytes +*/ please use standard comment style:
/*
* Comment
*/
Hmm, this is interesting. I kind of like this because it is not really a standard comment. It is a comment about the definitions of the enum. I believe if they are above:
/*
* Comment
*/
RB_ENUM_TYPE,
It is not as readable. But if we do:
RB_ENUM_TYPE, /*
* Comment */
The comment is not at the same line as the enum, which also looks unpleasing.
We can't could do:
/* RB_ENUM_TYPE, * Comment */ /* RB_ENUM_TYPE2, * Comment */
Because the ENUM is also in the comment :-p
I chose this way because we have:
RB_ENUM_TYPE, /* Comment
* More comment */ RB_ENUM_TYPE2, /* Comment */
Since I find this the nices way to describe enums. That last */ is good to space the comments apart, otherwise we have:
RB_ENUM_TYPE, /* Comment
* More comment */
RB_ENUM_TYPE2, /* Comment */
That is not as easy to see the separation of one description of enums with the other.
-- Steve
Quoted 10 lines · Steven Rostedt
Quoted 5 lines
include/linux/ring_buffer.h line 19
Quoted 3 lines
Index:
linux-trace.git/include/linux/ring_buffer.hinclude/linux/ring_buffer.h new file +2
-0+enum { +RB_TYPE_PADDING ,/* Left over page padding
RB_clashes with red-black tree namespace. (on the thought level)Yeah, Linus pointed this out with the
rb_static function names. But since the functions are static I kept them as is. But here we have global names.Would
RNGBF_be OK, or do you have any other ideas?
that's even worse i think :-/ And this isnt bikeshed-painting really, the RNGBF_ name hurts my eyes and RB_ is definitely confusing to read. (as the rbtree constants are in capitals as well and similarly named)
RING_TYPE_PADDING
or:
RINGBUF_TYPE_PADDING
yes, it's longer, but still, saner.
Quoted 3 lines
Quoted 1 line
too large, please uninline.
I calculated this on
x86_64to add 78 bytes. Is that still too big?
yes, way too big. Sometimes we make savings from a 10 bytes function already. (but it's always case dependent - if a function has a lot of parameters then uninlining can hurt)
the only exception would be if there's normally only a single instantiation per tracer, and if it's in the absolute tracing hotpath.
Quoted 9 lines
Quoted 3 lines
hm, should not be raw, at least initially. I am 95% sure we'll see lockups, we always did when we iterated ftrace's buffer implementation ;-)
It was to prevent lockdep from checking the locks from inside. We had issues with ftroce and lockdep in the past, because ftrace would trace the internals of lockdep, and lockdep would then recurse back into itself to trace. If lockdep itself can get away with not using
raw_spinlocks, then this will be OK to make back to spinlock.
would be nice to make sure that ftrace's recursion checks work as intended - and the same goes for lockdep's recursion checks. Yes, we had problems in this area, and it would be nice to make sure it all works fine. (or fix it if it doesnt)
Quoted 10 lines
Quoted 8 lines
kernel/trace/ring_buffer.c line 502
Quoted 4 lines
kernel/trace/ring_buffer.c new file +4
-0+for (head =0 ; head <rb_head_size (cpu_buffer); + head +=ring_buffer_event_length (event)) { + event =rb_page_index (cpu_buffer->head_page, head); +BUG_ON (rb_null_event (event));( optional:when there's a multi-line loop then i generally try to insert
an extra newline when starting the body - to make sure the iterator and the body stands apart visually. Matter of taste. )Will fix, I have no preference.
clarification: multi-line loop _condition_. It's pretty rare (this is such a case) but sometimes unavoidable - and then the newline helps visually.
Quoted 15 lines
Quoted 10 lines
include/linux/ring_buffer.h line 27
Quoted 4 lines
include/linux/ring_buffer.h new file +4
-0+ RB_TYPE_TIME_EXTENT, /* Extent the time delta +* array[0] = time delta (28 .. 59) +* size = 8 bytes +*/ please use standard comment style:
/*
* Comment
*/Hmm, this is interesting. I kind of like this because it is not really a standard comment. It is a comment about the definitions of the enum. I believe if they are above:
Quoted 6 lines
/*
* Comment
*/
RB_ENUM_TYPE,It is not as readable. But if we do:
no, it is not readable. My point was that you should do:
Quoted 7 lines
RB_ENUM_TYPE, /* * Comment */The comment is not at the same line as the enum, which also looks unpleasing.
but you did:
Quoted 2 lines
RB_ENUM_TYPE, /* Comment*/
So i suggested to fix it to:
+ RB_TYPE_TIME_EXTENT, /*
+ * Extent the time delta
+ * array[0] = time delta (28 .. 59)
+ * size = 8 bytes
+ */
ok? I.e. "comment" should have the same visual properties as other comments.
I fully agree with moving it next to the enum, i sometimes use that style too, it's a nice touch and more readable in this case than comment-ahead. (which we use for statements)
Ingo
Steven Rostedt
maintainerQuoted 7 lines · Ingo Molnar
* Steven Rostedt <[email protected]> wrote:
that's even worse i think :-/ And this isnt bikeshed-painting really, the
RNGBF_name hurts my eyes andRB_is definitely confusing to read. (as the rbtree constants are in capitals as well and similarly named)
Quoted 7 lines
RING_TYPE_PADDINGor:
RINGBUF_TYPE_PADDINGyes, it's longer, but still, saner.
I don't mind the extra typing, it is just a bit more difficult to keep in the 80 character line limit.
Quoted 11 lines
Quoted 4 lines
Quoted 2 lines
too large, please uninline.
I calculated this on
x86_64to add 78 bytes. Is that still too big?yes, way too big. Sometimes we make savings from a 10 bytes function already. (but it's always case dependent - if a function has a lot of parameters then uninlining can hurt)
the only exception would be if there's normally only a single instantiation per tracer, and if it's in the absolute tracing hotpath.
It is a hot path in the internals. Perhaps I'll make an inline function in the interal code "rb_event_length" and have the other users call.
unsigned ring_buffer_event(struct ring_buffer_event *event)
{
return rb_event_length(event);
}Quoted 22 lines
no, it is not readable. My point was that you should do:
Quoted 7 lines
RB_ENUM_TYPE, /* * Comment */The comment is not at the same line as the enum, which also looks unpleasing.
but you did:
Quoted 2 lines
RB_ENUM_TYPE, /* Comment*/So i suggested to fix it to:
+
RB_TYPE_TIME_EXTENT, /*
+ * Extent the time delta
+ * array[0] = time delta (28 .. 59)
+ * size = 8 bytes
+ */
Quoted 6 lines
ok? I.e. "comment" should have the same visual properties as other comments.
I fully agree with moving it next to the enum, i sometimes use that style too, it's a nice touch and more readable in this case than comment-ahead. (which we use for statements)
But then we have:
RB_TYPE_PADDING, /*
* Left over page padding
* array is ignored
* size is variable depending on
* how much padding is needed */
RB_TYPE_TIME_EXTENT, /*
* Extent the time delta
* array[0] = time delta (28 .. 59)
* size = 8 bytes
*/
Where it is not as easy to see which comment is with which enum. Especially when you have many enums. That's why I like the method I used with:
RB_TYPE_PADDING, /* Left over page padding
* array is ignored
* size is variable depending on
* how much padding is needed */
RB_TYPE_TIME_EXTENT, /* Extent the time delta
* array[0] = time delta (28 .. 59)
* size = 8 bytes
*/
Where it is very easy to notice which comment goes with which enum.
-- Steve
Quoted 6 lines · Steven Rostedt
Quoted 3 lines
RINGBUF_TYPE_PADDINGyes, it's longer, but still, saner.
I don't mind the extra typing, it is just a bit more difficult to keep in the 80 character line limit.
that's really not a hard limit, but yeah.
generally, with clean and simple functions it's easy to keep it.
Quoted 8 lines
Quoted 7 lines
yes, way too big. Sometimes we make savings from a 10 bytes function already. (but it's always case dependent - if a function has a lot of parameters then uninlining can hurt)
the only exception would be if there's normally only a single instantiation per tracer, and if it's in the absolute tracing hotpath.
Quoted 8 lines
It is a hot path in the internals. Perhaps I'll make an inline function in the interal code "
rb_event_length" and have the other users call.unsigned
ring_buffer_event(struct ring_buffer_event *event){ return rb_event_length(event); }
yeah, sounds sane.
Quoted 58 lines
Quoted 22 lines
no, it is not readable. My point was that you should do:
Quoted 7 lines
RB_ENUM_TYPE, /* * Comment */The comment is not at the same line as the enum, which also looks unpleasing.
but you did:
Quoted 2 lines
RB_ENUM_TYPE, /* Comment*/So i suggested to fix it to:
+
RB_TYPE_TIME_EXTENT, /*
+ * Extent the time delta
+ * array[0] = time delta (28 .. 59)
+ * size = 8 bytes
+ */Quoted 6 lines
ok? I.e. "comment" should have the same visual properties as other comments.
I fully agree with moving it next to the enum, i sometimes use that style too, it's a nice touch and more readable in this case than comment-ahead. (which we use for statements)
But then we have:
RB_TYPE_PADDING, /*
* Left over page padding
* array is ignored
* size is variable depending on
* how much padding is needed */
RB_TYPE_TIME_EXTENT, /*
* Extent the time delta
* array[0] = time delta (28 .. 59)
* size = 8 bytes
*/Where it is not as easy to see which comment is with which enum. Especially when you have many enums. That's why I like the method I used with:
RB_TYPE_PADDING, /* Left over page padding
* array is ignored
* size is variable depending on
* how much padding is needed */
RB_TYPE_TIME_EXTENT, /* Extent the time delta
* array[0] = time delta (28 .. 59)
* size = 8 bytes
*/
Quoted 1 line
Where it is very easy to notice which comment goes with which enum.
this:
Quoted 7 lines
RB_TYPE_PADDING, /*
* Left over page padding
* array is ignored
* size is variable depending on
* how much padding is needed */
Quoted 5 lines
RB_TYPE_TIME_EXTENT, /*
* Extent the time delta
* array[0] = time delta (28 .. 59)
* size = 8 bytes
*/
or:
Quoted 11 lines
/* * Left over page padding. 'array' is ignored, * 'size' is variable depending on how much padding is needed. */ RB_TYPE_PADDING, /* * Extent the time delta, * array[0] = time delta (28 .. 59), size = 8 bytes */ RB_TYPE_TIME_EXTENT,
oh, btw., that's a spelling mistake: s/extend/extend ?
Ingo
Steven Rostedt
maintainerQuoted 7 lines · Ingo Molnar
Quoted 7 lines
Quoted 7 lines
no, it is not readable. My point was that you should do:
Quoted 5 lines
RB_ENUM_TYPE, /* * Comment */
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 2 lines
The comment is not at the same line as the enum, which also looks unpleasing.
but you did:
Quoted 2 lines
RB_ENUM_TYPE, /* Comment*/
OK, I did a quick survey of what others did in include/linux to handle multi line comments for enums. I ignored the single line comments since that is pretty standard. Here's what I found:
Those that do:
enum myenum {
ENUM_PING_PONG, /* Bounce a ball back and forth
till you have a winner. */
ENUM_HONEY_CONE, /* Soft and sweet a yummy for
the tummy. */
};
include/linux/atmdev.hinclude/linux/fd.hinclude/linux/hil.hinclude/linux/if_pppol2tp.hinclude/linux/ivtv.hinclude/linux/libata.hinclude/linux/mmzone.hinclude/linux/reiserfs_fs.hinclude/linux/reiserfs_fs_sb.hinclude/linux/rtnetlink.hinclude/linux/scc.hinclude/linux/videodev2.h
Those that do:
enum myenum {
ENUM_PING_PONG, /* Bounce a ball back and forth */
/* till you have a winner. */
ENUM_HONEY_CONE, /* Soft and sweet a yummy for */
/* the tummy. */
};
include/linux/atmsvc.hinclude/linux/pktcdvd.h
Those that do (what I did):
enum myenum {
ENUM_PING_PONG, /* Bounce a ball back and forth
* till you have a winner. */
ENUM_HONEY_CONE, /* Soft and sweet a yummy for
* the tummy.
*/
};
include/linux/buffer_head.h (with space between the two enums) include/linux/personality.h
Those that do:
enum myenum {
/*
* Bounce a ball back and forth
* till you have a winner.
*/
ENUM_PING_PONG,
/*
* Soft and sweet a yummy for
* the tummy.
*/
ENUM_HONEY_CONE,
};include/linux/cgroup.hinclude/linux/cn_proc.hinclude/linux/exportfs.hinclude/linux/fb.hinclude/linux/hil_mlc.hinclude/linux/pci.hinclude/linux/reiserfs_fs_i.h
And finally Doc book style:
/**
* enum myenum
* @ENUM_PING_PONG: Bounce a ball back and forth
* till you have a winner.
* @ENUM_HONEY_CONE: Soft and sweet a yummy for
* the tummy.
*/
enum myenum {
ENUM_PING_PONG,
ENUM_HONEY_CONE,
};
Note I did not see any enum users that did what you asked:
enum myenum {
ENUM_PING_PONG, /*
* Bounce a ball back and forth
* till you have a winner. */
ENUM_HONEY_CONE, /*
* Soft and sweet a yummy for
* the tummy.
*/
};
So by adding that, I will be adding yet another format.
Actually I think the docbook style is the most appropriate for me. I'll go with that one.
Thanks,
-- Steve
Quoted 6 lines
Quoted 6 lines
that's even worse i think :-/ And this isnt bikeshed-painting really, the
RNGBF_name hurts my eyes andRB_is definitely confusing to read. (as the rbtree constants are in capitals as well and similarly named)
RING_TYPE_PADDING
Quoted 8 lines
Quoted 5 lines
or:
RINGBUF_TYPE_PADDINGyes, it's longer, but still, saner.
I don't mind the extra typing, it is just a bit more difficult to keep in the 80 character line limit.
Would using tb_ (trace buffer) rather than rb_ help ?
Quoted 8 lines · Martin Bligh
Quoted 8 lines
Quoted 8 lines
that's even worse i think :-/ And this isnt bikeshed-painting really, the
RNGBF_name hurts my eyes andRB_is definitely confusing to read. (as the rbtree constants are in capitals as well and similarly named)
RING_TYPE_PADDINGor:
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
RINGBUF_TYPE_PADDINGyes, it's longer, but still, saner.
I don't mind the extra typing, it is just a bit more difficult to keep in the 80 character line limit.
Would using
tb_(trace buffer) rather thanrb_help ?
excellent idea ...
Ingo
Steven Rostedt
maintainerPATCH v10 1/1 Unified trace buffer
In reply to Steven Rostedt[
This is the final version of this patch. From now on, I will be sending changes on top of this patch.
Changes since v9:
All suggestions from Ingo Molnar.
- Changed comment of enum to DocBook style.
- Replaced the RB_TYPE_ enums with RINGBUF_TYPE_ prefixes to avoid name collision with rbtree. Note, I did not use the TB_ extension because I envision a "trace_buffer" layer on top of this layer in the future.
- Moved ring_buffer_event_{length,data} into the .c file and added internal inlines. External uses will need to call the function.
- Broke out rb_add_time_stamp function from rb_reserve_next_event.
- made the cpu_buffer->lock back to a normal spin lock.
- The rest are style changes.
]
This is a unified tracing buffer that implements a ring buffer that hopefully everyone will eventually be able to use.
The events recorded into the buffer have the following structure:
struct ring_buffer_event {
u32 type:2, len:3, time_delta:27;
u32 array[];
};The minimum size of an event is 8 bytes. All events are 4 byte aligned inside the buffer.
There are 4 types (all internal use for the ring buffer, only the data type is exported to the interface users).
RINGBUF_TYPE_PADDING: this type is used to note extra space at the end
of a buffer page.
RINGBUF_TYPE_TIME_EXTENT: This type is used when the time between events
is greater than the 27 bit delta can hold. We add another 32 bits, and record that in its own event (8 byte size).
RINGBUF_TYPE_TIME_STAMP: (Not implemented yet). This will hold data to
help keep the buffer timestamps in sync.
RINGBUF_TYPE_DATA: The event actually holds user data.
The "len" field is only three bits. Since the data must be 4 byte aligned, this field is shifted left by 2, giving a max length of 28 bytes. If the data load is greater than 28 bytes, the first array field holds the full length of the data load and the len field is set to zero.
Example, data size of 7 bytes:
type = RINGBUF_TYPE_DATA len = 2 time_delta: <time-stamp> - <prev_event-time-stamp> array[0..1]: <7 bytes of data> <1 byte empty>
This event is saved in 12 bytes of the buffer.
An event with 82 bytes of data:
type = RINGBUF_TYPE_DATA
len = 0
time_delta: <time-stamp> - <prev_event-time-stamp> array[0]: 84 (Note the alignment) array[1..14]: <82 bytes of data> <2 bytes empty>
The above event is saved in 92 bytes (if my math is correct). 82 bytes of data, 2 bytes empty, 4 byte header, 4 byte length.
Do not reference the above event struct directly. Use the following functions to gain access to the event table, since the ring_buffer_event structure may change in the future.
ring_buffer_event_length(event): get the length of the event.
This is the size of the memory used to record this event, and not the size of the data pay load.
ring_buffer_time_delta(event): get the time delta of the event
This returns the delta time stamp since the last event.
Note: Even though this is in the header, there should
be no reason to access this directly, accept for debugging.
ring_buffer_event_data(event): get the data from the event
This is the function to use to get the actual data from the event. Note, it is only a pointer to the data inside the buffer. This data must be copied to another location otherwise you risk it being written over in the buffer.
ring_buffer_lock: A way to lock the entire buffer.ring_buffer_unlock: unlock the buffer.
ring_buffer_alloc: create a new ring buffer. Can choose between
overwrite or consumer/producer mode. Overwrite will overwrite old data, where as consumer producer will throw away new data if the consumer catches up with the producer. The consumer/producer is the default.
ring_buffer_free: free the ring buffer.
ring_buffer_resize: resize the buffer. Changes the size of each cpu
buffer. Note, it is up to the caller to provide that the buffer is not being used while this is happening. This requirement may go away but do not count on it.
ring_buffer_lock_reserve: locks the ring buffer and allocates an
entry on the buffer to write to.ring_buffer_unlock_commit: unlocks the ring buffer and commits it to
the buffer.
ring_buffer_write: writes some data into the ring buffer.
ring_buffer_peek: Look at a next item in the cpu buffer.ring_buffer_consume: get the next item in the cpu buffer and
consume it. That is, this function increments the head pointer.
ring_buffer_read_start: Start an iterator of a cpu buffer.
For now, this disables the cpu buffer, until you issue a finish. This is just because we do not want the iterator to be overwritten. This restriction may change in the future. But note, this is used for static reading of a buffer which is usually done "after" a trace. Live readings would want to use the ring_buffer_consume above, which will not disable the ring buffer.
ring_buffer_read_finish: Finishes the read iterator and reenables
the ring buffer.
ring_buffer_iter_peek: Look at the next item in the cpu iterator.ring_buffer_read: Read the iterator and increment it.ring_buffer_iter_reset: Reset the iterator to point to the beginning
of the cpu buffer.ring_buffer_iter_empty: Returns true if the iterator is at the end
of the cpu buffer.
ring_buffer_size: returns the size in bytes of each cpu buffer.
Note, the real size is this times the number of CPUs.
ring_buffer_reset_cpu: Sets the cpu buffer to emptyring_buffer_reset: sets all cpu buffers to empty
ring_buffer_swap_cpu: swaps a cpu buffer from one buffer with a
cpu buffer of another buffer. This is handy when you want to take a snap shot of a running trace on just one cpu. Having a backup buffer, to swap with facilitates this. Ftrace max latencies use this.
ring_buffer_empty: Returns true if the ring buffer is empty.ring_buffer_empty_cpu: Returns true if the cpu buffer is empty.
ring_buffer_record_disable: disable all cpu buffers (read only) ring_buffer_record_disable_cpu: disable a single cpu buffer (read only)ring_buffer_record_enable: enable all cpu buffers. ring_buffer_record_enabl_cpu: enable a single cpu buffer.
ring_buffer_entries: The number of entries in a ring buffer.ring_buffer_overruns: The number of entries removed due to writing wrap.
ring_buffer_time_stamp: Get the time stamp used by the ring buffer ring_buffer_normalize_time_stamp: normalize the ring buffer time stamp
into nanosecs.
I still need to implement the GTOD feature. But we need support from the cpu frequency infrastructure. But this can be done at a later time without affecting the ring buffer interface.
--- include/linux/ring_buffer.h | 130 +++ kernel/trace/Kconfig | 4 kernel/trace/Makefile | 1 kernel/trace/ring_buffer.c | 1672 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1807 insertions(+)
include/linux/ring_buffer.h new file +130 -0
@@ -0,0 +1,130 @@ +#ifndef _LINUX_RING_BUFFER_H +#define _LINUX_RING_BUFFER_H + +#include <linux/mm.h> +#include <linux/seq_file.h> + +struct ring_buffer ; +struct ring_buffer_iter ; + +/* +* Don't reference this struct directly, use functions below. +*/ +struct ring_buffer_event { +u32 type:2 , len:3 , time_delta:27 ; +u32 array[]; +}; + +/** +* enum ring_buffer_type - internal ring buffer types +* +* @RINGBUF_TYPE_PADDING: Left over page padding +* array is ignored +* size is variable depending on how much +* padding is needed +* +* @RINGBUF_TYPE_TIME_EXTEND: Extend the time delta +* array[0] = time delta (28 .. 59) +* size = 8 bytes +* +* @RINGBUF_TYPE_TIME_STAMP: Sync time stamp with external clock +* array[0] = tv_nsec +* array[1] = tv_sec +* size = 16 bytes +* +* @RINGBUF_TYPE_DATA: Data record +* If len is zero: +* array[0] holds the actual length +* array[1..(length+3)/4-1] holds data +* else +* length = len << 2 +* array[0..(length+3)/4] holds data +*/ +enum ring_buffer_type { +RINGBUF_TYPE_PADDING , +RINGBUF_TYPE_TIME_EXTEND , +/* FIXME: RINGBUF_TYPE_TIME_STAMP not implemented */ +RINGBUF_TYPE_TIME_STAMP , +RINGBUF_TYPE_DATA , +}; + +unsigned ring_buffer_event_length (struct ring_buffer_event *event); +void *ring_buffer_event_data (struct ring_buffer_event *event); + +/** +* ring_buffer_event_time_delta - return the delta timestamp of the event +* @event: the event to get the delta timestamp of +* +* The delta timestamp is the 27 bit timestamp since the last event. +*/ +static inline unsigned +ring_buffer_event_time_delta (struct ring_buffer_event *event) +{ +return event->time_delta; +} + +void ring_buffer_lock (struct ring_buffer *buffer,unsigned long *flags); +void ring_buffer_unlock (struct ring_buffer *buffer,unsigned long flags); + +/* +* size is in bytes for each per CPU buffer. +*/ +struct ring_buffer * +ring_buffer_alloc (unsigned long size,unsigned flags); +void ring_buffer_free (struct ring_buffer *buffer); + +int ring_buffer_resize (struct ring_buffer *buffer,unsigned long size); + +struct ring_buffer_event * +ring_buffer_lock_reserve (struct ring_buffer *buffer, +unsigned long length, +unsigned long *flags); +int ring_buffer_unlock_commit (struct ring_buffer *buffer, +struct ring_buffer_event *event, +unsigned long flags); +int ring_buffer_write (struct ring_buffer *buffer, +unsigned long length,void *data); + +struct ring_buffer_event * +ring_buffer_peek (struct ring_buffer *buffer,int cpu,u64 *ts); +struct ring_buffer_event * +ring_buffer_consume (struct ring_buffer *buffer,int cpu,u64 *ts); + +struct ring_buffer_iter * +ring_buffer_read_start (struct ring_buffer *buffer,int cpu); +void ring_buffer_read_finish (struct ring_buffer_iter *iter); + +struct ring_buffer_event * +ring_buffer_iter_peek (struct ring_buffer_iter *iter,u64 *ts); +struct ring_buffer_event * +ring_buffer_read (struct ring_buffer_iter *iter,u64 *ts); +void ring_buffer_iter_reset (struct ring_buffer_iter *iter); +int ring_buffer_iter_empty (struct ring_buffer_iter *iter); + +unsigned long ring_buffer_size (struct ring_buffer *buffer); + +void ring_buffer_reset_cpu (struct ring_buffer *buffer,int cpu); +void ring_buffer_reset (struct ring_buffer *buffer); + +int ring_buffer_swap_cpu (struct ring_buffer *buffer_a, +struct ring_buffer *buffer_b,int cpu); + +int ring_buffer_empty (struct ring_buffer *buffer); +int ring_buffer_empty_cpu (struct ring_buffer *buffer,int cpu); + +void ring_buffer_record_disable (struct ring_buffer *buffer); +void ring_buffer_record_enable (struct ring_buffer *buffer); +void ring_buffer_record_disable_cpu (struct ring_buffer *buffer,int cpu); +void ring_buffer_record_enable_cpu (struct ring_buffer *buffer,int cpu); + +unsigned long ring_buffer_entries (struct ring_buffer *buffer); +unsigned long ring_buffer_overruns (struct ring_buffer *buffer); + +u64 ring_buffer_time_stamp (int cpu); +void ring_buffer_normalize_time_stamp (int cpu,u64 *ts); + +enum ring_buffer_flags { +RB_FL_OVERWRITE =1 <<0 , +}; + +#endif /* _LINUX_RING_BUFFER_H */
kernel/trace/ring_buffer.c new file +1672 -0
1,672 lines not on this page · raw message
kernel/trace/Kconfig +4 -0
@@ -10,10 +10,14 @@ config HAVE_DYNAMIC_FTRACE config TRACER_MAX_TRACE bool +config RING_BUFFER + bool + config TRACING bool select DEBUG_FS select STACKTRACE + select RING_BUFFER config FTRACE bool "Kernel Function Tracer"
kernel/trace/Makefile +1 -0
@@ -11,6 +11,7 @@ obj-y += trace_selftest_dynamic.o endif obj-$(CONFIG_FTRACE) += libftrace.o +obj-$(CONFIG_RING_BUFFER) += ring_buffer.o obj-$(CONFIG_TRACING) += trace.o obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
Steven Rostedt
maintainerIngo,
I will add this patch to my linux-tip and then I will start porting ftrace over to it in an incremental fashion.
-- Steve
* Steven Rostedt ([email protected]) wrote:
[...]
Quoted 8 lines
kernel/trace/ring_buffer.c new file +8
-0+/* +* This hack stolen from mm/slob.c. +* We can store per page timing information in the page frame of the page. +* Thanks to Peter Zijlstra for suggesting this idea. +*/ +struct buffer_page { + union { + struct {
kernel/trace/ring_buffer.c line 129
Quoted 10 lines
kernel/trace/ring_buffer.c new file +10
-0+unsigned long flags;/* mandatory */ +atomic_t _count;/* mandatory */ +u64 time_stamp;/* page time stamp */ +unsigned size;/* size of page data */ +struct list_head list;/* list of free pages */ + }; +struct page page; + }; +}; +
Hi Steven,
You should have a look at mm/slob.c free_slob_page(). I think your page free will generate a "bad_page" call due to mapping != NULL and mapcount != 0. I just ran into this in my own code. :)
Regards,
Mathieu
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Steven Rostedt
maintainerQuoted 5 lines · Mathieu Desnoyers
* Steven Rostedt ([email protected]) wrote:
You should have a look at
mm/slob.cfree_slob_page(). I think your page free will generate a "bad_page" call due to mapping != NULL and mapcount != 0. I just ran into this in my own code. :)
Hi Mathieu!
Thanks! I must have been lucky some how not to trigger this :-/
I'll add an update patch for this.
-- Steve
Quoted 5 lines · * Steven Rostedt ([email protected]) wrote:
Quoted 2 lines · Mathieu Desnoyers
* Steven Rostedt ([email protected]) wrote:
Quoted 9 lines
Quoted 3 lines
You should have a look at
mm/slob.cfree_slob_page(). I think your page free will generate a "bad_page" call due to mapping != NULL and mapcount != 0. I just ran into this in my own code. :)Hi Mathieu!
Thanks! I must have been lucky some how not to trigger this :-/
My guess is that you never free your buffers in your test cases. I don't know if it was expected; probably not if your code is built into the kernel.
Mathieu
Quoted 4 lines
I'll add an update patch for this.
-- Steve
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Steven Rostedt
maintainerQuoted 7 lines · Mathieu Desnoyers
Quoted 3 lines
Thanks! I must have been lucky some how not to trigger this :-/
My guess is that you never free your buffers in your test cases. I don't know if it was expected; probably not if your code is built into the kernel.
Actually my resize does free the buffers and I did test this. I probably never ran the trace when testing the freeing which means those pointers could have luckily not have been changed.
-- Steve
Quoted 10 lines · * Steven Rostedt ([email protected]) wrote:
Quoted 7 lines · Mathieu Desnoyers
Quoted 3 lines
Thanks! I must have been lucky some how not to trigger this :-/
My guess is that you never free your buffers in your test cases. I don't know if it was expected; probably not if your code is built into the kernel.
Quoted 6 lines
Actually my resize does free the buffers and I did test this. I probably never ran the trace when testing the freeing which means those pointers could have luckily not have been changed.
-- Steve
I also got some corruption of the offset field in the struct page I use. I think it might be related to the fact that I don't set the PG_private bit (slob does set it when the page is in its free pages list). However, given I'd like to pass the buffer pages to disk I/O and for network socket and still keep the ability to re-use it when the I/O has been performed, I wonder where I should put my
struct list_head list; /* linked list of buf pages */
size_t offset; /* page offset in the buffer */
fields ? Any ideas ?
They are currently in :
struct buf_page {
union {
struct {
unsigned long flags; /* mandatory */
atomic_t _count; /* mandatory */
union { /* mandatory */
atomic_t _mapcount;
struct {
u16 inuse;
u16 objects;
};
};
struct list_head list; /* linked list of buf pages */
size_t offset; /* page offset in the buffer */
};
struct page page;
};
};Mathieu
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Steven Rostedt
maintainerQuoted 5 lines · Mathieu Desnoyers
I also got some corruption of the offset field in the struct page I use. I think it might be related to the fact that I don't set the
PG_privatebit (slob does set it when the page is in its free pages list). However, given I'd like to pass the buffer pages to disk I/O and for network
Ah, I believe the disk IO uses the page frame. That might be a bit more difficult to pass the data to disk and still keep information on the page frame.
-- Steve
Quoted 3 lines · On Tue, 30 Sep 2008 00:00:11 -0400 (EDT) Steven Rostedt <[email protected]>…
Ah, I believe the disk IO uses the page frame. That might be a bit more difficult to pass the data to disk and still keep information on the page frame.
Perhaps I'm speaking out of turn, but I have to wonder: am I the only one who gets uncomfortable looking at these hacks to overload struct page? It seems fragile as all hell; woe to he who tries to make a change to struct page someday and has to track all of this stuff down.
Are the savings gained by using struct page this way really worth the added complexity?
jon
Quoted 7 lines · Jonathan Corbet
Quoted 3 lines · On Tue, 30 Sep 2008 00:00:11 -0400 (EDT) Steven Rostedt <[email protected]>…
Ah, I believe the disk IO uses the page frame. That might be a bit more difficult to pass the data to disk and still keep information on the page frame.
Quoted 7 lines
Perhaps I'm speaking out of turn, but I have to wonder: am I the only one who gets uncomfortable looking at these hacks to overload struct page? It seems fragile as all hell; woe to he who tries to make a change to struct page someday and has to track all of this stuff down.
Are the savings gained by using struct page this way really worth the added complexity?
Its not that complex IMHO, the thing that is ugly are those struct page overloads, what we could do is try and sanitize the regular struct page and pull all these things in.
Because the only reason people are doing these overloads is because struct page in mm_types.h is becomming an unreadable mess.
Trouble is, looking at it I see no easy way out,
Quoted 4 lines · Peter Zijlstra
Its not that complex IMHO, the thing that is ugly are those struct page overloads, what we could do is try and sanitize the regular struct page and pull all these things in.
That's not the scary part. The scary part is that somebody may well want to access the trace buffer pages in complex ways.
If you mmap them, for example, you can use VM_PFNMAP to make sure that nobody should ever look at the "struct page", but if you want to do things like direct-to-disk IO on the trace pages (either with splice() or with some kind of in-kernel IO logic), then you're officially screwed.
Quoted 2 lines
Because the only reason people are doing these overloads is because struct page in
mm_types.his becomming an unreadable mess.
The "unreadable mess" has exactly the same issues, though: people need to realize that when you overload fields in the page structure, you can then NEVER EVER use those pages for any other thing.
For the internal VM code, that's ok. The VM knows that a page is either an anonymous page or a file mapping etc, and the overloading wrt mm_types.h is explicit. The same goes for SL*B, although it does the overloading differently.
Trace buffers are different, though. Do people realize that doing the overloading means that you never EVER can use those buffers for anything else? Do people realize that it means that splice() and friends are out of the question?
Quoted 1 line
Trouble is, looking at it I see no easy way out,
Quite frankly, we could just put it at the head of the page itself. Having a "whole page" for the trace data is not possible anyway, since the trace header itself will always eat 8 bytes.
And I do think it would potentially be a better model. Or at least safer.
Linus
Steven Rostedt
maintainerQuoted 6 lines · Linus Torvalds
Trace buffers are different, though. Do people realize that doing the overloading means that you never EVER can use those buffers for anything else? Do people realize that it means that
splice()and friends are out of the question?
Quoted 7 lines
Quoted 1 line
Trouble is, looking at it I see no easy way out,
Quite frankly, we could just put it at the head of the page itself. Having a "whole page" for the trace data is not possible anyway, since the trace header itself will always eat 8 bytes.
And I do think it would potentially be a better model. Or at least safer.
Actually, looking at the code, there is no reason I need to keep this in the frame buffer itself. I've also encapsulated the accesses to the incrementing of the pointers so it would be trivial to try other approaches.
The problem we had with the big array struct is that we can want large buffers and to do that with pointers means we would need to either come up with a large allocator or use vmap.
But I just realized that I could also just make a link list of page pointers and do the exact same thing without having to worry about page frames. Again, the way I coded this up, it is quite trivial to replace the handling of the pages with other schemes.
-- Steve
Quoted 5 lines · Steven Rostedt
But I just realized that I could also just make a link list of page pointers and do the exact same thing without having to worry about page frames. Again, the way I coded this up, it is quite trivial to replace the handling of the pages with other schemes.
That might be the best option.
Yes, doing it in the 'struct page' itself is obviously going to save us some memory over having specially allocated page headers, but it's not like we'd expect to have _that_ many of these, and having a separate structure is actually good in that it also would make it simpler/clearer when/if you want to add larger pages (or other non-page allocations) into the mix.
For example, if somebody really wants bigger areas, they can allocate them with vmalloc and/or multi-page allocations, and then add them as easily to the list of pages as if it was a normal page. Doing the same with playing tricks on 'struct page' would be pretty damn painful.
Linus
Steven Rostedt
maintainerPATCH 1/1 ring_buffer: allocate buffer page pointer
The current method of overlaying the page frame as the buffer page pointer can be very dangerous and limits our ability to do other things with a page from the buffer, like send it off to disk.
This patch allocates the buffer_page instead of overlaying the page's page frame. The use of the buffer_page has hardly changed due to this.
--- kernel/trace/ring_buffer.c | 54 ++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 22 deletions(-)
kernel/trace/ring_buffer.c +32 -22
@@ -115,16 +115,10 @@ void *ring_buffer_event_data(struct ring* Thanks to Peter Zijlstra for suggesting this idea. */ struct buffer_page { -union { -struct { -unsigned long flags;/* mandatory */ -atomic_t _count;/* mandatory */ -u64 time_stamp;/* page time stamp */ -unsigned size;/* size of page data */ -struct list_head list;/* list of free pages */ - }; -struct page page; - }; +u64 time_stamp;/* page time stamp */ +unsigned size;/* size of page data */ +struct list_head list;/* list of free pages */ +void *page;/* Actual data page */ };/*
@@ -133,9 +127,9 @@ struct buffer_page {*/ static inline void free_buffer_page (struct buffer_page *bpage) { -reset_page_mapcount (&bpage->page); - bpage->page.mapping =NULL ; -__free_page (&bpage->page); +if (bpage->page) +__free_page (bpage->page); +kfree (bpage); }/*
@@ -237,11 +231,16 @@ static int rb_allocate_pages(struct ringunsigned i;for (i =0 ; i < nr_pages; i++) { + page =kzalloc_node (ALIGN (sizeof (*page),cache_line_size ()), +GFP_KERNEL ,cpu_to_node (cpu)); +if (!page) + goto free_pages; +list_add (&page->list, &pages); + addr =__get_free_page (GFP_KERNEL );if (!addr) goto free_pages; - page = (struct buffer_page *)virt_to_page (addr); -list_add (&page->list, &pages); + page->page = (void *)addr; }list_splice (&pages, head);
@@ -262,6 +261,7 @@ static struct ring_buffer_per_cpu * rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu) {struct ring_buffer_per_cpu *cpu_buffer; +struct buffer_page *page;unsigned long addr;int ret;
@@ -275,10 +275,17 @@ rb_allocate_cpu_buffer(struct ring_buffespin_lock_init (&cpu_buffer->lock);INIT_LIST_HEAD (&cpu_buffer->pages); + page =kzalloc_node (ALIGN (sizeof (*page),cache_line_size ()), +GFP_KERNEL ,cpu_to_node (cpu)); +if (!page) + goto fail_free_buffer; + + cpu_buffer->reader_page = page; addr =__get_free_page (GFP_KERNEL );if (!addr) - goto fail_free_buffer; - cpu_buffer->reader_page = (struct buffer_page *)virt_to_page (addr); + goto fail_free_reader; + page->page = (void *)addr; +INIT_LIST_HEAD (&cpu_buffer->reader_page->list); cpu_buffer->reader_page->size =0 ;
@@ -523,11 +530,16 @@ int ring_buffer_resize(struct ring_buffefor_each_buffer_cpu (buffer, cpu) {for (i =0 ; i < new_pages; i++) { + page =kzalloc_node (ALIGN (sizeof (*page), +cache_line_size ()), +GFP_KERNEL ,cpu_to_node (cpu)); +if (!page) + goto free_pages; +list_add (&page->list, &pages); addr =__get_free_page (GFP_KERNEL );if (!addr) goto free_pages; - page = (struct buffer_page *)virt_to_page (addr); -list_add (&page->list, &pages); + page->page = (void *)addr; } }
@@ -567,9 +579,7 @@ static inline int rb_null_event(struct rstatic inline void *rb_page_index (struct buffer_page *page,unsigned index) { -void *addr =page_address (&page->page); - -return addr + index; +return page->page + index; } static inline struct ring_buffer_event *
Re: [PATCH] ring_buffer: allocate buffer page pointer
Quoted 79 lines · * Steven Rostedt ([email protected]) wrote:
The current method of overlaying the page frame as the buffer page pointer can be very dangerous and limits our ability to do other things with a page from the buffer, like send it off to disk.
This patch allocates the
buffer_pageinstead of overlaying the page's page frame. The use of thebuffer_pagehas hardly changed due to this.Signed-off-by Steven Rostedt <[email protected]>--- kernel/trace/ring_buffer.c | 54 ++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 22 deletions(-)Index:
linux-tip.git/kernel/trace/ring_buffer.c
===================================================================kernel/trace/ring_buffer.c +15
-15@@ -115,16 +115,10 @@ void *ring_buffer_event_data(struct ring* Thanks to Peter Zijlstra for suggesting this idea. */ struct buffer_page { -union { -struct { -unsigned long flags;/* mandatory */ -atomic_t _count;/* mandatory */ -u64 time_stamp;/* page time stamp */ -unsigned size;/* size of page data */ -struct list_head list;/* list of free pages */ - }; -struct page page; - }; +u64 time_stamp;/* page time stamp */ +unsigned size;/* size of page data */ +struct list_head list;/* list of free pages */ +void *page;/* Actual data page */ };/* @@ -133,9 +127,9 @@ struct buffer_page {*/ static inline void free_buffer_page (struct buffer_page *bpage) { -reset_page_mapcount (&bpage->page); - bpage->page.mapping =NULL ; -__free_page (&bpage->page); +if (bpage->page) +__free_page (bpage->page); +kfree (bpage); }/* @@ -237,11 +231,16 @@ static int rb_allocate_pages(struct ringunsigned i;for (i =0 ; i < nr_pages; i++) { + page =kzalloc_node (ALIGN (sizeof (*page),cache_line_size ()), +GFP_KERNEL ,cpu_to_node (cpu)); +if (!page) + goto free_pages; +list_add (&page->list, &pages); + addr =__get_free_page (GFP_KERNEL );if (!addr) goto free_pages; - page = (struct buffer_page *)virt_to_page (addr); -list_add (&page->list, &pages); + page->page = (void *)addr; }list_splice (&pages, head);@@ -262,6 +261,7 @@ static struct ring_buffer_per_cpu * rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu) {struct ring_buffer_per_cpu *cpu_buffer; +struct buffer_page *page;unsigned long addr;int ret;
kernel/trace/ring_buffer.c rb_allocate_cpu_buffer(struct ring_buffe · line 279
Quoted 5 lines
kernel/trace/ring_buffer.c +2
-0@@ -275,10 +275,17 @@ rb_allocate_cpu_buffer(struct ring_buffespin_lock_init (&cpu_buffer->lock);INIT_LIST_HEAD (&cpu_buffer->pages); + page =kzalloc_node (ALIGN (sizeof (*page),cache_line_size ()), +GFP_KERNEL ,cpu_to_node (cpu));
Hi Steven,
I understand that you want to allocate these struct buffer_page in memory local to a given cpu node, which is great, but why do you feel you need to align them on cache_line_size() ?
Hrm.. you put the timestamp in there, so I guess you're concerned about having a writer on one CPU, a reader on another, and the fact that you will have cache line bouncing because of that.
Note that if you put the timestamp and the unused bytes in a tiny header at the beginning of the page, you
1 - make this information directly accessible for disk, network I/O without any other abstraction layer.
2 - won't have to do such alignment on the struct buffer_page, because it will only be read once it's been allocated.
My 2 cents ;)
Mathieu
Quoted 46 lines
kernel/trace/ring_buffer.c +15
-7+if (!page) + goto fail_free_buffer; + + cpu_buffer->reader_page = page; addr =__get_free_page (GFP_KERNEL );if (!addr) - goto fail_free_buffer; - cpu_buffer->reader_page = (struct buffer_page *)virt_to_page (addr); + goto fail_free_reader; + page->page = (void *)addr; +INIT_LIST_HEAD (&cpu_buffer->reader_page->list); cpu_buffer->reader_page->size =0 ;@@ -523,11 +530,16 @@ int ring_buffer_resize(struct ring_buffefor_each_buffer_cpu (buffer, cpu) {for (i =0 ; i < new_pages; i++) { + page =kzalloc_node (ALIGN (sizeof (*page), +cache_line_size ()), +GFP_KERNEL ,cpu_to_node (cpu)); +if (!page) + goto free_pages; +list_add (&page->list, &pages); addr =__get_free_page (GFP_KERNEL );if (!addr) goto free_pages; - page = (struct buffer_page *)virt_to_page (addr); -list_add (&page->list, &pages); + page->page = (void *)addr; } }@@ -567,9 +579,7 @@ static inline int rb_null_event(struct rstatic inline void *rb_page_index (struct buffer_page *page,unsigned index) { -void *addr =page_address (&page->page); - -return addr + index; +return page->page + index; } static inline struct ring_buffer_event *
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Steven Rostedt
maintainerRe: [PATCH] ring_buffer: allocate buffer page pointer
Quoted 9 lines · Mathieu Desnoyers
I understand that you want to allocate these struct
buffer_pagein memory local to a given cpu node, which is great, but why do you feel you need to align them oncache_line_size()?Hrm.. you put the timestamp in there, so I guess you're concerned about having a writer on one CPU, a reader on another, and the fact that you will have cache line bouncing because of that.
Quoted 8 lines
Note that if you put the timestamp and the unused bytes in a tiny header at the beginning of the page, you
1 - make this information directly accessible for disk, network I/O without any other abstraction layer.
2 - won't have to do such alignment on the structbuffer_page, because it will only be read once it's been allocated.
That was the approach I actually started with. But someone (I think Peter) asked me to remove it.
Who knows, perhaps I can put it back. It's not that hard to do. This is why I used BUF_PAGE_SIZE to determine the size of the buffer page. Right now it BUF_PAGE_SIZE == PAGE_SIZE, but if we do add a header than it will be BUF_PAGE_SIZE == PAGE_SIZE - sizeof(header)
-- Steve
Re: [PATCH] ring_buffer: allocate buffer page pointer
In reply to Steven RostedtQuoted 52 lines · * Steven Rostedt ([email protected]) wrote:
The current method of overlaying the page frame as the buffer page pointer can be very dangerous and limits our ability to do other things with a page from the buffer, like send it off to disk.
This patch allocates the
buffer_pageinstead of overlaying the page's page frame. The use of thebuffer_pagehas hardly changed due to this.Signed-off-by Steven Rostedt <[email protected]>--- kernel/trace/ring_buffer.c | 54 ++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 22 deletions(-)Index:
linux-tip.git/kernel/trace/ring_buffer.c
===================================================================kernel/trace/ring_buffer.c +7
-13@@ -115,16 +115,10 @@ void *ring_buffer_event_data(struct ring* Thanks to Peter Zijlstra for suggesting this idea. */ struct buffer_page { -union { -struct { -unsigned long flags;/* mandatory */ -atomic_t _count;/* mandatory */ -u64 time_stamp;/* page time stamp */ -unsigned size;/* size of page data */ -struct list_head list;/* list of free pages */ - }; -struct page page; - }; +u64 time_stamp;/* page time stamp */ +unsigned size;/* size of page data */ +struct list_head list;/* list of free pages */ +void *page;/* Actual data page */ };/* @@ -133,9 +127,9 @@ struct buffer_page {*/ static inline void free_buffer_page (struct buffer_page *bpage) { -reset_page_mapcount (&bpage->page); - bpage->page.mapping =NULL ; -__free_page (&bpage->page); +if (bpage->page) +__free_page (bpage->page); +kfree (bpage); }/*
kernel/trace/ring_buffer.c static int rb_allocate_pages(struct ring · line 240
Quoted 10 lines
kernel/trace/ring_buffer.c +6
-0@@ -237,11 +231,16 @@ static int rb_allocate_pages(struct ringunsigned i;for (i =0 ; i < nr_pages; i++) { + page =kzalloc_node (ALIGN (sizeof (*page),cache_line_size ()), +GFP_KERNEL ,cpu_to_node (cpu)); +if (!page) + goto free_pages; +list_add (&page->list, &pages); + addr =__get_free_page (GFP_KERNEL );
You could probably use alloc_pages_node instead here...
Mathieu
Quoted 68 lines
kernel/trace/ring_buffer.c +19
-9if (!addr) goto free_pages; - page = (struct buffer_page *)virt_to_page (addr); -list_add (&page->list, &pages); + page->page = (void *)addr; }list_splice (&pages, head);@@ -262,6 +261,7 @@ static struct ring_buffer_per_cpu * rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu) {struct ring_buffer_per_cpu *cpu_buffer; +struct buffer_page *page;unsigned long addr;int ret;@@ -275,10 +275,17 @@ rb_allocate_cpu_buffer(struct ring_buffespin_lock_init (&cpu_buffer->lock);INIT_LIST_HEAD (&cpu_buffer->pages); + page =kzalloc_node (ALIGN (sizeof (*page),cache_line_size ()), +GFP_KERNEL ,cpu_to_node (cpu)); +if (!page) + goto fail_free_buffer; + + cpu_buffer->reader_page = page; addr =__get_free_page (GFP_KERNEL );if (!addr) - goto fail_free_buffer; - cpu_buffer->reader_page = (struct buffer_page *)virt_to_page (addr); + goto fail_free_reader; + page->page = (void *)addr; +INIT_LIST_HEAD (&cpu_buffer->reader_page->list); cpu_buffer->reader_page->size =0 ;@@ -523,11 +530,16 @@ int ring_buffer_resize(struct ring_buffefor_each_buffer_cpu (buffer, cpu) {for (i =0 ; i < new_pages; i++) { + page =kzalloc_node (ALIGN (sizeof (*page), +cache_line_size ()), +GFP_KERNEL ,cpu_to_node (cpu)); +if (!page) + goto free_pages; +list_add (&page->list, &pages); addr =__get_free_page (GFP_KERNEL );if (!addr) goto free_pages; - page = (struct buffer_page *)virt_to_page (addr); -list_add (&page->list, &pages); + page->page = (void *)addr; } }@@ -567,9 +579,7 @@ static inline int rb_null_event(struct rstatic inline void *rb_page_index (struct buffer_page *page,unsigned index) { -void *addr =page_address (&page->page); - -return addr + index; +return page->page + index; } static inline struct ring_buffer_event *
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Ingo Molnar
AppliedRe: [PATCH] ring_buffer: allocate buffer page pointer
In reply to Steven RostedtQuoted 5 lines · Steven Rostedt
The current method of overlaying the page frame as the buffer page pointer can be very dangerous and limits our ability to do other things with a page from the buffer, like send it off to disk.
Quoted 7 lines
This patch allocates the
buffer_pageinstead of overlaying the page's page frame. The use of thebuffer_pagehas hardly changed due to this.Signed-off-by Steven Rostedt <[email protected]>--- kernel/trace/ring_buffer.c | 54 ++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 22 deletions(-)
applied to tip/tracing/ftrace, with the extended changlog below - i think this commit warrants that extra mention.
Ingo
--------------->
Quoted 1 line
From
da78331b4ced2763322d732ac5ba275965853bdeMon Sep 17 00:00:00 2001
From: Steven Rostedt <[email protected]>
Date: Wed, 1 Oct 2008 10:52:51 -0400
Subject: [PATCH] ftrace: type cast filter+verifier
The mmiotrace map had a bug that would typecast the entry from the trace to the wrong type. That is a known danger of C typecasts, there's absolutely zero checking done on them.
Help that problem a bit by using a GCC extension to implement a type filter that restricts the types that a trace record can be cast into, and by adding a dynamic check (in debug mode) to verify the type of the entry.
This patch adds a macro to assign all entries of ftrace using the type of the variable and checking the entry id. The typecasts are now done in the macro for only those types that it knows about, which should be all the types that are allowed to be read from the tracer.
--- kernel/trace/trace.c | 85 ++++++++++++++++++++++++++++------------ kernel/trace/trace.h | 42 ++++++++++++++++++++ kernel/trace/trace_mmiotrace.c | 14 +++++-- 3 files changed, 112 insertions(+), 29 deletions(-)
kernel/trace/trace.c +60 -25
@@ -1350,7 +1350,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) }switch (entry->type) {case TRACE_FN : { -struct ftrace_entry *field = (struct ftrace_entry *)entry; +struct ftrace_entry *field; + +trace_assign_type (field, entry);seq_print_ip_sym (s, field->ip, sym_flags);trace_seq_puts (s," (" );
@@ -1363,8 +1365,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) }case TRACE_CTX :case TRACE_WAKE : { -struct ctx_switch_entry *field = - (struct ctx_switch_entry *)entry; +struct ctx_switch_entry *field; + +trace_assign_type (field, entry);T = field->next_state <sizeof (state_to_char) ? state_to_char[field->next_state] :'X' ;
@@ -1384,7 +1387,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)break ; }case TRACE_SPECIAL : { -struct special_entry *field = (struct special_entry *)entry; +struct special_entry *field; + +trace_assign_type (field, entry); trace_seq_printf(s, "# %ld %ld %ld\n", field->arg1,
@@ -1393,7 +1398,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)break ; }case TRACE_STACK : { -struct stack_entry *field = (struct stack_entry *)entry; +struct stack_entry *field; + +trace_assign_type (field, entry);for (i =0 ; i <FTRACE_STACK_ENTRIES ; i++) {if (i)
@@ -1404,7 +1411,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)break ; }case TRACE_PRINT : { -struct print_entry *field = (struct print_entry *)entry; +struct print_entry *field; + +trace_assign_type (field, entry);seq_print_ip_sym (s, field->ip, sym_flags);trace_seq_printf (s,": %s" , field->buf);
@@ -1454,7 +1463,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)switch (entry->type) {case TRACE_FN : { -struct ftrace_entry *field = (struct ftrace_entry *)entry; +struct ftrace_entry *field; + +trace_assign_type (field, entry); ret =seq_print_ip_sym (s, field->ip, sym_flags);if (!ret)
@@ -1480,8 +1491,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter) }case TRACE_CTX :case TRACE_WAKE : { -struct ctx_switch_entry *field = - (struct ctx_switch_entry *)entry; +struct ctx_switch_entry *field; + +trace_assign_type (field, entry);S = field->prev_state <sizeof (state_to_char) ? state_to_char[field->prev_state] :'X' ;
@@ -1501,7 +1513,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)break ; }case TRACE_SPECIAL : { -struct special_entry *field = (struct special_entry *)entry; +struct special_entry *field; + +trace_assign_type (field, entry); ret = trace_seq_printf(s, "# %ld %ld %ld\n", field->arg1,
@@ -1512,7 +1526,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)break ; }case TRACE_STACK : { -struct stack_entry *field = (struct stack_entry *)entry; +struct stack_entry *field; + +trace_assign_type (field, entry);for (i =0 ; i <FTRACE_STACK_ENTRIES ; i++) {if (i) {
@@ -1531,7 +1547,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)break ; }case TRACE_PRINT : { -struct print_entry *field = (struct print_entry *)entry; +struct print_entry *field; + +trace_assign_type (field, entry);seq_print_ip_sym (s, field->ip, sym_flags);trace_seq_printf (s,": %s" , field->buf);
@@ -1562,7 +1580,9 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter)switch (entry->type) {case TRACE_FN : { -struct ftrace_entry *field = (struct ftrace_entry *)entry; +struct ftrace_entry *field; + +trace_assign_type (field, entry); ret = trace_seq_printf(s, "%x %x\n", field->ip,
@@ -1573,8 +1593,9 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter) }case TRACE_CTX :case TRACE_WAKE : { -struct ctx_switch_entry *field = - (struct ctx_switch_entry *)entry; +struct ctx_switch_entry *field; + +trace_assign_type (field, entry);S = field->prev_state <sizeof (state_to_char) ? state_to_char[field->prev_state] :'X' ;
@@ -1596,7 +1617,9 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter) }case TRACE_SPECIAL :case TRACE_STACK : { -struct special_entry *field = (struct special_entry *)entry; +struct special_entry *field; + +trace_assign_type (field, entry); ret = trace_seq_printf(s, "# %ld %ld %ld\n", field->arg1,
@@ -1607,7 +1630,9 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter)break ; }case TRACE_PRINT : { -struct print_entry *field = (struct print_entry *)entry; +struct print_entry *field; + +trace_assign_type (field, entry);trace_seq_printf (s,"# %lx %s" , field->ip, field->buf);if (entry->flags &TRACE_FLAG_CONT )
@@ -1648,7 +1673,9 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter)switch (entry->type) {case TRACE_FN : { -struct ftrace_entry *field = (struct ftrace_entry *)entry; +struct ftrace_entry *field; + +trace_assign_type (field, entry);SEQ_PUT_HEX_FIELD_RET (s, field->ip);SEQ_PUT_HEX_FIELD_RET (s, field->parent_ip);
@@ -1656,8 +1683,9 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter) }case TRACE_CTX :case TRACE_WAKE : { -struct ctx_switch_entry *field = - (struct ctx_switch_entry *)entry; +struct ctx_switch_entry *field; + +trace_assign_type (field, entry);S = field->prev_state <sizeof (state_to_char) ? state_to_char[field->prev_state] :'X' ;
@@ -1676,7 +1704,9 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter) }case TRACE_SPECIAL :case TRACE_STACK : { -struct special_entry *field = (struct special_entry *)entry; +struct special_entry *field; + +trace_assign_type (field, entry);SEQ_PUT_HEX_FIELD_RET (s, field->arg1);SEQ_PUT_HEX_FIELD_RET (s, field->arg2);
@@ -1705,15 +1735,18 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter)switch (entry->type) {case TRACE_FN : { -struct ftrace_entry *field = (struct ftrace_entry *)entry; +struct ftrace_entry *field; + +trace_assign_type (field, entry);SEQ_PUT_FIELD_RET (s, field->ip);SEQ_PUT_FIELD_RET (s, field->parent_ip);break ; }case TRACE_CTX : { -struct ctx_switch_entry *field = - (struct ctx_switch_entry *)entry; +struct ctx_switch_entry *field; + +trace_assign_type (field, entry);SEQ_PUT_FIELD_RET (s, field->prev_pid);SEQ_PUT_FIELD_RET (s, field->prev_prio);
@@ -1725,7 +1758,9 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter) }case TRACE_SPECIAL :case TRACE_STACK : { -struct special_entry *field = (struct special_entry *)entry; +struct special_entry *field; + +trace_assign_type (field, entry);SEQ_PUT_FIELD_RET (s, field->arg1);SEQ_PUT_FIELD_RET (s, field->arg2);
kernel/trace/trace.h +42 -0
48 lines not on this page · raw message
kernel/trace/trace_mmiotrace.c +10 -4
@@ -178,15 +178,17 @@ print_out:static enum print_line_t mmio_print_rw (struct trace_iterator *iter) {struct trace_entry *entry = iter->ent; -struct trace_mmiotrace_rw *field = - (struct trace_mmiotrace_rw *)entry; -struct mmiotrace_rw *rw = &field->rw; +struct trace_mmiotrace_rw *field; +struct mmiotrace_rw *rw;struct trace_seq *s = &iter->seq;unsigned long long t =ns2usecs (iter->ts);unsigned long usec_rem =do_div (t,1000000ULL );unsigned secs = (unsigned long )t;int ret =1 ; +trace_assign_type (field, entry); + rw = &field->rw; +switch (rw->opcode) {case MMIO_READ : ret = trace_seq_printf(s,
@@ -222,13 +224,17 @@ static enum print_line_t mmio_print_rw(struct trace_iterator *iter)static enum print_line_t mmio_print_map (struct trace_iterator *iter) {struct trace_entry *entry = iter->ent; -struct mmiotrace_map *m = (struct mmiotrace_map *)entry; +struct trace_mmiotrace_map *field; +struct mmiotrace_map *m;struct trace_seq *s = &iter->seq;unsigned long long t =ns2usecs (iter->ts);unsigned long usec_rem =do_div (t,1000000ULL );unsigned secs = (unsigned long )t;int ret; +trace_assign_type (field, entry); + m = &field->map; +switch (m->opcode) {case MMIO_PROBE : ret = trace_seq_printf(s,
Re: [PATCH] ring_buffer: allocate buffer page pointer
Quoted 2 lines · Ingo Molnar
applied to tip/tracing/ftrace, with the extended changlog below - i think this commit warrants that extra mention.
that was for the type filter commit. The 3 patches i've picked up into tip/tracing/ring-buffer are:
b6eeea4: ftrace: preempt disable over interrupt disable 52abc82: ring_buffer: allocate buffer page pointer
da78331: ftrace: type cast filter+verifier
Thanks,
Ingo
PATCH 1/1 ring-buffer: fix build error
Quoted 6 lines · Ingo Molnar
Quoted 2 lines · Ingo Molnar
applied to tip/tracing/ftrace, with the extended changlog below - i think this commit warrants that extra mention.
Quoted 6 lines
that was for the type filter commit. The 3 patches i've picked up into tip/tracing/ring-buffer are:
b6eeea4: ftrace: preempt disable over interrupt disable 52abc82:
ring_buffer: allocate buffer page pointer
da78331: ftrace: type cast filter+verifier
trivial build fix below.
Ingo
Quoted 1 line
From
339ce9af3e6cbc02442b0b356c1ecb80a8ae92fbMon Sep 17 00:00:00 2001
From: Ingo Molnar <[email protected]>
Date: Thu, 2 Oct 2008 11:04:14 +0200
Subject: [PATCH] ring-buffer: fix build error
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
fix:
kernel/trace/ring_buffer.c: In function ‘rb_allocate_pages’:
kernel/trace/ring_buffer.c:235: error: ‘cpu’ undeclared (first use in this function) kernel/trace/ring_buffer.c:235: error: (Each undeclared identifier is reported only once kernel/trace/ring_buffer.c:235: error: for each function it appears in.)
--- kernel/trace/ring_buffer.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
kernel/trace/ring_buffer.c +1 -1
@@ -232,7 +232,7 @@ static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,for (i =0 ; i < nr_pages; i++) { page =kzalloc_node (ALIGN (sizeof (*page),cache_line_size ()), -GFP_KERNEL ,cpu_to_node (cpu)); +GFP_KERNEL ,cpu_to_node (i));if (!page) goto free_pages;list_add (&page->list, &pages);
[boot crash] Re: [PATCH] ring-buffer: fix build error
Quoted 8 lines · Ingo Molnar
Quoted 6 lines
that was for the type filter commit. The 3 patches i've picked up into tip/tracing/ring-buffer are:
b6eeea4: ftrace: preempt disable over interrupt disable 52abc82:
ring_buffer: allocate buffer page pointer
da78331: ftrace: type cast filter+verifiertrivial build fix below.
ok, these latest ring-buffer updates cause more serious trouble, i just got this boot crash on a testbox:
[ 0.324003] calling tracer_alloc_buffers+0x0/0x14a @ 1 [ 0.328008] BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 [ 0.332001] IP: [<ffffffff8027d28b>] ring_buffer_alloc+0x207/0x3fc [ 0.332001] PGD 0 [ 0.332001] Oops: 0000 [1] SMP [ 0.332001] CPU 0 [ 0.332001] Modules linked in: [ 0.332001] Pid: 1, comm: swapper Not tainted 2.6.27-rc8-tip-01064-gd163d6b-dirty #1 [ 0.332001] RIP: 0010:[<ffffffff8027d28b>] [<ffffffff8027d28b>] ring_buffer_alloc+0x207/0x3fc [ 0.332001] RSP: 0018:ffff88003f9d7de0 EFLAGS: 00010287 [ 0.332001] RAX: 0000000000000000 RBX: ffffffff80b08404 RCX: 0000000000000067 [ 0.332001] RDX: 0000000000000004 RSI: 00000000000080d0 RDI: ffffffffffffffc0 [ 0.332001] RBP: ffff88003f9d7e80 R08: ffff88003f8010b4 R09: 000000000003db02 [ 0.332001] R10: 0000000000000000 R11: 0000000000000001 R12: ffff88003f801600 [ 0.332001] R13: 0000000000000004 R14: ffff88003f801580 R15: ffff88003f801618 [ 0.332001] FS: 0000000000000000(0000) GS:ffffffff80a68280(0000) knlGS:0000000000000000 [ 0.332001] CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b [ 0.332001] CR2: 0000000000000008 CR3: 0000000000201000 CR4: 00000000000006e0 [ 0.332001] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 0.332001] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 0.332001] Process swapper (pid: 1, threadinfo ffff88003f9d6000, task ffff88003f9d8000) [ 0.332001] Stack: ffff88003f9d7df0 ffff88003f9d7e40 0000000000000283 ffffffff80b08404 [ 0.332001] ffffffff80b08404 ffff88003f801598 0000000000000000 ffff88003f801598 [ 0.332001] ffff88003f801580 0000016000000000 ffff88003f801600 ffff88003f9a2a40 [ 0.332001] Call Trace: [ 0.332001] [<ffffffff80a95f41>] ? tracer_alloc_buffers+0x0/0x14a [ 0.332001] [<ffffffff80a95f67>] tracer_alloc_buffers+0x26/0x14a [ 0.332001] [<ffffffff80a95f41>] ? tracer_alloc_buffers+0x0/0x14a [ 0.332001] [<ffffffff80209056>] do_one_initcall+0x56/0x144 [ 0.332001] [<ffffffff80a87d4a>] ? native_smp_prepare_cpus+0x2aa/0x2ef [ 0.332001] [<ffffffff80a7c8ce>] kernel_init+0x69/0x20e [ 0.332001] [<ffffffff8020d4e9>] child_rip+0xa/0x11 [ 0.332001] [<ffffffff80257896>] ? __atomic_notifier_call_chain+0xd/0xf [ 0.332001] [<ffffffff80a7c865>] ? kernel_init+0x0/0x20e [ 0.332001] [<ffffffff8020d4df>] ? child_rip+0x0/0x11 [ 0.332001] Code: 48 8b 05 d9 b2 7e 00 49 63 d5 48 63 0d 1b b2 7e 00 48 8b 9d 78 ff ff ff be d0 80 00 00 48 8b 04 d0 48 89 cf 48 83 c1 27 48 f7 df <48> 8b 40 08 48 21 cf 8b 14 03 e8 4e b5 02 00 48 85 c0 48 89 c3 [ 0.332001] RIP [<ffffffff8027d28b>] ring_buffer_alloc+0x207/0x3fc [ 0.332001] RSP <ffff88003f9d7de0> [ 0.332001] CR2: 0000000000000008 [ 0.332002] Kernel panic - not syncing: Fatal exception
full serial log and config attached. I'm excluding these latest commits from tip/master for now:
339ce9a: ring-buffer: fix build error
b6eeea4: ftrace: preempt disable over interrupt disable 52abc82: ring_buffer: allocate buffer page pointer
da78331: ftrace: type cast filter+verifier
i'm quite sure 52abc82 causes this problem.
Another 64-bit testbox crashed too meanwhile.
Ingo
Steven Rostedt
maintainerRe: [boot crash] Re: [PATCH] ring-buffer: fix build error
Quoted 4 lines · Ingo Molnar
[ 0.332002] Kernel panic - not syncing: Fatal exceptionfull serial log and config attached. I'm excluding these latest commits from tip/master for now:
Thanks I'll take a look at this.
Quoted 3 lines
339ce9a: ring-buffer: fix build error
b6eeea4: ftrace: preempt disable over interrupt disable
The above "preempt disable" is the most likely culprit. I'm trying to get towards an interrupt disabled free and lockless code path. But in doing so, one must be extra careful. This is why I'm taking baby steps towards this approach. Any little error in one of these steps, and you have race conditions biting you.
The above replaces interrupt disables with preempt disables, uses the atomic data disable to protect against reentrancy. But this could also have opened up a bug that was not present with the interrupts disabled version.
Quoted 5 lines
52abc82:
ring_buffer: allocate buffer page pointer
da78331: ftrace: type cast filter+verifieri'm quite sure 52abc82 causes this problem.
Hmm, that was a trivial patch. Perhaps the trivial ones are the ones that are most likely to be error prone. A developer will take much more care in developing a patch that is complex than something he sees as trivial ;-)
-- Steve
Quoted 5 lines
Another 64-bit testbox crashed too meanwhile.
Ingo
Steven Rostedt
maintainerRe: [boot crash] Re: [PATCH] ring-buffer: fix build error
In reply to Ingo MolnarQuoted 3 lines · Ingo Molnar
* Ingo Molnar <[email protected]> wrote:
full serial log and config attached. I'm excluding these latest commits
-ENOATTACHMENT
-- Steve
Re: [boot crash] Re: [PATCH] ring-buffer: fix build error
Quoted 7 lines · Steven Rostedt
Quoted 3 lines · Ingo Molnar
* Ingo Molnar <[email protected]> wrote:
full serial log and config attached. I'm excluding these latest commits
-ENOATTACHMENT
attached.
You can get the broken tree by doing this in tip/master:
git-merge tip/tracing/ring-buffer
Ingo
[ 0.000000] Linux version 2.6.27-rc8-tip-01064-gd163d6b-dirty (mingo@titan) (gcc version 4.2.3) #1 SMP Thu Oct 2 11:21:04 CEST 2008 [ 0.000000] Command line: root=/dev/sda1 earlyprintk=serial,ttyS0,115200 console=ttyS0,115200 console=tty 5 profile=0 debug initcall_debug apic=debug apic=verbose ignore_loglevel sysrq_always_enabled pci=nomsi [ 0.000000] KERNEL supported cpus: [ 0.000000] Intel GenuineIntel [ 0.000000] AMD AuthenticAMD [ 0.000000] Centaur CentaurHauls [ 0.000000] BIOS-provided physical RAM map: [ 0.000000] BIOS-e820: 0000000000000000 - 000000000009fc00 (usable) [ 0.000000] BIOS-e820: 000000000009fc00 - 00000000000a0000 (reserved) [ 0.000000] BIOS-e820: 00000000000e0000 - 0000000000100000 (reserved) [ 0.000000] BIOS-e820: 0000000000100000 - 000000003ed94000 (usable) [ 0.000000] BIOS-e820: 000000003ed94000 - 000000003ee4e000 (ACPI NVS) [ 0.000000] BIOS-e820: 000000003ee4e000 - 000000003fea2000 (usable) [ 0.000000] BIOS-e820: 000000003fea2000 - 000000003fee9000 (ACPI NVS) [ 0.000000] BIOS-e820: 000000003fee9000 - 000000003feed000 (usable) [ 0.000000] BIOS-e820: 000000003feed000 - 000000003feff000 (ACPI data) [ 0.000000] BIOS-e820: 000000003feff000 - 000000003ff00000 (usable) [ 0.000000] console [earlyser0] enabled [ 0.000000] debug: ignoring loglevel setting. [ 0.000000] DMI 2.3 present. [ 0.000000] last_pfn = 0x3ff00 max_arch_pfn = 0x3ffffffff [ 0.000000] x86 PAT enabled: cpu 0, old 0x7040600070406, new 0x7010600070106 [ 0.000000] Scanning 2 areas for low memory corruption [ 0.000000] modified physical RAM map: [ 0.000000] modified: 0000000000000000 - 0000000000001000 (usable) [ 0.000000] modified: 0000000000001000 - 0000000000006000 (reserved) [ 0.000000] modified: 0000000000006000 - 0000000000008000 (usable) [ 0.000000] modified: 0000000000008000 - 0000000000010000 (reserved) [ 0.000000] modified: 0000000000010000 - 0000000000092c00 (usable) [ 0.000000] modified: 000000000009fc00 - 00000000000a0000 (reserved) [ 0.000000] modified: 00000000000e0000 - 0000000000100000 (reserved) [ 0.000000] modified: 0000000000100000 - 000000003ed94000 (usable) [ 0.000000] modified: 000000003ed94000 - 000000003ee4e000 (ACPI NVS) [ 0.000000] modified: 000000003ee4e000 - 000000003fea2000 (usable) [ 0.000000] modified: 000000003fea2000 - 000000003fee9000 (ACPI NVS) [ 0.000000] modified: 000000003fee9000 - 000000003feed000 (usable) [ 0.000000] modified: 000000003feed000 - 000000003feff000 (ACPI data) [ 0.000000] modified: 000000003feff000 - 000000003ff00000 (usable) [ 0.000000] init_memory_mapping [ 0.000000] 0000000000 - 003fe00000 page 2M [ 0.000000] 003fe00000 - 003ff00000 page 4k [ 0.000000] kernel direct mapping tables up to 3ff00000 @ 10000-13000 [ 0.000000] last_map_addr: 3ff00000 end: 3ff00000 [ 0.000000] ACPI: RSDP 000FE020, 0014 (r0 INTEL ) [ 0.000000] ACPI: RSDT 3FEFDE48, 0050 (r1 INTEL D975XBX 4B9 MSFT 1000013) [ 0.000000] ACPI: FACP 3FEFCF10, 0074 (r1 INTEL D975XBX 4B9 MSFT 1000013) [ 0.000000] ACPI: DSDT 3FEF8010, 3E70 (r1 INTEL D975XBX 4B9 MSFT 1000013) [ 0.000000] ACPI: FACS 3FEDFC40, 0040 [ 0.000000] ACPI: APIC 3FEFCE10, 0078 (r1 INTEL D975XBX 4B9 MSFT 1000013) [ 0.000000] ACPI: WDDT 3FEF7F90, 0040 (r1 INTEL D975XBX 4B9 MSFT 1000013) [ 0.000000] ACPI: MCFG 3FEF7F10, 003C (r1 INTEL D975XBX 4B9 MSFT 1000013) [ 0.000000] ACPI: ASF! 3FEFCD10, 00A6 (r32 INTEL D975XBX 4B9 MSFT 1000013) [ 0.000000] ACPI: HPET 3FEF7E90, 0038 (r1 INTEL D975XBX 4B9 MSFT 1000013) [ 0.000000] ACPI: SSDT 3FEFDC10, 01BC (r1 INTEL CpuPm 4B9 MSFT 1000013) [ 0.000000] ACPI: SSDT 3FEFDA10, 01B7 (r1 INTEL Cpu0Ist 4B9 MSFT 1000013) [ 0.000000] ACPI: SSDT 3FEFD810, 01B7 (r1 INTEL Cpu1Ist 4B9 MSFT 1000013) [ 0.000000] ACPI: SSDT 3FEFD610, 01B7 (r1 INTEL Cpu2Ist 4B9 MSFT 1000013) [ 0.000000] ACPI: SSDT 3FEFD410, 01B7 (r1 INTEL Cpu3Ist 4B9 MSFT 1000013) [ 0.000000] ACPI: Local APIC address 0xfee00000 [ 0.000000] No NUMA configuration found [ 0.000000] Faking a node at 0000000000000000-000000003ff00000 [ 0.000000] Bootmem setup node 0 0000000000000000-000000003ff00000 [ 0.000000] NODE_DATA [0000000000013000 - 0000000000016fff] [ 0.000000] bootmap [0000000000017000 - 000000000001efdf] pages 8 [ 0.000000] (5 early reservations) ==> bootmem [0000000000 - 003ff00000] [ 0.000000] #0 [0000000000 - 0000001000] BIOS data page ==> [0000000000 - 0000001000] [ 0.000000] #1 [0000006000 - 0000008000] TRAMPOLINE ==> [0000006000 - 0000008000] [ 0.000000] #2 [0000200000 - 0000c68370] TEXT DATA BSS ==> [0000200000 - 0000c68370] [ 0.000000] #3 [000009fc00 - 0000100000] BIOS reserved ==> [000009fc00 - 0000100000] [ 0.000000] #4 [0000010000 - 0000013000] PGTABLE ==> [0000010000 - 0000013000] [ 0.000000] Scan SMP from ffff880000000000 for 1024 bytes. [ 0.000000] Scan SMP from ffff88000009fc00 for 1024 bytes. [ 0.000000] Scan SMP from ffff8800000f0000 for 65536 bytes. [ 0.000000] found SMP MP-table at [ffff8800000fe680] 000fe680 [ 0.000000] Zone PFN ranges: [ 0.000000] DMA 0x00000000 -> 0x00001000 [ 0.000000] DMA32 0x00001000 -> 0x00100000 [ 0.000000] Normal 0x00100000 -> 0x00100000 [ 0.000000] Movable zone start PFN for each node [ 0.000000] early_node_map[7] active PFN ranges [ 0.000000] 0: 0x00000000 -> 0x00000001 [ 0.000000] 0: 0x00000006 -> 0x00000008 [ 0.000000] 0: 0x00000010 -> 0x00000092 [ 0.000000] 0: 0x00000100 -> 0x0003ed94 [ 0.000000] 0: 0x0003ee4e -> 0x0003fea2 [ 0.000000] 0: 0x0003fee9 -> 0x0003feed [ 0.000000] 0: 0x0003feff -> 0x0003ff00 [ 0.000000] On node 0 totalpages: 261490 [ 0.000000] DMA zone: 1141 pages, LIFO batch:0 [ 0.000000] DMA32 zone: 253489 pages, LIFO batch:31 [ 0.000000] ACPI: PM-Timer IO Port: 0x408 [ 0.000000] ACPI: Local APIC address 0xfee00000 [ 0.000000] ACPI: LAPIC (acpi_id[0x01] lapic_id[0x00] enabled) [ 0.000000] ACPI: LAPIC (acpi_id[0x02] lapic_id[0x01] enabled) [ 0.000000] ACPI: LAPIC (acpi_id[0x03] lapic_id[0x82] disabled) [ 0.000000] ACPI: LAPIC (acpi_id[0x04] lapic_id[0x83] disabled) [ 0.000000] ACPI: LAPIC_NMI (acpi_id[0x01] dfl dfl lint[0x1]) [ 0.000000] ACPI: LAPIC_NMI (acpi_id[0x02] dfl dfl lint[0x1]) [ 0.000000] ACPI: IOAPIC (id[0x02] address[0xfec00000] gsi_base[0]) [ 0.000000] IOAPIC[0]: apic_id 2, version 0, address 0xfec00000, GSI 0-23 [ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl) [ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level) [ 0.000000] ACPI: IRQ0 used by override. [ 0.000000] ACPI: IRQ2 used by override. [ 0.000000] ACPI: IRQ9 used by override. [ 0.000000] ACPI: HPET id: 0x8086a201 base: 0xfed00000 [ 0.000000] Using ACPI (MADT) for SMP configuration information [ 0.000000] SMP: Allowing 4 CPUs, 2 hotplug CPUs [ 0.000000] mapped APIC to ffffffffff5fc000 (fee00000) [ 0.000000] mapped IOAPIC to ffffffffff5fb000 (fec00000) [ 0.000000] Allocating PCI resources starting at 40000000 (gap: 3ff00000:c0100000) [ 0.000000] dyn_array irq_2_pin_head+0x0/0x4a8 size:0x10 nr:256 align:0x1000 [ 0.000000] dyn_array irq_cfgx+0x0/0x8 size:0x28 nr:48 align:0x1000 [ 0.000000] dyn_array irq_desc+0x0/0x8 size:0x100 nr:48 align:0x1000 [ 0.000000] dyn_array irq_timer_state+0x0/0x10 size:0x8 nr:48 align:0x1000 [ 0.000000] dyn_array total_size: 0x6000 [ 0.000000] dyn_array irq_2_pin_head+0x0/0x4a8 ==> [0x100a000 - 0x100b000] [ 0.000000] dyn_array irq_cfgx+0x0/0x8 ==> [0x100b000 - 0x100b780] [ 0.000000] dyn_array irq_desc+0x0/0x8 ==> [0x100c000 - 0x100f000] [ 0.000000] kstat_irqs ==> [0x1010000 - 0x1010300] [ 0.000000] dyn_array irq_timer_state+0x0/0x10 ==> [0x100f000 - 0x100f180] [ 0.000000] PERCPU: Allocating 57344 bytes of per cpu data [ 0.000000] per cpu data for cpu0 on node0 at 0000000001011000 [ 0.000000] per cpu data for cpu1 on node0 at 000000000101f000 [ 0.000000] per cpu data for cpu2 on node0 at 000000000102d000 [ 0.000000] per cpu data for cpu3 on node0 at 000000000103b000 [ 0.000000] NR_CPUS: 8, nr_cpu_ids: 4, nr_node_ids 1 [ 0.000000] Built 1 zonelists in Node order, mobility grouping on. Total pages: 254630 [ 0.000000] Policy zone: DMA32 [ 0.000000] Kernel command line: root=/dev/sda1 earlyprintk=serial,ttyS0,115200 console=ttyS0,115200 console=tty 5 profile=0 debug initcall_debug apic=debug apic=verbose ignore_loglevel sysrq_always_enabled pci=nomsi [ 0.000000] debug: sysrq always enabled. [ 0.000000] Initializing CPU#0 [ 0.000000] PID hash table entries: 4096 (order: 12, 32768 bytes) [ 0.000000] Fast TSC calibration using PIT [ 0.000000] Detected 2933.237 MHz processor. [ 0.004000] Console: colour VGA+ 80x25 [ 0.004000] console handover: boot [earlyser0] -> real [tty0] [ 0.004000] console [ttyS0] enabled [ 0.004000] Scanning for low memory corruption every 60 seconds [ 0.004000] Checking aperture... [ 0.004000] No AGP bridge found [ 0.004000] Memory: 1018524k/1047552k available (5392k kernel code, 27436k reserved, 3199k data, 608k init) [ 0.004000] SLUB: Genslabs=13, HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1 [ 0.004000] hpet clockevent registered [ 0.004000] HPET: 3 timers in total, 0 timers will be used for per-cpu timer [ 0.004011] Calibrating delay loop (skipped), value calculated using timer frequency.. 5866.47 BogoMIPS (lpj=11732948) [ 0.012021] Security Framework initialized [ 0.016091] Dentry cache hash table entries: 131072 (order: 8, 1048576 bytes) [ 0.020676] Inode-cache hash table entries: 65536 (order: 7, 524288 bytes) [ 0.024312] Mount-cache hash table entries: 256 [ 0.028160] Initializing cgroup subsys debug [ 0.032004] Initializing cgroup subsys ns [ 0.036003] Initializing cgroup subsys memory [ 0.040021] CPU: L1 I cache: 32K, L1 D cache: 32K [ 0.045682] CPU: L2 cache: 4096K [ 0.048004] CPU 0/0x0 -> Node 0 [ 0.052003] CPU: Physical Processor ID: 0 [ 0.056002] CPU: Processor Core ID: 0 [ 0.060007] CPU0: Thermal monitoring enabled (TM2) [ 0.064003] using mwait in idle threads. [ 0.069799] ACPI: Core revision 20080609 [ 0.081336] Parsing all Control Methods: [ 0.084117] Table [DSDT](id 0001) - 529 Objects with 55 Devices 147 Methods 32 Regions [ 0.088143] Parsing all Control Methods: [ 0.092098] Table [SSDT](id 0002) - 10 Objects with 0 Devices 4 Methods 0 Regions [ 0.096087] Parsing all Control Methods: [ 0.100098] Table [SSDT](id 0003) - 5 Objects with 0 Devices 3 Methods 0 Regions [ 0.104087] Parsing all Control Methods: [ 0.108099] Table [SSDT](id 0004) - 5 Objects with 0 Devices 3 Methods 0 Regions [ 0.112086] Parsing all Control Methods: [ 0.116101] Table [SSDT](id 0005) - 5 Objects with 0 Devices 3 Methods 0 Regions [ 0.120087] Parsing all Control Methods: [ 0.124101] Table [SSDT](id 0006) - 5 Objects with 0 Devices 3 Methods 0 Regions [ 0.128003] tbxface-0607 [02] tb_load_namespace : ACPI Tables successfully acquired [ 0.137205] evxfevnt-0091 [02] enable : Transition to ACPI mode successful [ 0.144052] Setting APIC routing to flat [ 0.148005] enabled ExtINT on CPU#0 [ 0.152139] ENABLING IO-APIC IRQs [ 0.156003] init IO_APIC IRQs [ 0.158984] 2-0 (apicid-pin) not connected [ 0.162551] IOAPIC[0]: Set routing entry (2-1 -> 0x31 -> IRQ 1 Mode:0 Active:0) [ 0.164005] IOAPIC[0]: Set routing entry (2-2 -> 0x30 -> IRQ 0 Mode:0 Active:0) [ 0.168004] IOAPIC[0]: Set routing entry (2-3 -> 0x33 -> IRQ 3 Mode:0 Active:0) [ 0.172004] IOAPIC[0]: Set routing entry (2-4 -> 0x34 -> IRQ 4 Mode:0 Active:0) [ 0.176003] IOAPIC[0]: Set routing entry (2-5 -> 0x35 -> IRQ 5 Mode:0 Active:0) [ 0.180004] IOAPIC[0]: Set routing entry (2-6 -> 0x36 -> IRQ 6 Mode:0 Active:0) [ 0.184004] IOAPIC[0]: Set routing entry (2-7 -> 0x37 -> IRQ 7 Mode:0 Active:0) [ 0.188003] IOAPIC[0]: Set routing entry (2-8 -> 0x38 -> IRQ 8 Mode:0 Active:0) [ 0.192004] IOAPIC[0]: Set routing entry (2-9 -> 0x39 -> IRQ 9 Mode:1 Active:0) [ 0.196004] IOAPIC[0]: Set routing entry (2-10 -> 0x3a -> IRQ 10 Mode:0 Active:0) [ 0.200004] IOAPIC[0]: Set routing entry (2-11 -> 0x3b -> IRQ 11 Mode:0 Active:0) [ 0.204004] IOAPIC[0]: Set routing entry (2-12 -> 0x3c -> IRQ 12 Mode:0 Active:0) [ 0.208004] IOAPIC[0]: Set routing entry (2-13 -> 0x3d -> IRQ 13 Mode:0 Active:0) [ 0.212004] IOAPIC[0]: Set routing entry (2-14 -> 0x3e -> IRQ 14 Mode:0 Active:0) [ 0.216004] IOAPIC[0]: Set routing entry (2-15 -> 0x3f -> IRQ 15 Mode:0 Active:0) [ 0.220003] 2-16 2-17 2-18 2-19 2-20 2-21 2-22 2-23 (apicid-pin) not connected [ 0.228132] ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1 [ 0.272252] CPU0: Intel(R) Core(TM)2 CPU E6800 @ 2.93GHz stepping 05 [ 0.277251] Using local APIC timer interrupts. [ 0.277252] calibrating APIC timer ... [ 0.284001] ... lapic delta = 1666638 [ 0.284001] ... PM timer delta = 357949 [ 0.284001] ... PM timer result ok [ 0.284001] ..... delta 1666638 [ 0.284001] ..... mult: 71577083 [ 0.284001] ..... calibration result: 1066648 [ 0.284001] ..... CPU clock speed is 2933.1156 MHz. [ 0.284001] ..... host bus clock speed is 266.2648 MHz. [ 0.284012] calling migration_init+0x0/0x5b @ 1 [ 0.288026] initcall migration_init+0x0/0x5b returned 1 after 0 msecs [ 0.292003] initcall migration_init+0x0/0x5b returned with error code 1 [ 0.300003] calling spawn_ksoftirqd+0x0/0x58 @ 1 [ 0.304017] initcall spawn_ksoftirqd+0x0/0x58 returned 0 after 0 msecs [ 0.308005] calling init_call_single_data+0x0/0x52 @ 1 [ 0.312003] initcall init_call_single_data+0x0/0x52 returned 0 after 0 msecs [ 0.316003] calling relay_init+0x0/0x14 @ 1 [ 0.320003] initcall relay_init+0x0/0x14 returned 0 after 0 msecs [ 0.324003] calling tracer_alloc_buffers+0x0/0x14a @ 1 [ 0.328008] BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 [ 0.332001] IP: [<ffffffff8027d28b>] ring_buffer_alloc+0x207/0x3fc [ 0.332001] PGD 0 [ 0.332001] Oops: 0000 [1] SMP [ 0.332001] CPU 0 [ 0.332001] Modules linked in: [ 0.332001] Pid: 1, comm: swapper Not tainted 2.6.27-rc8-tip-01064-gd163d6b-dirty #1 [ 0.332001] RIP: 0010:[<ffffffff8027d28b>] [<ffffffff8027d28b>] ring_buffer_alloc+0x207/0x3fc [ 0.332001] RSP: 0018:ffff88003f9d7de0 EFLAGS: 00010287 [ 0.332001] RAX: 0000000000000000 RBX: ffffffff80b08404 RCX: 0000000000000067 [ 0.332001] RDX: 0000000000000004 RSI: 00000000000080d0 RDI: ffffffffffffffc0 [ 0.332001] RBP: ffff88003f9d7e80 R08: ffff88003f8010b4 R09: 000000000003db02 [ 0.332001] R10: 0000000000000000 R11: 0000000000000001 R12: ffff88003f801600 [ 0.332001] R13: 0000000000000004 R14: ffff88003f801580 R15: ffff88003f801618 [ 0.332001] FS: 0000000000000000(0000) GS:ffffffff80a68280(0000) knlGS:0000000000000000 [ 0.332001] CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b [ 0.332001] CR2: 0000000000000008 CR3: 0000000000201000 CR4: 00000000000006e0 [ 0.332001] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 0.332001] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 0.332001] Process swapper (pid: 1, threadinfo ffff88003f9d6000, task ffff88003f9d8000) [ 0.332001] Stack: ffff88003f9d7df0 ffff88003f9d7e40 0000000000000283 ffffffff80b08404 [ 0.332001] ffffffff80b08404 ffff88003f801598 0000000000000000 ffff88003f801598 [ 0.332001] ffff88003f801580 0000016000000000 ffff88003f801600 ffff88003f9a2a40 [ 0.332001] Call Trace: [ 0.332001] [<ffffffff80a95f41>] ? tracer_alloc_buffers+0x0/0x14a [ 0.332001] [<ffffffff80a95f67>] tracer_alloc_buffers+0x26/0x14a [ 0.332001] [<ffffffff80a95f41>] ? tracer_alloc_buffers+0x0/0x14a [ 0.332001] [<ffffffff80209056>] do_one_initcall+0x56/0x144 [ 0.332001] [<ffffffff80a87d4a>] ? native_smp_prepare_cpus+0x2aa/0x2ef [ 0.332001] [<ffffffff80a7c8ce>] kernel_init+0x69/0x20e [ 0.332001] [<ffffffff8020d4e9>] child_rip+0xa/0x11 [ 0.332001] [<ffffffff80257896>] ? __atomic_notifier_call_chain+0xd/0xf [ 0.332001] [<ffffffff80a7c865>] ? kernel_init+0x0/0x20e [ 0.332001] [<ffffffff8020d4df>] ? child_rip+0x0/0x11 [ 0.332001] Code: 48 8b 05 d9 b2 7e 00 49 63 d5 48 63 0d 1b b2 7e 00 48 8b 9d 78 ff ff ff be d0 80 00 00 48 8b 04 d0 48 89 cf 48 83 c1 27 48 f7 df <48> 8b 40 08 48 21 cf 8b 14 03 e8 4e b5 02 00 48 85 c0 48 89 c3 [ 0.332001] RIP [<ffffffff8027d28b>] ring_buffer_alloc+0x207/0x3fc [ 0.332001] RSP <ffff88003f9d7de0> [ 0.332001] CR2: 0000000000000008 [ 0.332002] Kernel panic - not syncing: Fatal exception # d3ff3924 # # Automatically generated make config: don't edit # Linux kernel version: 2.6.27-rc8 # Thu Oct 2 11:00:18 2008 # CONFIG_64BIT=y # CONFIG_X86_32 is not set CONFIG_X86_64=y CONFIG_X86=y CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig" # CONFIG_GENERIC_LOCKBREAK is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_CLOCKSOURCE_WATCHDOG=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y CONFIG_LOCKDEP_SUPPORT=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_HAVE_LATENCYTOP_SUPPORT=y CONFIG_FAST_CMPXCHG_LOCAL=y CONFIG_MMU=y CONFIG_ZONE_DMA=y CONFIG_GENERIC_ISA_DMA=y CONFIG_GENERIC_IOMAP=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_GPIO=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_ARCH_HAS_CPU_RELAX=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y CONFIG_HAVE_CPUMASK_OF_CPU_MAP=y CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ZONE_DMA32=y CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_AUDIT_ARCH=y CONFIG_ARCH_SUPPORTS_AOUT=y CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_PENDING_IRQ=y CONFIG_X86_SMP=y CONFIG_X86_64_SMP=y CONFIG_X86_HT=y CONFIG_X86_BIOS_REBOOT=y CONFIG_X86_TRAMPOLINE=y # CONFIG_KTIME_SCALAR is not set CONFIG_BOOTPARAM_SUPPORT_NOT_WANTED=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
# General setup
#CONFIG_EXPERIMENTAL=yCONFIG_BROKEN_BOOT_ALLOWED4=yCONFIG_BROKEN_BOOT_ALLOWED3=y
# CONFIG_BROKEN_BOOT_ALLOWED2 is not set
# CONFIG_BROKEN_BOOT_EUROPE is not set
# CONFIG_BROKEN_BOOT_TITAN is not setCONFIG_LOCK_KERNEL=yCONFIG_INIT_ENV_ARG_LIMIT=32CONFIG_LOCALVERSION=""CONFIG_LOCALVERSION_AUTO=yCONFIG_SWAP=y
# CONFIG_SYSVIPC is not set
# CONFIG_POSIX_MQUEUE is not setCONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not setCONFIG_TASKSTATS=y
# CONFIG_TASK_DELAY_ACCT is not set
# CONFIG_TASK_XACCT is not setCONFIG_AUDIT=yCONFIG_AUDITSYSCALL=yCONFIG_AUDIT_TREE=yCONFIG_IKCONFIG=y
# CONFIG_IKCONFIG_PROC is not setCONFIG_LOG_BUF_SHIFT=21CONFIG_CGROUPS=yCONFIG_CGROUP_DEBUG=yCONFIG_CGROUP_NS=yCONFIG_CGROUP_DEVICE=yCONFIG_CPUSETS=yCONFIG_HAVE_UNSTABLE_SCHED_CLOCK=yCONFIG_GROUP_SCHED=yCONFIG_FAIR_GROUP_SCHED=yCONFIG_RT_GROUP_SCHED=yCONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not setCONFIG_CGROUP_CPUACCT=yCONFIG_RESOURCE_COUNTERS=yCONFIG_MM_OWNER=yCONFIG_CGROUP_MEM_RES_CTLR=yCONFIG_SYSFS_DEPRECATED=y
# CONFIG_SYSFS_DEPRECATED_V2 is not setCONFIG_PROC_PID_CPUSET=yCONFIG_RELAY=yCONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
# CONFIG_USER_NS is not setCONFIG_PID_NS=y
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not setCONFIG_FASTBOOT=yCONFIG_SYSCTL=yCONFIG_EMBEDDED=yCONFIG_UID16=yCONFIG_SYSCTL_SYSCALL=yCONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not setCONFIG_HOTPLUG=yCONFIG_PRINTK=y
# CONFIG_BUG is not setCONFIG_ELF_CORE=y
# CONFIG_PCSPKR_PLATFORM is not setCONFIG_COMPAT_BRK=yCONFIG_BASE_FULL=yCONFIG_FUTEX=yCONFIG_ANON_INODES=yCONFIG_EPOLL=yCONFIG_SIGNALFD=yCONFIG_TIMERFD=yCONFIG_EVENTFD=yCONFIG_SHMEM=y
# CONFIG_VM_EVENT_COUNTERS is not setCONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not setCONFIG_SLUB=y
# CONFIG_SLOB is not setCONFIG_PROFILING=yCONFIG_TRACEPOINTS=y
# CONFIG_MARKERS is not setCONFIG_OPROFILE=y
# CONFIG_OPROFILE_IBS is not setCONFIG_HAVE_OPROFILE=yCONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=yCONFIG_HAVE_IOREMAP_PROT=yCONFIG_HAVE_KPROBES=yCONFIG_HAVE_KRETPROBES=yCONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_DMA_ATTRS is not setCONFIG_USE_GENERIC_SMP_HELPERS=y
# CONFIG_HAVE_CLK is not setCONFIG_HAVE_DYN_ARRAY=y
# CONFIG_PROC_PAGE_MONITOR is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not setCONFIG_SLABINFO=yCONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not setCONFIG_BASE_SMALL=0
# CONFIG_MODULES is not setCONFIG_STOP_MACHINE=yCONFIG_BLOCK=yCONFIG_BLK_DEV_IO_TRACE=yCONFIG_BLK_DEV_BSG=yCONFIG_BLK_DEV_INTEGRITY=yCONFIG_BLOCK_COMPAT=y
#
# IO Schedulers
#CONFIG_IOSCHED_NOOP=yCONFIG_IOSCHED_AS=yCONFIG_IOSCHED_DEADLINE=yCONFIG_IOSCHED_CFQ=y
# CONFIG_DEFAULT_AS is not set
# CONFIG_DEFAULT_DEADLINE is not setCONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not setCONFIG_DEFAULT_IOSCHED="cfq"CONFIG_PREEMPT_NOTIFIERS=yCONFIG_CLASSIC_RCU=y
#
# Processor type and features
#CONFIG_TICK_ONESHOT=y
# CONFIG_NO_HZ is not set CONFIG_HIGH_RES_TIMERS=y CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_SMP_SUPPORT=y CONFIG_HAVE_SPARSE_IRQ=y
# CONFIG_X86_MPPARSE is not set
# CONFIG_UP_WANTED_1 is not setCONFIG_SMP=yCONFIG_X86_PC=y
# CONFIG_X86_ELAN is not set
# CONFIG_X86_VOYAGER is not set
# CONFIG_X86_GENERICARCH is not set
# CONFIG_X86_VSMP is not set
# CONFIG_PARAVIRT_GUEST is not set
# CONFIG_MEMTEST is not set
# CONFIG_M386 is not set
# CONFIG_M486 is not set
# CONFIG_M586 is not set
# CONFIG_M586TSC is not set
# CONFIG_M586MMX is not set
# CONFIG_M686 is not set
# CONFIG_MPENTIUMII is not set
# CONFIG_MPENTIUMIII is not set
# CONFIG_MPENTIUMM is not set
# CONFIG_MPENTIUM4 is not set
# CONFIG_MK6 is not set
# CONFIG_MK7 is not set
# CONFIG_MK8 is not set
# CONFIG_MCRUSOE is not set
# CONFIG_MEFFICEON is not set
# CONFIG_MWINCHIPC6 is not set
# CONFIG_MWINCHIP3D is not set
# CONFIG_MGEODEGX1 is not set
# CONFIG_MGEODE_LX is not set
# CONFIG_MCYRIXIII is not set
# CONFIG_MVIAC3_2 is not set
# CONFIG_MVIAC7 is not set
# CONFIG_MPSC is not set
# CONFIG_MCORE2 is not set CONFIG_GENERIC_CPU=yCONFIG_X86_CPU=y CONFIG_X86_L1_CACHE_BYTES=128 CONFIG_X86_INTERNODE_CACHE_BYTES=128 CONFIG_X86_CMPXCHG=y CONFIG_X86_L1_CACHE_SHIFT=7 CONFIG_X86_WP_WORKS_OK=yCONFIG_X86_TSC=yCONFIG_X86_CMPXCHG64=yCONFIG_X86_CMOV=y CONFIG_X86_MINIMUM_CPU_FAMILY=64 CONFIG_X86_DEBUGCTLMSR=y CONFIG_PROCESSOR_SELECT=y
# CONFIG_CPU_SUP_INTEL is not set CONFIG_CPU_SUP_AMD=y CONFIG_CPU_SUP_CENTAUR_64=yCONFIG_X86_DS=y
# CONFIG_X86_PTRACE_BTS is not set CONFIG_HPET_TIMER=y CONFIG_HPET_EMULATE_RTC=yCONFIG_DMI=yCONFIG_GART_IOMMU=yCONFIG_CALGARY_IOMMU=y CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y CONFIG_AMD_IOMMU=yCONFIG_SWIOTLB=yCONFIG_IOMMU_HELPER=yCONFIG_NR_CPUS=8
# CONFIG_SCHED_SMT is not set
# CONFIG_SCHED_MC is not set CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set CONFIG_X86_LOCAL_APIC=yCONFIG_X86_IO_APIC=y
# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set CONFIG_X86_MCE=yCONFIG_X86_MCE_INTEL=y
# CONFIG_X86_MCE_AMD is not setCONFIG_I8K=yCONFIG_MICROCODE=yCONFIG_MICROCODE_INTEL=y CONFIG_MICROCODE_AMD=y CONFIG_MICROCODE_OLD_INTERFACE=y CONFIG_X86_MSR=yCONFIG_X86_CPUID=y CONFIG_ARCH_PHYS_ADDR_T_64BIT=y CONFIG_NUMA=yCONFIG_K8_NUMA=yCONFIG_X86_64_ACPI_NUMA=y CONFIG_NODES_SPAN_OTHER_NODES=y CONFIG_NUMA_EMU=yCONFIG_NODES_SHIFT=6 CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 CONFIG_SELECT_MEMORY_MODEL=y
# CONFIG_FLATMEM_MANUAL is not set
# CONFIG_DISCONTIGMEM_MANUAL is not set CONFIG_SPARSEMEM_MANUAL=yCONFIG_SPARSEMEM=y CONFIG_NEED_MULTIPLE_NODES=y CONFIG_HAVE_MEMORY_PRESENT=y
# CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPARSEMEM_EXTREME=y CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y CONFIG_SPARSEMEM_VMEMMAP=y
#
# Memory hotplug is currently incompatible with Software Suspend #CONFIG_PAGEFLAGS_EXTENDED=yCONFIG_SPLIT_PTLOCK_CPUS=4CONFIG_MIGRATION=yCONFIG_RESOURCES_64BIT=yCONFIG_PHYS_ADDR_T_64BIT=yCONFIG_ZONE_DMA_FLAG=1CONFIG_BOUNCE=yCONFIG_VIRT_TO_BUS=yCONFIG_MMU_NOTIFIER=y CONFIG_X86_CHECK_BIOS_CORRUPTION=y CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y CONFIG_X86_RESERVE_LOW_64K=y
# CONFIG_MTRR is not setCONFIG_EFI=y
# CONFIG_SECCOMP is not set CONFIG_CC_STACKPROTECTOR_ALL=y CONFIG_CC_STACKPROTECTOR=y
# CONFIG_HZ_100 is not setCONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not setCONFIG_HZ=250CONFIG_SCHED_HRTICK=yCONFIG_KEXEC=y
# CONFIG_CRASH_DUMP is not set CONFIG_PHYSICAL_START=0x200000CONFIG_RELOCATABLE=yCONFIG_PHYSICAL_ALIGN=0x200000CONFIG_HOTPLUG_CPU=yCONFIG_COMPAT_VDSO=y
# CONFIG_CMDLINE_BOOL is not set CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
#
# Power management options
#CONFIG_ARCH_HIBERNATION_HEADER=yCONFIG_PM=yCONFIG_PM_DEBUG=y
# CONFIG_PM_VERBOSE is not setCONFIG_CAN_PM_TRACE=y
# CONFIG_PM_TRACE_RTC is not setCONFIG_PM_SLEEP_SMP=yCONFIG_PM_SLEEP=y
# CONFIG_SUSPEND is not setCONFIG_HIBERNATION=yCONFIG_PM_STD_PARTITION=""CONFIG_ACPI=yCONFIG_ACPI_SLEEP=yCONFIG_ACPI_PROCFS=yCONFIG_ACPI_PROCFS_POWER=y
# CONFIG_ACPI_SYSFS_POWER is not set
# CONFIG_ACPI_PROC_EVENT is not setCONFIG_ACPI_AC=y
# CONFIG_ACPI_BATTERY is not set
# CONFIG_ACPI_BUTTON is not setCONFIG_ACPI_VIDEO=yCONFIG_ACPI_FAN=yCONFIG_ACPI_DOCK=yCONFIG_ACPI_BAY=yCONFIG_ACPI_PROCESSOR=yCONFIG_ACPI_HOTPLUG_CPU=yCONFIG_ACPI_THERMAL=yCONFIG_ACPI_NUMA=yCONFIG_ACPI_WMI=yCONFIG_ACPI_ASUS=yCONFIG_ACPI_TOSHIBA=y
# CONFIG_ACPI_CUSTOM_DSDT is not setCONFIG_ACPI_BLACKLIST_YEAR=0
# CONFIG_ACPI_DEBUG is not setCONFIG_ACPI_EC=yCONFIG_ACPI_PCI_SLOT=yCONFIG_ACPI_POWER=yCONFIG_ACPI_SYSTEM=yCONFIG_X86_PM_TIMER=yCONFIG_ACPI_CONTAINER=yCONFIG_ACPI_SBS=y
#
# CPU Frequency scaling
#CONFIG_CPU_FREQ=yCONFIG_CPU_FREQ_TABLE=y CONFIG_CPU_FREQ_DEBUG=y
# CONFIG_CPU_FREQ_STAT is not set CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set CONFIG_CPU_FREQ_GOV_PERFORMANCE=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
#
# CPUFreq processor drivers
#CONFIG_X86_ACPI_CPUFREQ=yCONFIG_X86_POWERNOW_K8=yCONFIG_X86_POWERNOW_K8_ACPI=y
# CONFIG_X86_SPEEDSTEP_CENTRINO is not setCONFIG_X86_P4_CLOCKMOD=y
#
# shared options # CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y CONFIG_X86_SPEEDSTEP_LIB=y CONFIG_CPU_IDLE=y CONFIG_CPU_IDLE_GOV_LADDER=y
#
# Bus options (PCI etc.)
#CONFIG_PCI=yCONFIG_PCI_DIRECT=y
# CONFIG_PCI_MMCONFIG is not setCONFIG_PCI_DOMAINS=yCONFIG_DMAR=y
# CONFIG_DMAR_GFX_WA is not setCONFIG_DMAR_FLOPPY_WA=yCONFIG_INTR_REMAP=y
# CONFIG_PCIEPORTBUS is not setCONFIG_ARCH_SUPPORTS_MSI=yCONFIG_PCI_MSI=yCONFIG_PCI_LEGACY=yCONFIG_HT_IRQ=yCONFIG_ISA_DMA_API=yCONFIG_K8_NB=y
# CONFIG_PCCARD is not setCONFIG_HOTPLUG_PCI=yCONFIG_HOTPLUG_PCI_FAKE=yCONFIG_HOTPLUG_PCI_ACPI=yCONFIG_HOTPLUG_PCI_ACPI_IBM=yCONFIG_HOTPLUG_PCI_CPCI=yCONFIG_HOTPLUG_PCI_CPCI_ZT5550=yCONFIG_HOTPLUG_PCI_CPCI_GENERIC=y
# CONFIG_HOTPLUG_PCI_SHPC is not set
#
# Executable file formats / Emulations
#CONFIG_BINFMT_ELF=yCONFIG_COMPAT_BINFMT_ELF=yCONFIG_BINFMT_MISC=yCONFIG_IA32_EMULATION=yCONFIG_IA32_AOUT=yCONFIG_COMPAT=yCONFIG_COMPAT_FOR_U64_ALIGNMENT=yCONFIG_NET=y
#
# Networking options
#CONFIG_PACKET=yCONFIG_PACKET_MMAP=yCONFIG_UNIX=yCONFIG_XFRM=y
# CONFIG_XFRM_USER is not setCONFIG_XFRM_SUB_POLICY=yCONFIG_XFRM_MIGRATE=yCONFIG_XFRM_STATISTICS=yCONFIG_XFRM_IPCOMP=yCONFIG_NET_KEY=yCONFIG_NET_KEY_MIGRATE=yCONFIG_INET=yCONFIG_IP_MULTICAST=yCONFIG_IP_ADVANCED_ROUTER=yCONFIG_ASK_IP_FIB_HASH=y
# CONFIG_IP_FIB_TRIE is not setCONFIG_IP_FIB_HASH=y
# CONFIG_IP_MULTIPLE_TABLES is not setCONFIG_IP_ROUTE_MULTIPATH=y
# CONFIG_IP_ROUTE_VERBOSE is not set
# CONFIG_IP_PNP is not setCONFIG_NET_IPIP=yCONFIG_NET_IPGRE=y
# CONFIG_NET_IPGRE_BROADCAST is not setCONFIG_IP_MROUTE=yCONFIG_IP_PIMSM_V1=y
# CONFIG_IP_PIMSM_V2 is not setCONFIG_ARPD=y
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not setCONFIG_INET_ESP=yCONFIG_INET_IPCOMP=yCONFIG_INET_XFRM_TUNNEL=yCONFIG_INET_TUNNEL=y
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not setCONFIG_INET_XFRM_MODE_BEET=yCONFIG_INET_LRO=yCONFIG_INET_DIAG=yCONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not setCONFIG_TCP_CONG_CUBIC=yCONFIG_DEFAULT_TCP_CONG="cubic"CONFIG_TCP_MD5SIG=y
# CONFIG_IPV6 is not setCONFIG_NETLABEL=yCONFIG_NETWORK_SECMARK=y
# CONFIG_NETFILTER is not set
# CONFIG_IP_DCCP is not setCONFIG_IP_SCTP=y
# CONFIG_SCTP_DBG_MSG is not setCONFIG_SCTP_DBG_OBJCNT=y
# CONFIG_SCTP_HMAC_NONE is not set
# CONFIG_SCTP_HMAC_SHA1 is not setCONFIG_SCTP_HMAC_MD5=yCONFIG_TIPC=y
# CONFIG_TIPC_ADVANCED is not set
# CONFIG_TIPC_DEBUG is not setCONFIG_ATM=yCONFIG_ATM_CLIP=yCONFIG_ATM_CLIP_NO_ICMP=yCONFIG_ATM_LANE=yCONFIG_ATM_MPOA=yCONFIG_ATM_BR2684=y
# CONFIG_ATM_BR2684_IPFILTER is not setCONFIG_STP=yCONFIG_BRIDGE=yCONFIG_VLAN_8021Q=y
# CONFIG_VLAN_8021Q_GVRP is not setCONFIG_DECNET=yCONFIG_DECNET_ROUTER=yCONFIG_LLC=yCONFIG_LLC2=yCONFIG_IPX=yCONFIG_IPX_INTERN=yCONFIG_ATALK=yCONFIG_DEV_APPLETALK=y
# CONFIG_IPDDP is not setCONFIG_X25=yCONFIG_LAPB=yCONFIG_ECONET=yCONFIG_ECONET_AUNUDP=yCONFIG_ECONET_NATIVE=y
# CONFIG_WAN_ROUTER is not setCONFIG_NET_SCHED=y
#
# Queueing/Scheduling
#
# CONFIG_NET_SCH_CBQ is not set
# CONFIG_NET_SCH_HTB is not setCONFIG_NET_SCH_HFSC=y
# CONFIG_NET_SCH_ATM is not setCONFIG_NET_SCH_PRIO=y
# CONFIG_NET_SCH_RED is not setCONFIG_NET_SCH_SFQ=yCONFIG_NET_SCH_TEQL=yCONFIG_NET_SCH_TBF=yCONFIG_NET_SCH_GRED=y
# CONFIG_NET_SCH_DSMARK is not setCONFIG_NET_SCH_NETEM=y
# CONFIG_NET_SCH_INGRESS is not set
#
# Classification
#CONFIG_NET_CLS=y
# CONFIG_NET_CLS_BASIC is not setCONFIG_NET_CLS_TCINDEX=yCONFIG_NET_CLS_ROUTE4=yCONFIG_NET_CLS_ROUTE=yCONFIG_NET_CLS_FW=yCONFIG_NET_CLS_U32=y
# CONFIG_CLS_U32_PERF is not setCONFIG_CLS_U32_MARK=y
# CONFIG_NET_CLS_RSVP is not setCONFIG_NET_CLS_RSVP6=yCONFIG_NET_CLS_FLOW=yCONFIG_NET_EMATCH=yCONFIG_NET_EMATCH_STACK=32
# CONFIG_NET_EMATCH_CMP is not setCONFIG_NET_EMATCH_NBYTE=yCONFIG_NET_EMATCH_U32=yCONFIG_NET_EMATCH_META=y
# CONFIG_NET_EMATCH_TEXT is not setCONFIG_NET_CLS_ACT=y
# CONFIG_NET_ACT_POLICE is not setCONFIG_NET_ACT_GACT=yCONFIG_GACT_PROB=yCONFIG_NET_ACT_MIRRED=yCONFIG_NET_ACT_NAT=yCONFIG_NET_ACT_PEDIT=yCONFIG_NET_ACT_SIMP=y
# CONFIG_NET_CLS_IND is not setCONFIG_NET_SCH_FIFO=y
#
# Network testing
#
# CONFIG_NET_PKTGEN is not setCONFIG_HAMRADIO=y
#
# Packet Radio protocols
#CONFIG_AX25=yCONFIG_AX25_DAMA_SLAVE=y
# CONFIG_NETROM is not setCONFIG_ROSE=y
#
# AX.25 network device drivers
#
# CONFIG_MKISS is not set
# CONFIG_6PACK is not setCONFIG_BPQETHER=yCONFIG_BAYCOM_SER_FDX=yCONFIG_BAYCOM_SER_HDX=y
# CONFIG_YAM is not setCONFIG_CAN=yCONFIG_CAN_RAW=y
# CONFIG_CAN_BCM is not set
#
# CAN Device Drivers
#
# CONFIG_CAN_VCAN is not setCONFIG_CAN_DEBUG_DEVICES=yCONFIG_IRDA=y
#
# IrDA protocols
#CONFIG_IRLAN=yCONFIG_IRNET=yCONFIG_IRCOMM=yCONFIG_IRDA_ULTRA=y
#
# IrDA options
#
# CONFIG_IRDA_CACHE_LAST_LSAP is not setCONFIG_IRDA_FAST_RR=yCONFIG_IRDA_DEBUG=y
#
# Infrared-port device drivers
#
#
# SIR device drivers
#CONFIG_IRTTY_SIR=y
#
# Dongle support
#CONFIG_DONGLE=yCONFIG_ESI_DONGLE=yCONFIG_ACTISYS_DONGLE=yCONFIG_TEKRAM_DONGLE=yCONFIG_TOIM3232_DONGLE=yCONFIG_LITELINK_DONGLE=yCONFIG_MA600_DONGLE=yCONFIG_GIRBIL_DONGLE=yCONFIG_MCP2120_DONGLE=yCONFIG_OLD_BELKIN_DONGLE=yCONFIG_ACT200L_DONGLE=yCONFIG_KINGSUN_DONGLE=yCONFIG_KSDAZZLE_DONGLE=yCONFIG_KS959_DONGLE=y
#
# FIR device drivers
#CONFIG_USB_IRDA=y
# CONFIG_SIGMATEL_FIR is not setCONFIG_NSC_FIR=yCONFIG_WINBOND_FIR=y
# CONFIG_SMC_IRCC_FIR is not set
# CONFIG_ALI_FIR is not setCONFIG_VLSI_FIR=y
# CONFIG_VIA_FIR is not set
# CONFIG_MCS_FIR is not setCONFIG_BT=y
# CONFIG_BT_L2CAP is not setCONFIG_BT_SCO=y
#
# Bluetooth device drivers
#CONFIG_BT_HCIUSB=yCONFIG_BT_HCIUSB_SCO=y
# CONFIG_BT_HCIBTUSB is not set
# CONFIG_BT_HCIUART is not set
# CONFIG_BT_HCIBCM203X is not setCONFIG_BT_HCIBPA10X=y
# CONFIG_BT_HCIBFUSB is not setCONFIG_BT_HCIVHCI=yCONFIG_AF_RXRPC=y
# CONFIG_AF_RXRPC_DEBUG is not setCONFIG_RXKAD=yCONFIG_FIB_RULES=y
#
# Wireless
#CONFIG_CFG80211=yCONFIG_NL80211=yCONFIG_WIRELESS_EXT=yCONFIG_WIRELESS_EXT_SYSFS=yCONFIG_MAC80211=y
#
# Rate control algorithm selection
#CONFIG_MAC80211_RC_PID=y CONFIG_MAC80211_RC_DEFAULT_PID=y CONFIG_MAC80211_RC_DEFAULT="pid"
# CONFIG_MAC80211_MESH is not set
# CONFIG_MAC80211_LEDS is not set CONFIG_MAC80211_DEBUGFS=y CONFIG_MAC80211_DEBUG_MENU=y
# CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT is not set # CONFIG_MAC80211_NOINLINE is not set CONFIG_MAC80211_VERBOSE_DEBUG=y CONFIG_MAC80211_HT_DEBUG=y CONFIG_MAC80211_TKIP_DEBUG=y CONFIG_MAC80211_IBSS_DEBUG=y CONFIG_MAC80211_VERBOSE_PS_DEBUG=y CONFIG_MAC80211_LOWTX_FRAME_DUMP=y CONFIG_MAC80211_DEBUG_COUNTERS=y CONFIG_MAC80211_VERBOSE_SPECT_MGMT_DEBUG=y CONFIG_IEEE80211=yCONFIG_IEEE80211_DEBUG=y
# CONFIG_IEEE80211_CRYPT_WEP is not set CONFIG_IEEE80211_CRYPT_CCMP=y CONFIG_IEEE80211_CRYPT_TKIP=y CONFIG_RFKILL=yCONFIG_RFKILL_INPUT=yCONFIG_RFKILL_LEDS=yCONFIG_NET_9P=yCONFIG_NET_9P_VIRTIO=y
# CONFIG_NET_9P_DEBUG is not set
#
# Device Drivers
#
#
# Generic Driver Options
#CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"CONFIG_STANDALONE=yCONFIG_PREVENT_FIRMWARE_BUILD=yCONFIG_FW_LOADER=yCONFIG_FIRMWARE_IN_KERNEL=yCONFIG_EXTRA_FIRMWARE=""
# CONFIG_SYS_HYPERVISOR is not setCONFIG_CONNECTOR=yCONFIG_PROC_EVENTS=y
# CONFIG_PARPORT is not setCONFIG_PNP=y
# CONFIG_PNP_DEBUG is not set
#
# Protocols
#CONFIG_PNPACPI=yCONFIG_BLK_DEV=yCONFIG_BLK_DEV_FD=yCONFIG_BLK_CPQ_DA=yCONFIG_BLK_CPQ_CISS_DA=y
# CONFIG_CISS_SCSI_TAPE is not setCONFIG_BLK_DEV_DAC960=yCONFIG_BLK_DEV_UMEM=y
# CONFIG_BLK_DEV_COW_COMMON is not setCONFIG_BLK_DEV_LOOP=yCONFIG_BLK_DEV_CRYPTOLOOP=yCONFIG_BLK_DEV_NBD=yCONFIG_BLK_DEV_SX8=yCONFIG_BLK_DEV_UB=yCONFIG_BLK_DEV_RAM=yCONFIG_BLK_DEV_RAM_COUNT=16CONFIG_BLK_DEV_RAM_SIZE=4096CONFIG_BLK_DEV_XIP=y
# CONFIG_CDROM_PKTCDVD is not setCONFIG_ATA_OVER_ETH=yCONFIG_VIRTIO_BLK=yCONFIG_BLK_DEV_HD=yCONFIG_MISC_DEVICES=yCONFIG_IBM_ASM=yCONFIG_PHANTOM=yCONFIG_EEPROM_93CX6=yCONFIG_SGI_IOC4=yCONFIG_TIFM_CORE=yCONFIG_TIFM_7XX1=y
# CONFIG_ACER_WMI is not setCONFIG_FUJITSU_LAPTOP=yCONFIG_FUJITSU_LAPTOP_DEBUG=y
# CONFIG_HP_WMI is not setCONFIG_MSI_LAPTOP=y
# CONFIG_COMPAL_LAPTOP is not setCONFIG_SONY_LAPTOP=y
# CONFIG_SONYPI_COMPAT is not set
# CONFIG_THINKPAD_ACPI is not setCONFIG_INTEL_MENLOW=yCONFIG_ENCLOSURE_SERVICES=y
# CONFIG_SGI_XP is not setCONFIG_HP_ILO=y
# CONFIG_SGI_GRU is not setCONFIG_HAVE_IDE=y
#
# SCSI device support
#CONFIG_RAID_ATTRS=yCONFIG_SCSI=yCONFIG_SCSI_DMA=yCONFIG_SCSI_TGT=yCONFIG_SCSI_NETLINK=yCONFIG_SCSI_PROC_FS=y
#
# SCSI support type (disk, tape, CD-ROM)
#CONFIG_BLK_DEV_SD=yCONFIG_CHR_DEV_ST=y
# CONFIG_CHR_DEV_OSST is not setCONFIG_BLK_DEV_SR=yCONFIG_BLK_DEV_SR_VENDOR=yCONFIG_CHR_DEV_SG=y
# CONFIG_CHR_DEV_SCH is not setCONFIG_SCSI_ENCLOSURE=y
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs #CONFIG_SCSI_MULTI_LUN=yCONFIG_SCSI_CONSTANTS=yCONFIG_SCSI_LOGGING=yCONFIG_SCSI_SCAN_ASYNC=y
#
# SCSI Transports
#CONFIG_SCSI_SPI_ATTRS=yCONFIG_SCSI_FC_ATTRS=y
# CONFIG_SCSI_FC_TGT_ATTRS is not setCONFIG_SCSI_ISCSI_ATTRS=yCONFIG_SCSI_SAS_ATTRS=yCONFIG_SCSI_SRP_ATTRS=yCONFIG_SCSI_SRP_TGT_ATTRS=yCONFIG_SCSI_LOWLEVEL=yCONFIG_ISCSI_TCP=y
# CONFIG_BLK_DEV_3W_XXXX_RAID is not setCONFIG_SCSI_3W_9XXX=yCONFIG_SCSI_ACARD=yCONFIG_SCSI_AACRAID=yCONFIG_SCSI_AIC7XXX=yCONFIG_AIC7XXX_CMDS_PER_DEVICE=32CONFIG_AIC7XXX_RESET_DELAY_MS=5000CONFIG_AIC7XXX_DEBUG_ENABLE=yCONFIG_AIC7XXX_DEBUG_MASK=0CONFIG_AIC7XXX_REG_PRETTY_PRINT=yCONFIG_SCSI_AIC7XXX_OLD=y
# CONFIG_SCSI_AIC79XX is not setCONFIG_SCSI_DPT_I2O=yCONFIG_SCSI_ADVANSYS=y
# CONFIG_SCSI_ARCMSR is not setCONFIG_MEGARAID_NEWGEN=y
# CONFIG_MEGARAID_MM is not setCONFIG_MEGARAID_LEGACY=yCONFIG_MEGARAID_SAS=y
# CONFIG_SCSI_HPTIOP is not setCONFIG_SCSI_BUSLOGIC=yCONFIG_SCSI_DMX3191D=yCONFIG_SCSI_EATA=yCONFIG_SCSI_EATA_TAGGED_QUEUE=yCONFIG_SCSI_EATA_LINKED_COMMANDS=yCONFIG_SCSI_EATA_MAX_TAGS=16CONFIG_SCSI_FUTURE_DOMAIN=y
# CONFIG_SCSI_GDTH is not setCONFIG_SCSI_IPS=yCONFIG_SCSI_INITIO=y
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not setCONFIG_SCSI_IPR=y
# CONFIG_SCSI_IPR_TRACE is not setCONFIG_SCSI_IPR_DUMP=yCONFIG_SCSI_QLOGIC_1280=y
# CONFIG_SCSI_QLA_FC is not setCONFIG_SCSI_QLA_ISCSI=yCONFIG_SCSI_LPFC=y
CONFIG_SCSI_DC395x=yCONFIG_SCSI_DC390T=y
# CONFIG_SCSI_SRP is not setCONFIG_SCSI_DH=y
# CONFIG_SCSI_DH_RDAC is not setCONFIG_SCSI_DH_HP_SW=y
# CONFIG_SCSI_DH_EMC is not setCONFIG_SCSI_DH_ALUA=yCONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
# CONFIG_ATA_ACPI is not set
# CONFIG_SATA_PMP is not setCONFIG_SATA_AHCI=yCONFIG_SATA_SIL24=yCONFIG_ATA_SFF=yCONFIG_SATA_SVW=yCONFIG_ATA_PIIX=yCONFIG_SATA_MV=yCONFIG_SATA_NV=yCONFIG_PDC_ADMA=yCONFIG_SATA_QSTOR=y
# CONFIG_SATA_PROMISE is not set
# CONFIG_SATA_SX4 is not setCONFIG_SATA_SIL=y
# CONFIG_SATA_SIS is not set
# CONFIG_SATA_ULI is not setCONFIG_SATA_VIA=y
# CONFIG_SATA_VITESSE is not setCONFIG_SATA_INIC162X=yCONFIG_PATA_ALI=yCONFIG_PATA_AMD=yCONFIG_PATA_ARTOP=yCONFIG_PATA_ATIIXP=yCONFIG_PATA_CMD640_PCI=y
# CONFIG_PATA_CMD64X is not setCONFIG_PATA_CS5520=y
# CONFIG_PATA_CS5530 is not setCONFIG_PATA_CYPRESS=y
# CONFIG_PATA_EFAR is not setCONFIG_ATA_GENERIC=y
# CONFIG_PATA_HPT366 is not set
# CONFIG_PATA_HPT37X is not setCONFIG_PATA_HPT3X2N=yCONFIG_PATA_HPT3X3=yCONFIG_PATA_HPT3X3_DMA=y
# CONFIG_PATA_IT821X is not set
# CONFIG_PATA_IT8213 is not setCONFIG_PATA_JMICRON=yCONFIG_PATA_TRIFLEX=y
# CONFIG_PATA_MARVELL is not setCONFIG_PATA_MPIIX=yCONFIG_PATA_OLDPIIX=yCONFIG_PATA_NETCELL=yCONFIG_PATA_NINJA32=yCONFIG_PATA_NS87410=yCONFIG_PATA_NS87415=yCONFIG_PATA_OPTI=yCONFIG_PATA_OPTIDMA=y
# CONFIG_PATA_PDC_OLD is not setCONFIG_PATA_RADISYS=y
# CONFIG_PATA_RZ1000 is not setCONFIG_PATA_SC1200=yCONFIG_PATA_SERVERWORKS=yCONFIG_PATA_PDC2027X=yCONFIG_PATA_SIL680=yCONFIG_PATA_SIS=y
# CONFIG_PATA_VIA is not set
# CONFIG_PATA_WINBOND is not setCONFIG_PATA_PLATFORM=y
# CONFIG_PATA_SCH is not setCONFIG_MD=y
# CONFIG_BLK_DEV_MD is not setCONFIG_BLK_DEV_DM=yCONFIG_DM_DEBUG=y
# CONFIG_DM_CRYPT is not setCONFIG_DM_SNAPSHOT=yCONFIG_DM_MIRROR=yCONFIG_DM_ZERO=yCONFIG_DM_MULTIPATH=yCONFIG_DM_DELAY=yCONFIG_DM_UEVENT=y
# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
#
#
# Enable only one of the two stacks, unless you know what you are doing #CONFIG_FIREWIRE=yCONFIG_FIREWIRE_OHCI=yCONFIG_FIREWIRE_OHCI_DEBUG=yCONFIG_FIREWIRE_SBP2=yCONFIG_IEEE1394=yCONFIG_IEEE1394_OHCI1394=y
# CONFIG_IEEE1394_PCILYNX is not setCONFIG_IEEE1394_SBP2=yCONFIG_IEEE1394_SBP2_PHYS_DMA=y CONFIG_IEEE1394_ETH1394_ROM_ENTRY=y CONFIG_IEEE1394_ETH1394=yCONFIG_IEEE1394_RAWIO=yCONFIG_IEEE1394_VIDEO1394=y
# CONFIG_IEEE1394_DV1394 is not set
# CONFIG_IEEE1394_VERBOSEDEBUG is not setCONFIG_I2O=yCONFIG_I2O_LCT_NOTIFY_ON_CHANGES=yCONFIG_I2O_EXT_ADAPTEC=yCONFIG_I2O_EXT_ADAPTEC_DMA64=y
# CONFIG_I2O_CONFIG is not set
# CONFIG_I2O_BUS is not set
# CONFIG_I2O_BLOCK is not setCONFIG_I2O_SCSI=yCONFIG_I2O_PROC=y
# CONFIG_MACINTOSH_DRIVERS is not setCONFIG_NETDEVICES=yCONFIG_IFB=yCONFIG_DUMMY=yCONFIG_BONDING=yCONFIG_MACVLAN=y
# CONFIG_EQUALIZER is not setCONFIG_TUN=yCONFIG_VETH=y
# CONFIG_NET_SB1000 is not setCONFIG_ARCNET=yCONFIG_ARCNET_1201=yCONFIG_ARCNET_1051=yCONFIG_ARCNET_RAW=yCONFIG_ARCNET_CAP=y
CONFIG_ARCNET_COM90xx=y
CONFIG_ARCNET_COM90xxIO=y
# CONFIG_ARCNET_RIM_I is not set
# CONFIG_ARCNET_COM20020 is not setCONFIG_PHYLIB=y
#
# MII PHY device drivers
#
# CONFIG_MARVELL_PHY is not setCONFIG_DAVICOM_PHY=yCONFIG_QSEMI_PHY=yCONFIG_LXT_PHY=yCONFIG_CICADA_PHY=yCONFIG_VITESSE_PHY=yCONFIG_SMSC_PHY=yCONFIG_BROADCOM_PHY=y
# CONFIG_ICPLUS_PHY is not setCONFIG_REALTEK_PHY=y
# CONFIG_FIXED_PHY is not setCONFIG_MDIO_BITBANG=yCONFIG_NET_ETHERNET=yCONFIG_MII=yCONFIG_HAPPYMEAL=yCONFIG_SUNGEM=yCONFIG_CASSINI=y
# CONFIG_NET_VENDOR_3COM is not setCONFIG_VORTEX=y
# CONFIG_NET_TULIP is not setCONFIG_HP100=y
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not setCONFIG_NET_PCI=yCONFIG_PCNET32=y
# CONFIG_AMD8111_ETH is not setCONFIG_ADAPTEC_STARFIRE=yCONFIG_B44=yCONFIG_B44_PCI_AUTOSELECT=yCONFIG_B44_PCICORE_AUTOSELECT=yCONFIG_B44_PCI=yCONFIG_FORCEDETH=y
# CONFIG_FORCEDETH_NAPI is not setCONFIG_EEPRO100=yCONFIG_E100=yCONFIG_FEALNX=yCONFIG_NATSEMI=y
# CONFIG_NE2K_PCI is not setCONFIG_8139CP=yCONFIG_8139TOO=yCONFIG_8139TOO_PIO=yCONFIG_8139TOO_TUNE_TWISTER=y
# CONFIG_8139TOO_8129 is not setCONFIG_8139_OLD_RX_RESET=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not setCONFIG_EPIC100=yCONFIG_SUNDANCE=y
# CONFIG_SUNDANCE_MMIO is not setCONFIG_TLAN=yCONFIG_VIA_RHINE=yCONFIG_VIA_RHINE_MMIO=yCONFIG_SC92031=yCONFIG_NETDEV_1000=yCONFIG_ACENIC=yCONFIG_ACENIC_OMIT_TIGON_I=y
# CONFIG_DL2K is not setCONFIG_E1000=yCONFIG_E1000_DISABLE_PACKET_SPLIT=yCONFIG_E1000E=yCONFIG_IP1000=yCONFIG_IGB=y
# CONFIG_IGB_LRO is not setCONFIG_NS83820=yCONFIG_HAMACHI=y
# CONFIG_YELLOWFIN is not setCONFIG_R8169=yCONFIG_R8169_VLAN=yCONFIG_SIS190=y
# CONFIG_SKGE is not setCONFIG_SKY2=yCONFIG_SKY2_DEBUG=yCONFIG_VIA_VELOCITY=yCONFIG_TIGON3=yCONFIG_BNX2=y
# CONFIG_QLA3XXX is not setCONFIG_ATL1=yCONFIG_ATL1E=y
# CONFIG_NETDEV_10000 is not setCONFIG_MLX4_CORE=y
# CONFIG_TR is not set
#
# Wireless LAN
#CONFIG_WLAN_PRE80211=yCONFIG_STRIP=y
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
#
# USB Network Adapters
#
# CONFIG_USB_CATC is not setCONFIG_USB_KAWETH=yCONFIG_USB_PEGASUS=y
# CONFIG_USB_RTL8150 is not setCONFIG_USB_USBNET=yCONFIG_USB_NET_AX8817X=yCONFIG_USB_NET_CDCETHER=yCONFIG_USB_NET_DM9601=yCONFIG_USB_NET_GL620A=yCONFIG_USB_NET_NET1080=yCONFIG_USB_NET_PLUSB=y
# CONFIG_USB_NET_MCS7830 is not set
# CONFIG_USB_NET_RNDIS_HOST is not set
# CONFIG_USB_NET_CDC_SUBSET is not setCONFIG_USB_NET_ZAURUS=y
# CONFIG_USB_HSO is not setCONFIG_WAN=y
# CONFIG_LANMEDIA is not setCONFIG_HDLC=yCONFIG_HDLC_RAW=y
# CONFIG_HDLC_RAW_ETH is not setCONFIG_HDLC_CISCO=yCONFIG_HDLC_FR=yCONFIG_HDLC_PPP=yCONFIG_HDLC_X25=yCONFIG_PCI200SYN=yCONFIG_WANXL=y
# CONFIG_PC300 is not setCONFIG_PC300TOO=y
# CONFIG_FARSYNC is not set
# CONFIG_DLCI is not setCONFIG_LAPBETHER=yCONFIG_X25_ASY=yCONFIG_SBNI=yCONFIG_SBNI_MULTILINE=yCONFIG_ATM_DRIVERS=yCONFIG_ATM_DUMMY=y
# CONFIG_ATM_TCP is not setCONFIG_ATM_LANAI=yCONFIG_ATM_ENI=y
# CONFIG_ATM_ENI_DEBUG is not setCONFIG_ATM_ENI_TUNE_BURST=yCONFIG_ATM_ENI_BURST_TX_16W=yCONFIG_ATM_ENI_BURST_TX_8W=y
# CONFIG_ATM_ENI_BURST_TX_4W is not setCONFIG_ATM_ENI_BURST_TX_2W=yCONFIG_ATM_ENI_BURST_RX_16W=yCONFIG_ATM_ENI_BURST_RX_8W=yCONFIG_ATM_ENI_BURST_RX_4W=yCONFIG_ATM_ENI_BURST_RX_2W=yCONFIG_ATM_FIRESTREAM=yCONFIG_ATM_ZATM=yCONFIG_ATM_ZATM_DEBUG=yCONFIG_ATM_IDT77252=yCONFIG_ATM_IDT77252_DEBUG=y
# CONFIG_ATM_IDT77252_RCV_ALL is not setCONFIG_ATM_IDT77252_USE_SUNI=y
# CONFIG_ATM_AMBASSADOR is not setCONFIG_ATM_HORIZON=yCONFIG_ATM_HORIZON_DEBUG=y
# CONFIG_ATM_IA is not setCONFIG_ATM_FORE200E=yCONFIG_ATM_FORE200E_USE_TASKLET=yCONFIG_ATM_FORE200E_TX_RETRY=16CONFIG_ATM_FORE200E_DEBUG=0CONFIG_ATM_HE=yCONFIG_ATM_HE_USE_SUNI=yCONFIG_FDDI=yCONFIG_DEFXX=y
# CONFIG_DEFXX_MMIO is not setCONFIG_SKFP=yCONFIG_HIPPI=yCONFIG_ROADRUNNER=y
# CONFIG_ROADRUNNER_LARGE_RINGS is not setCONFIG_PPP=yCONFIG_PPP_MULTILINK=y
# CONFIG_PPP_FILTER is not setCONFIG_PPP_ASYNC=yCONFIG_PPP_SYNC_TTY=y
# CONFIG_PPP_DEFLATE is not set
# CONFIG_PPP_BSDCOMP is not set
# CONFIG_PPP_MPPE is not setCONFIG_PPPOE=y
# CONFIG_PPPOATM is not setCONFIG_PPPOL2TP=yCONFIG_SLIP=yCONFIG_SLIP_COMPRESSED=yCONFIG_SLHC=y
# CONFIG_SLIP_SMART is not set
# CONFIG_SLIP_MODE_SLIP6 is not setCONFIG_NET_FC=yCONFIG_NETCONSOLE=yCONFIG_NETCONSOLE_DYNAMIC=yCONFIG_NETPOLL=yCONFIG_NETPOLL_TRAP=yCONFIG_NET_POLL_CONTROLLER=yCONFIG_VIRTIO_NET=y
# CONFIG_ISDN is not setCONFIG_PHONE=y
#
# Input device support
#CONFIG_INPUT=yCONFIG_INPUT_FF_MEMLESS=yCONFIG_INPUT_POLLDEV=y
#
# Userland interfaces
#CONFIG_INPUT_MOUSEDEV=yCONFIG_INPUT_MOUSEDEV_PSAUX=yCONFIG_INPUT_MOUSEDEV_SCREEN_X=1024CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_EVDEV is not setCONFIG_INPUT_EVBUG=y
#
# Input Device Drivers
#CONFIG_INPUT_KEYBOARD=yCONFIG_KEYBOARD_ATKBD=yCONFIG_KEYBOARD_SUNKBD=yCONFIG_KEYBOARD_LKKBD=yCONFIG_KEYBOARD_XTKBD=yCONFIG_KEYBOARD_NEWTON=y
# CONFIG_KEYBOARD_STOWAWAY is not set
# CONFIG_KEYBOARD_GPIO is not set
# CONFIG_INPUT_MOUSE is not setCONFIG_INPUT_JOYSTICK=yCONFIG_JOYSTICK_ANALOG=yCONFIG_JOYSTICK_A3D=y
# CONFIG_JOYSTICK_ADI is not setCONFIG_JOYSTICK_COBRA=yCONFIG_JOYSTICK_GF2K=yCONFIG_JOYSTICK_GRIP=yCONFIG_JOYSTICK_GRIP_MP=yCONFIG_JOYSTICK_GUILLEMOT=yCONFIG_JOYSTICK_INTERACT=yCONFIG_JOYSTICK_SIDEWINDER=y
# CONFIG_JOYSTICK_TMDC is not set
# CONFIG_JOYSTICK_IFORCE is not setCONFIG_JOYSTICK_WARRIOR=y
# CONFIG_JOYSTICK_MAGELLAN is not set
# CONFIG_JOYSTICK_SPACEORB is not setCONFIG_JOYSTICK_SPACEBALL=yCONFIG_JOYSTICK_STINGER=yCONFIG_JOYSTICK_TWIDJOY=yCONFIG_JOYSTICK_ZHENHUA=yCONFIG_JOYSTICK_JOYDUMP=yCONFIG_JOYSTICK_XPAD=yCONFIG_JOYSTICK_XPAD_FF=y
# CONFIG_JOYSTICK_XPAD_LEDS is not set
# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not setCONFIG_INPUT_MISC=yCONFIG_INPUT_APANEL=y
# CONFIG_INPUT_ATLAS_BTNS is not setCONFIG_INPUT_ATI_REMOTE=yCONFIG_INPUT_ATI_REMOTE2=y
# CONFIG_INPUT_KEYSPAN_REMOTE is not set
# CONFIG_INPUT_POWERMATE is not setCONFIG_INPUT_YEALINK=yCONFIG_INPUT_UINPUT=y
#
# Hardware I/O ports
#CONFIG_SERIO=yCONFIG_SERIO_I8042=yCONFIG_SERIO_SERPORT=y
# CONFIG_SERIO_CT82C710 is not set
# CONFIG_SERIO_PCIPS2 is not setCONFIG_SERIO_LIBPS2=yCONFIG_SERIO_RAW=yCONFIG_GAMEPORT=y
# CONFIG_GAMEPORT_NS558 is not set
# CONFIG_GAMEPORT_L4 is not setCONFIG_GAMEPORT_EMU10K1=yCONFIG_GAMEPORT_FM801=y
#
# Character devices
#CONFIG_VT=yCONFIG_CONSOLE_TRANSLATIONS=yCONFIG_VT_CONSOLE=yCONFIG_HW_CONSOLE=yCONFIG_VT_HW_CONSOLE_BINDING=yCONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not setCONFIG_NOZOMI=y
#
# Serial drivers
#CONFIG_SERIAL_8250=yCONFIG_SERIAL_8250_CONSOLE=yCONFIG_FIX_EARLYCON_MEM=yCONFIG_SERIAL_8250_PCI=yCONFIG_SERIAL_8250_PNP=yCONFIG_SERIAL_8250_NR_UARTS=4CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
#
# Non-8250 serial port support
#CONFIG_SERIAL_CORE=yCONFIG_SERIAL_CORE_CONSOLE=yCONFIG_SERIAL_JSM=yCONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not setCONFIG_HVC_DRIVER=yCONFIG_VIRTIO_CONSOLE=y
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not setCONFIG_NVRAM=yCONFIG_RTC=y
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not setCONFIG_MWAVE=y
CONFIG_PC8736x_GPIO=yCONFIG_NSC_GPIO=yCONFIG_RAW_DRIVER=yCONFIG_MAX_RAW_DEVS=256CONFIG_HPET=yCONFIG_HPET_RTC_IRQ=y
# CONFIG_HPET_MMAP is not setCONFIG_HANGCHECK_TIMER=yCONFIG_TCG_TPM=yCONFIG_TCG_TIS=y
# CONFIG_TCG_NSC is not set
# CONFIG_TCG_ATMEL is not setCONFIG_TCG_INFINEON=yCONFIG_TELCLOCK=yCONFIG_DEVPORT=yCONFIG_I2C=yCONFIG_I2C_BOARDINFO=yCONFIG_I2C_CHARDEV=y
# CONFIG_I2C_HELPER_AUTO is not set
#
# I2C Algorithms
#CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_ALGOPCF is not setCONFIG_I2C_ALGOPCA=y
#
# I2C Hardware Bus support
#
#
# PC SMBus host controller drivers
#
# CONFIG_I2C_ALI1535 is not setCONFIG_I2C_ALI1563=y
# CONFIG_I2C_ALI15X3 is not setCONFIG_I2C_AMD756=y
# CONFIG_I2C_AMD8111 is not setCONFIG_I2C_I801=y
# CONFIG_I2C_ISCH is not setCONFIG_I2C_PIIX4=yCONFIG_I2C_NFORCE2=yCONFIG_I2C_SIS5595=y
# CONFIG_I2C_SIS630 is not setCONFIG_I2C_SIS96X=yCONFIG_I2C_VIA=yCONFIG_I2C_VIAPRO=y
#
# I2C system bus drivers (mostly embedded / system-on-chip) #CONFIG_I2C_GPIO=y
# CONFIG_I2C_OCORES is not setCONFIG_I2C_SIMTEC=y
#
# External I2C/SMBus adapter drivers
#CONFIG_I2C_PARPORT_LIGHT=yCONFIG_I2C_TAOS_EVM=y
# CONFIG_I2C_TINY_USB is not set
#
# Graphics adapter I2C/DDC channel drivers
#CONFIG_I2C_VOODOO3=y
#
# Other I2C/SMBus bus drivers
#CONFIG_I2C_PCA_PLATFORM=y
#
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not setCONFIG_AT24=yCONFIG_SENSORS_EEPROM=yCONFIG_SENSORS_PCF8574=yCONFIG_PCF8575=yCONFIG_SENSORS_PCF8591=yCONFIG_TPS65010=yCONFIG_SENSORS_MAX6875=yCONFIG_SENSORS_TSL2550=yCONFIG_I2C_DEBUG_CORE=yCONFIG_I2C_DEBUG_ALGO=y
# CONFIG_I2C_DEBUG_BUS is not setCONFIG_I2C_DEBUG_CHIP=y
# CONFIG_SPI is not setCONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=yCONFIG_GPIOLIB=y
# CONFIG_GPIO_SYSFS is not set
#
# I2C GPIO expanders:
#
# CONFIG_GPIO_MAX732X is not setCONFIG_GPIO_PCA953X=y
# CONFIG_GPIO_PCF857X is not set
#
# PCI GPIO expanders:
#CONFIG_GPIO_BT8XX=y
#
# SPI GPIO expanders:
#CONFIG_W1=y
# CONFIG_W1_CON is not set
#
# 1-wire Bus Masters
#
# CONFIG_W1_MASTER_MATROX is not set
# CONFIG_W1_MASTER_DS2490 is not setCONFIG_W1_MASTER_DS2482=yCONFIG_W1_MASTER_GPIO=y
#
# 1-wire Slaves
#CONFIG_W1_SLAVE_THERM=y
# CONFIG_W1_SLAVE_SMEM is not set
# CONFIG_W1_SLAVE_DS2433 is not setCONFIG_W1_SLAVE_DS2760=yCONFIG_POWER_SUPPLY=yCONFIG_POWER_SUPPLY_DEBUG=y
# CONFIG_PDA_POWER is not set
# CONFIG_BATTERY_DS2760 is not set
# CONFIG_HWMON is not setCONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
#
# Sonics Silicon Backplane
#CONFIG_SSB_POSSIBLE=yCONFIG_SSB=yCONFIG_SSB_SPROM=yCONFIG_SSB_PCIHOST_POSSIBLE=yCONFIG_SSB_PCIHOST=y
# CONFIG_SSB_B43_PCI_BRIDGE is not setCONFIG_SSB_SILENT=yCONFIG_SSB_DRIVER_PCICORE_POSSIBLE=yCONFIG_SSB_DRIVER_PCICORE=y
#
# Multifunction device drivers
#
# CONFIG_MFD_CORE is not setCONFIG_MFD_SM501=y
# CONFIG_MFD_SM501_GPIO is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
#
# Multimedia devices
#
#
# Multimedia core support
#
# CONFIG_VIDEO_DEV is not setCONFIG_DVB_CORE=yCONFIG_VIDEO_MEDIA=y
#
# Multimedia drivers
#CONFIG_MEDIA_TUNER=yCONFIG_MEDIA_TUNER_CUSTOMIZE=y
# CONFIG_MEDIA_TUNER_SIMPLE is not setCONFIG_MEDIA_TUNER_TDA8290=yCONFIG_MEDIA_TUNER_TDA827X=yCONFIG_MEDIA_TUNER_TDA18271=yCONFIG_MEDIA_TUNER_TDA9887=yCONFIG_MEDIA_TUNER_TEA5761=yCONFIG_MEDIA_TUNER_TEA5767=y
# CONFIG_MEDIA_TUNER_MT20XX is not setCONFIG_MEDIA_TUNER_MT2060=yCONFIG_MEDIA_TUNER_MT2266=yCONFIG_MEDIA_TUNER_MT2131=yCONFIG_MEDIA_TUNER_QT1010=yCONFIG_MEDIA_TUNER_XC2028=y
# CONFIG_MEDIA_TUNER_XC5000 is not setCONFIG_MEDIA_TUNER_MXL5005S=yCONFIG_MEDIA_TUNER_MXL5007T=y
# CONFIG_DVB_CAPTURE_DRIVERS is not setCONFIG_DAB=yCONFIG_USB_DABUSB=y
#
# Graphics support
#CONFIG_AGP=yCONFIG_AGP_AMD64=yCONFIG_AGP_INTEL=yCONFIG_AGP_SIS=y
# CONFIG_AGP_VIA is not set
# CONFIG_DRM is not setCONFIG_VGASTATE=yCONFIG_VIDEO_OUTPUT_CONTROL=yCONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not setCONFIG_FB_DDC=yCONFIG_FB_CFB_FILLRECT=yCONFIG_FB_CFB_COPYAREA=yCONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not setCONFIG_FB_SYS_FILLRECT=yCONFIG_FB_SYS_COPYAREA=yCONFIG_FB_SYS_IMAGEBLIT=yCONFIG_FB_FOREIGN_ENDIAN=yCONFIG_FB_BOTH_ENDIAN=y
# CONFIG_FB_BIG_ENDIAN is not set
# CONFIG_FB_LITTLE_ENDIAN is not setCONFIG_FB_SYS_FOPS=yCONFIG_FB_DEFERRED_IO=yCONFIG_FB_HECUBA=yCONFIG_FB_SVGALIB=y
# CONFIG_FB_MACMODES is not setCONFIG_FB_BACKLIGHT=yCONFIG_FB_MODE_HELPERS=yCONFIG_FB_TILEBLITTING=y
#
# Frame buffer hardware drivers
#CONFIG_FB_PM2=yCONFIG_FB_PM2_FIFO_DISCONNECT=yCONFIG_FB_CYBER2000=yCONFIG_FB_ARC=yCONFIG_FB_IMSTT=yCONFIG_FB_UVESA=y
# CONFIG_FB_EFI is not set
# CONFIG_FB_IMAC is not setCONFIG_FB_N411=y
# CONFIG_FB_HGA is not setCONFIG_FB_S1D13XXX=yCONFIG_FB_NVIDIA=yCONFIG_FB_NVIDIA_I2C=yCONFIG_FB_NVIDIA_DEBUG=yCONFIG_FB_NVIDIA_BACKLIGHT=y
# CONFIG_FB_RIVA is not set
# CONFIG_FB_LE80578 is not setCONFIG_FB_INTEL=yCONFIG_FB_INTEL_DEBUG=y
# CONFIG_FB_INTEL_I2C is not set
# CONFIG_FB_MATROX is not set
# CONFIG_FB_ATY128 is not setCONFIG_FB_ATY=y
# CONFIG_FB_ATY_CT is not setCONFIG_FB_ATY_GX=y
# CONFIG_FB_ATY_BACKLIGHT is not setCONFIG_FB_S3=yCONFIG_FB_SAVAGE=yCONFIG_FB_SAVAGE_I2C=y
# CONFIG_FB_SAVAGE_ACCEL is not set
# CONFIG_FB_SIS is not setCONFIG_FB_NEOMAGIC=y
# CONFIG_FB_KYRO is not setCONFIG_FB_3DFX=yCONFIG_FB_3DFX_ACCEL=yCONFIG_FB_VOODOO1=yCONFIG_FB_VT8623=y
# CONFIG_FB_TRIDENT is not setCONFIG_FB_ARK=y
# CONFIG_FB_PM3 is not set
# CONFIG_FB_CARMINE is not setCONFIG_FB_GEODE=yCONFIG_FB_GEODE_LX=yCONFIG_FB_GEODE_GX=yCONFIG_FB_GEODE_GX1=yCONFIG_FB_SM501=yCONFIG_BACKLIGHT_LCD_SUPPORT=y
# CONFIG_LCD_CLASS_DEVICE is not setCONFIG_BACKLIGHT_CLASS_DEVICE=yCONFIG_BACKLIGHT_CORGI=y
# CONFIG_BACKLIGHT_PROGEAR is not setCONFIG_BACKLIGHT_MBP_NVIDIA=y
#
# Display device support
#CONFIG_DISPLAY_SUPPORT=y
#
# Display hardware drivers
#
#
# Console display driver support
#CONFIG_VGA_CONSOLE=yCONFIG_VGACON_SOFT_SCROLLBACK=yCONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64CONFIG_DUMMY_CONSOLE=yCONFIG_LOGO=yCONFIG_LOGO_LINUX_MONO=yCONFIG_LOGO_LINUX_VGA16=yCONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_SOUND is not setCONFIG_HID_SUPPORT=yCONFIG_HID=yCONFIG_HID_DEBUG=y
# CONFIG_HIDRAW is not set
#
# USB Input Devices
#CONFIG_USB_HID=yCONFIG_USB_HIDINPUT_POWERBOOK=y
# CONFIG_HID_FF is not set
# CONFIG_USB_HIDDEV is not setCONFIG_USB_MOUSE=yCONFIG_USB_SUPPORT=yCONFIG_USB_ARCH_HAS_HCD=yCONFIG_USB_ARCH_HAS_OHCI=yCONFIG_USB_ARCH_HAS_EHCI=yCONFIG_USB=yCONFIG_USB_DEBUG=y
# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
#
# Miscellaneous USB options
#CONFIG_USB_DEVICEFS=yCONFIG_USB_DEVICE_CLASS=yCONFIG_USB_DYNAMIC_MINORS=y
# CONFIG_USB_SUSPEND is not set
# CONFIG_USB_OTG is not setCONFIG_USB_OTG_WHITELIST=yCONFIG_USB_OTG_BLACKLIST_HUB=yCONFIG_USB_MON=y
#
# USB Host Controller Drivers
#CONFIG_USB_C67X00_HCD=yCONFIG_USB_EHCI_HCD=yCONFIG_USB_EHCI_ROOT_HUB_TT=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not setCONFIG_USB_ISP116X_HCD=yCONFIG_USB_ISP1760_HCD=y
# CONFIG_USB_ISP1760_PCI is not setCONFIG_USB_OHCI_HCD=yCONFIG_USB_OHCI_HCD_SSB=y
# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not setCONFIG_USB_OHCI_LITTLE_ENDIAN=yCONFIG_USB_UHCI_HCD=yCONFIG_USB_U132_HCD=y
# CONFIG_USB_SL811_HCD is not setCONFIG_USB_R8A66597_HCD=y
#
# USB Device Class drivers
#CONFIG_USB_ACM=yCONFIG_USB_PRINTER=y
# CONFIG_USB_WDM is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' #
#
# may also be needed; see USB_STORAGE Help for more information # # CONFIG_USB_STORAGE is not set CONFIG_USB_LIBUSUAL=y
#
# USB Imaging devices
#CONFIG_USB_MDC800=y
# CONFIG_USB_MICROTEK is not set
#
# USB port drivers
#CONFIG_USB_SERIAL=yCONFIG_USB_SERIAL_CONSOLE=yCONFIG_USB_EZUSB=y
# CONFIG_USB_SERIAL_GENERIC is not setCONFIG_USB_SERIAL_AIRCABLE=yCONFIG_USB_SERIAL_ARK3116=yCONFIG_USB_SERIAL_BELKIN=yCONFIG_USB_SERIAL_CH341=y
# CONFIG_USB_SERIAL_WHITEHEAT is not setCONFIG_USB_SERIAL_DIGI_ACCELEPORT=yCONFIG_USB_SERIAL_CP2101=yCONFIG_USB_SERIAL_CYPRESS_M8=yCONFIG_USB_SERIAL_EMPEG=yCONFIG_USB_SERIAL_FTDI_SIO=yCONFIG_USB_SERIAL_FUNSOFT=yCONFIG_USB_SERIAL_VISOR=y
# CONFIG_USB_SERIAL_IPAQ is not setCONFIG_USB_SERIAL_IR=y
# CONFIG_USB_SERIAL_EDGEPORT is not setCONFIG_USB_SERIAL_EDGEPORT_TI=yCONFIG_USB_SERIAL_GARMIN=yCONFIG_USB_SERIAL_IPW=y
# CONFIG_USB_SERIAL_IUU is not setCONFIG_USB_SERIAL_KEYSPAN_PDA=yCONFIG_USB_SERIAL_KEYSPAN=y
# CONFIG_USB_SERIAL_KEYSPAN_MPR is not setCONFIG_USB_SERIAL_KEYSPAN_USA28=yCONFIG_USB_SERIAL_KEYSPAN_USA28X=yCONFIG_USB_SERIAL_KEYSPAN_USA28XA=yCONFIG_USB_SERIAL_KEYSPAN_USA28XB=yCONFIG_USB_SERIAL_KEYSPAN_USA19=y
# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not setCONFIG_USB_SERIAL_KEYSPAN_USA19W=yCONFIG_USB_SERIAL_KEYSPAN_USA19QW=yCONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not setCONFIG_USB_SERIAL_KEYSPAN_USA49WLC=yCONFIG_USB_SERIAL_KLSI=yCONFIG_USB_SERIAL_KOBIL_SCT=yCONFIG_USB_SERIAL_MCT_U232=yCONFIG_USB_SERIAL_MOS7720=yCONFIG_USB_SERIAL_MOS7840=y
# CONFIG_USB_SERIAL_MOTOROLA is not setCONFIG_USB_SERIAL_NAVMAN=yCONFIG_USB_SERIAL_PL2303=yCONFIG_USB_SERIAL_OTI6858=y
# CONFIG_USB_SERIAL_SPCP8X5 is not setCONFIG_USB_SERIAL_HP4X=y
# CONFIG_USB_SERIAL_SAFE is not setCONFIG_USB_SERIAL_SIERRAWIRELESS=y
# CONFIG_USB_SERIAL_TI is not setCONFIG_USB_SERIAL_CYBERJACK=y
# CONFIG_USB_SERIAL_XIRCOM is not setCONFIG_USB_SERIAL_OPTION=y
# CONFIG_USB_SERIAL_OMNINET is not set
# CONFIG_USB_SERIAL_DEBUG is not set
#
# USB Miscellaneous drivers
#CONFIG_USB_EMI62=y
# CONFIG_USB_EMI26 is not setCONFIG_USB_ADUTUX=y
# CONFIG_USB_RIO500 is not setCONFIG_USB_LEGOTOWER=y
# CONFIG_USB_LCD is not setCONFIG_USB_BERRY_CHARGE=y
# CONFIG_USB_LED is not setCONFIG_USB_CYPRESS_CY7C63=y
# CONFIG_USB_CYTHERM is not setCONFIG_USB_PHIDGET=yCONFIG_USB_PHIDGETKIT=y
# CONFIG_USB_PHIDGETMOTORCONTROL is not set
# CONFIG_USB_PHIDGETSERVO is not setCONFIG_USB_IDMOUSE=yCONFIG_USB_FTDI_ELAN=y
# CONFIG_USB_APPLEDISPLAY is not setCONFIG_USB_SISUSBVGA=y
# CONFIG_USB_SISUSBVGA_CON is not setCONFIG_USB_LD=y
# CONFIG_USB_TRANCEVIBRATOR is not setCONFIG_USB_IOWARRIOR=yCONFIG_USB_TEST=y
# CONFIG_USB_ISIGHTFW is not setCONFIG_USB_ATM=y
# CONFIG_USB_SPEEDTOUCH is not setCONFIG_USB_CXACRU=yCONFIG_USB_UEAGLEATM=y
# CONFIG_USB_XUSBATM is not set
# CONFIG_MMC is not setCONFIG_MEMSTICK=yCONFIG_MEMSTICK_DEBUG=y
#
# MemoryStick drivers
#CONFIG_MEMSTICK_UNSAFE_RESUME=y
# CONFIG_MSPRO_BLOCK is not set
#
# MemoryStick Host Controller Drivers
#CONFIG_MEMSTICK_TIFM_MS=yCONFIG_MEMSTICK_JMICRON_38X=yCONFIG_NEW_LEDS=yCONFIG_LEDS_CLASS=y
#
# LED drivers
#CONFIG_LEDS_PCA9532=y
# CONFIG_LEDS_GPIO is not set
# CONFIG_LEDS_CLEVO_MAIL is not setCONFIG_LEDS_PCA955X=y
#
# LED Triggers
#CONFIG_LEDS_TRIGGERS=y
# CONFIG_LEDS_TRIGGER_TIMER is not setCONFIG_LEDS_TRIGGER_HEARTBEAT=yCONFIG_LEDS_TRIGGER_DEFAULT_ON=yCONFIG_ACCESSIBILITY=yCONFIG_A11Y_BRAILLE_CONSOLE=yCONFIG_INFINIBAND=y
# CONFIG_INFINIBAND_USER_MAD is not set
# CONFIG_INFINIBAND_USER_ACCESS is not setCONFIG_INFINIBAND_ADDR_TRANS=y
# CONFIG_INFINIBAND_MTHCA is not setCONFIG_INFINIBAND_IPATH=yCONFIG_INFINIBAND_AMSO1100=y
# CONFIG_INFINIBAND_AMSO1100_DEBUG is not setCONFIG_MLX4_INFINIBAND=yCONFIG_INFINIBAND_NES=yCONFIG_INFINIBAND_NES_DEBUG=yCONFIG_INFINIBAND_IPOIB=y
# CONFIG_INFINIBAND_IPOIB_CM is not set
# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
# CONFIG_INFINIBAND_SRP is not setCONFIG_INFINIBAND_ISER=yCONFIG_EDAC=y
#
# Reporting subsystems
#CONFIG_EDAC_DEBUG=yCONFIG_EDAC_MM_EDAC=yCONFIG_EDAC_E752X=yCONFIG_EDAC_I82975X=yCONFIG_EDAC_I3000=y
# CONFIG_EDAC_I5000 is not set
# CONFIG_EDAC_I5100 is not set
# CONFIG_RTC_CLASS is not setCONFIG_DMADEVICES=y
#
# DMA Devices
#CONFIG_INTEL_IOATDMA=yCONFIG_DMA_ENGINE=y
#
# DMA Clients
#
# CONFIG_NET_DMA is not setCONFIG_DMATEST=yCONFIG_DCA=yCONFIG_UIO=y
# CONFIG_UIO_CIF is not setCONFIG_UIO_PDRV=yCONFIG_UIO_PDRV_GENIRQ=yCONFIG_UIO_SMX=y
#
# Firmware Drivers
#CONFIG_EDD=yCONFIG_EDD_OFF=yCONFIG_FIRMWARE_MEMMAP=yCONFIG_EFI_VARS=yCONFIG_DELL_RBU=y
# CONFIG_DCDBAS is not setCONFIG_DMIID=yCONFIG_ISCSI_IBFT_FIND=yCONFIG_ISCSI_IBFT=y
#
# File systems
#
# CONFIG_EXT2_FS is not setCONFIG_EXT3_FS=yCONFIG_EXT3_FS_XATTR=yCONFIG_EXT3_FS_POSIX_ACL=yCONFIG_EXT3_FS_SECURITY=y
# CONFIG_EXT4DEV_FS is not setCONFIG_JBD=yCONFIG_JBD_DEBUG=yCONFIG_FS_MBCACHE=yCONFIG_REISERFS_FS=yCONFIG_REISERFS_CHECK=y
# CONFIG_REISERFS_PROC_INFO is not setCONFIG_REISERFS_FS_XATTR=yCONFIG_REISERFS_FS_POSIX_ACL=yCONFIG_REISERFS_FS_SECURITY=y
# CONFIG_JFS_FS is not setCONFIG_FS_POSIX_ACL=yCONFIG_XFS_FS=y
# CONFIG_XFS_QUOTA is not setCONFIG_XFS_POSIX_ACL=yCONFIG_XFS_RT=yCONFIG_XFS_DEBUG=yCONFIG_GFS2_FS=yCONFIG_GFS2_FS_LOCKING_DLM=y
# CONFIG_OCFS2_FS is not setCONFIG_DNOTIFY=yCONFIG_INOTIFY=yCONFIG_INOTIFY_USER=yCONFIG_QUOTA=yCONFIG_QUOTA_NETLINK_INTERFACE=yCONFIG_PRINT_QUOTA_WARNING=y
# CONFIG_QFMT_V1 is not setCONFIG_QFMT_V2=yCONFIG_QUOTACTL=yCONFIG_AUTOFS_FS=yCONFIG_AUTOFS4_FS=y
# CONFIG_FUSE_FS is not setCONFIG_GENERIC_ACL=y
#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not setCONFIG_UDF_FS=yCONFIG_UDF_NLS=y
#
# DOS/FAT/NT Filesystems
#CONFIG_FAT_FS=yCONFIG_MSDOS_FS=yCONFIG_VFAT_FS=yCONFIG_FAT_DEFAULT_CODEPAGE=437CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
#
# Pseudo filesystems
#CONFIG_PROC_FS=y
# CONFIG_PROC_KCORE is not setCONFIG_PROC_SYSCTL=yCONFIG_SYSFS=yCONFIG_TMPFS=yCONFIG_TMPFS_POSIX_ACL=yCONFIG_HUGETLBFS=yCONFIG_HUGETLB_PAGE=yCONFIG_CONFIGFS_FS=y
#
# Miscellaneous filesystems
#CONFIG_ADFS_FS=y
# CONFIG_ADFS_FS_RW is not setCONFIG_AFFS_FS=yCONFIG_HFS_FS=yCONFIG_HFSPLUS_FS=yCONFIG_BEFS_FS=y
# CONFIG_BEFS_DEBUG is not set
# CONFIG_BFS_FS is not setCONFIG_EFS_FS=yCONFIG_CRAMFS=yCONFIG_VXFS_FS=yCONFIG_MINIX_FS=y
# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not setCONFIG_SYSV_FS=yCONFIG_UFS_FS=yCONFIG_UFS_FS_WRITE=yCONFIG_UFS_DEBUG=yCONFIG_NETWORK_FILESYSTEMS=yCONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
# CONFIG_NFS_V4 is not setCONFIG_NFSD=yCONFIG_NFSD_V3=y
# CONFIG_NFSD_V3_ACL is not setCONFIG_NFSD_V4=yCONFIG_LOCKD=yCONFIG_LOCKD_V4=yCONFIG_EXPORTFS=yCONFIG_NFS_COMMON=yCONFIG_SUNRPC=yCONFIG_SUNRPC_GSS=yCONFIG_SUNRPC_XPRT_RDMA=yCONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not setCONFIG_SMB_FS=y
# CONFIG_SMB_NLS_DEFAULT is not set
# CONFIG_CIFS is not setCONFIG_NCP_FS=yCONFIG_NCPFS_PACKET_SIGNING=y
# CONFIG_NCPFS_IOCTL_LOCKING is not set
# CONFIG_NCPFS_STRONG is not setCONFIG_NCPFS_NFS_NS=yCONFIG_NCPFS_OS2_NS=y
# CONFIG_NCPFS_SMALLDOS is not setCONFIG_NCPFS_NLS=y
# CONFIG_NCPFS_EXTRAS is not setCONFIG_CODA_FS=yCONFIG_AFS_FS=yCONFIG_AFS_DEBUG=yCONFIG_9P_FS=y
#
# Partition Types
#CONFIG_PARTITION_ADVANCED=yCONFIG_ACORN_PARTITION=y
# CONFIG_ACORN_PARTITION_CUMANA is not setCONFIG_ACORN_PARTITION_EESOX=y
# CONFIG_ACORN_PARTITION_ICS is not setCONFIG_ACORN_PARTITION_ADFS=yCONFIG_ACORN_PARTITION_POWERTEC=yCONFIG_ACORN_PARTITION_RISCIX=yCONFIG_OSF_PARTITION=yCONFIG_AMIGA_PARTITION=y
# CONFIG_ATARI_PARTITION is not setCONFIG_MAC_PARTITION=yCONFIG_MSDOS_PARTITION=yCONFIG_BSD_DISKLABEL=yCONFIG_MINIX_SUBPARTITION=yCONFIG_SOLARIS_X86_PARTITION=yCONFIG_UNIXWARE_DISKLABEL=yCONFIG_LDM_PARTITION=yCONFIG_LDM_DEBUG=y
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not setCONFIG_SUN_PARTITION=yCONFIG_KARMA_PARTITION=yCONFIG_EFI_PARTITION=yCONFIG_SYSV68_PARTITION=yCONFIG_NLS=yCONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not setCONFIG_NLS_CODEPAGE_850=y
# CONFIG_NLS_CODEPAGE_852 is not setCONFIG_NLS_CODEPAGE_855=yCONFIG_NLS_CODEPAGE_857=yCONFIG_NLS_CODEPAGE_860=y
# CONFIG_NLS_CODEPAGE_861 is not set
# CONFIG_NLS_CODEPAGE_862 is not setCONFIG_NLS_CODEPAGE_863=yCONFIG_NLS_CODEPAGE_864=yCONFIG_NLS_CODEPAGE_865=yCONFIG_NLS_CODEPAGE_866=yCONFIG_NLS_CODEPAGE_869=yCONFIG_NLS_CODEPAGE_936=yCONFIG_NLS_CODEPAGE_950=yCONFIG_NLS_CODEPAGE_932=yCONFIG_NLS_CODEPAGE_949=yCONFIG_NLS_CODEPAGE_874=yCONFIG_NLS_ISO8859_8=y
# CONFIG_NLS_CODEPAGE_1250 is not setCONFIG_NLS_CODEPAGE_1251=yCONFIG_NLS_ASCII=y
# CONFIG_NLS_ISO8859_1 is not setCONFIG_NLS_ISO8859_2=yCONFIG_NLS_ISO8859_3=yCONFIG_NLS_ISO8859_4=yCONFIG_NLS_ISO8859_5=y
# CONFIG_NLS_ISO8859_6 is not setCONFIG_NLS_ISO8859_7=yCONFIG_NLS_ISO8859_9=yCONFIG_NLS_ISO8859_13=yCONFIG_NLS_ISO8859_14=yCONFIG_NLS_ISO8859_15=y
# CONFIG_NLS_KOI8_R is not setCONFIG_NLS_KOI8_U=yCONFIG_NLS_UTF8=yCONFIG_DLM=yCONFIG_DLM_DEBUG=y
#
# Kernel hacking
#CONFIG_TRACE_IRQFLAGS_SUPPORT=yCONFIG_PRINTK_TIME=yCONFIG_ENABLE_WARN_DEPRECATED=yCONFIG_ENABLE_MUST_CHECK=yCONFIG_FRAME_WARN=2048CONFIG_MAGIC_SYSRQ=yCONFIG_UNUSED_SYMBOLS=yCONFIG_DEBUG_FS=yCONFIG_HEADERS_CHECK=y
# CONFIG_DEBUG_KERNEL is not setCONFIG_SLUB_DEBUG_ON=yCONFIG_SLUB_STATS=yCONFIG_STACKTRACE=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL is not set
# CONFIG_LATENCYTOP is not setCONFIG_SYSCTL_SYSCALL_CHECK=yCONFIG_NOP_TRACER=yCONFIG_HAVE_FTRACE=yCONFIG_HAVE_DYNAMIC_FTRACE=yCONFIG_HAVE_FTRACE_MCOUNT_RECORD=yCONFIG_RING_BUFFER=yCONFIG_TRACING=yCONFIG_SYSPROF_TRACER=yCONFIG_PROVIDE_OHCI1394_DMA_INIT=yCONFIG_FIREWIRE_OHCI_REMOTE_DMA=yCONFIG_BUILD_DOCSRC=y
# CONFIG_SAMPLES is not setCONFIG_HAVE_ARCH_KGDB=yCONFIG_STRICT_DEVMEM=yCONFIG_X86_VERBOSE_BOOTUP=yCONFIG_EARLY_PRINTK=yCONFIG_EARLY_PRINTK_DBGP=yCONFIG_IO_DELAY_TYPE_0X80=0CONFIG_IO_DELAY_TYPE_0XED=1CONFIG_IO_DELAY_TYPE_UDELAY=2CONFIG_IO_DELAY_TYPE_NONE=3CONFIG_IO_DELAY_0X80=y
# CONFIG_IO_DELAY_0XED is not set
# CONFIG_IO_DELAY_UDELAY is not set
# CONFIG_IO_DELAY_NONE is not setCONFIG_DEFAULT_IO_DELAY_TYPE=0
# CONFIG_OPTIMIZE_INLINING is not set
#
# Security options
#CONFIG_KEYS=yCONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY=yCONFIG_SECURITY_NETWORK=y
# CONFIG_SECURITY_NETWORK_XFRM is not set CONFIG_SECURITY_FILE_CAPABILITIES=y CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0 CONFIG_SECURITY_SELINUX=y
# CONFIG_SECURITY_SELINUX_BOOTPARAM is not set # CONFIG_SECURITY_SELINUX_DISABLE is not set CONFIG_SECURITY_SELINUX_DEVELOP=y CONFIG_SECURITY_SELINUX_AVC_STATS=y CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX=y CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE=19 CONFIG_CRYPTO=y
#
# Crypto core or helper
#CONFIG_CRYPTO_ALGAPI=yCONFIG_CRYPTO_AEAD=yCONFIG_CRYPTO_BLKCIPHER=yCONFIG_CRYPTO_HASH=yCONFIG_CRYPTO_MANAGER=yCONFIG_CRYPTO_GF128MUL=y
# CONFIG_CRYPTO_NULL is not setCONFIG_CRYPTO_CRYPTD=yCONFIG_CRYPTO_AUTHENC=y
#
# Authenticated Encryption with Associated Data
#
# CONFIG_CRYPTO_CCM is not setCONFIG_CRYPTO_GCM=yCONFIG_CRYPTO_SEQIV=y
#
# Block modes
#CONFIG_CRYPTO_CBC=yCONFIG_CRYPTO_CTR=yCONFIG_CRYPTO_CTS=yCONFIG_CRYPTO_ECB=yCONFIG_CRYPTO_LRW=yCONFIG_CRYPTO_PCBC=yCONFIG_CRYPTO_XTS=y
#
# Hash modes
#CONFIG_CRYPTO_HMAC=yCONFIG_CRYPTO_XCBC=y
#
# Digest
#CONFIG_CRYPTO_CRC32C=yCONFIG_CRYPTO_MD4=yCONFIG_CRYPTO_MD5=yCONFIG_CRYPTO_MICHAEL_MIC=y
# CONFIG_CRYPTO_RMD128 is not setCONFIG_CRYPTO_RMD160=yCONFIG_CRYPTO_RMD256=y
# CONFIG_CRYPTO_RMD320 is not setCONFIG_CRYPTO_SHA1=y
# CONFIG_CRYPTO_SHA256 is not setCONFIG_CRYPTO_SHA512=yCONFIG_CRYPTO_TGR192=y
# CONFIG_CRYPTO_WP512 is not set
#
# Ciphers
#CONFIG_CRYPTO_AES=yCONFIG_CRYPTO_AES_X86_64=yCONFIG_CRYPTO_ANUBIS=yCONFIG_CRYPTO_ARC4=yCONFIG_CRYPTO_BLOWFISH=yCONFIG_CRYPTO_CAMELLIA=yCONFIG_CRYPTO_CAST5=yCONFIG_CRYPTO_CAST6=yCONFIG_CRYPTO_DES=yCONFIG_CRYPTO_FCRYPT=yCONFIG_CRYPTO_KHAZAD=yCONFIG_CRYPTO_SALSA20=yCONFIG_CRYPTO_SALSA20_X86_64=yCONFIG_CRYPTO_SEED=yCONFIG_CRYPTO_SERPENT=y
# CONFIG_CRYPTO_TEA is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_TWOFISH_X86_64 is not set
#
# Compression
#CONFIG_CRYPTO_DEFLATE=yCONFIG_CRYPTO_LZO=yCONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not setCONFIG_HAVE_KVM=yCONFIG_VIRTUALIZATION=yCONFIG_KVM=yCONFIG_KVM_INTEL=yCONFIG_KVM_AMD=yCONFIG_VIRTIO=yCONFIG_VIRTIO_RING=y
# CONFIG_VIRTIO_PCI is not setCONFIG_VIRTIO_BALLOON=y
#
# Library routines
#CONFIG_BITREVERSE=yCONFIG_GENERIC_FIND_FIRST_BIT=yCONFIG_GENERIC_FIND_NEXT_BIT=yCONFIG_CRC_CCITT=yCONFIG_CRC16=yCONFIG_CRC_T10DIF=yCONFIG_CRC_ITU_T=yCONFIG_CRC32=y
# CONFIG_CRC7 is not setCONFIG_LIBCRC32C=yCONFIG_ZLIB_INFLATE=yCONFIG_ZLIB_DEFLATE=yCONFIG_LZO_COMPRESS=yCONFIG_LZO_DECOMPRESS=yCONFIG_PLIST=yCONFIG_HAS_IOMEM=yCONFIG_HAS_IOPORT=yCONFIG_HAS_DMA=yCONFIG_CHECK_SIGNATURE=yCONFIG_FORCE_SUCCESSFUL_BUILD=yCONFIG_FORCE_MINIMAL_CONFIG=yCONFIG_FORCE_MINIMAL_CONFIG_64=yCONFIG_FORCE_MINIMAL_CONFIG_PHYS=y
Steven Rostedt
maintainerRe: [boot crash] Re: [PATCH] ring-buffer: fix build error
Quoted 9 lines · Ingo Molnar
Quoted 6 lines · Steven Rostedt
Quoted 3 lines · Ingo Molnar
* Ingo Molnar <[email protected]> wrote:
full serial log and config attached. I'm excluding these latest commits
Quoted 7 lines
Quoted 1 line
-ENOATTACHMENTattached.
You can get the broken tree by doing this in tip/master:
git-merge tip/tracing/ring-buffer
I've just checked-out tip/tracing/ring-buffer. That tree is still broken too, right? Or do I need to merge it to get the broken version?
-- Steve
Re: [boot crash] Re: [PATCH] ring-buffer: fix build error
Quoted 14 lines · Steven Rostedt
Quoted 11 lines · Ingo Molnar
Quoted 7 lines · Steven Rostedt
Quoted 3 lines · Ingo Molnar
* Ingo Molnar <[email protected]> wrote:
full serial log and config attached. I'm excluding these latest commits
-ENOATTACHMENT
Quoted 8 lines
Quoted 5 lines
attached.
You can get the broken tree by doing this in tip/master:
git-merge tip/tracing/ring-buffer
I've just checked-out tip/tracing/ring-buffer. That tree is still broken too, right? Or do I need to merge it to get the broken version?
yes, that's very likely broken too in a standalone way as well - but to get the exact tree i tested i'd suggest:
git checkout tip/master
git merge tip/tracing/ring-buffer
Ingo
Steven Rostedt
maintainerPATCH 1/1 ring_buffer: map to cpu not page
In reply to Ingo MolnarMy original patch had a compile bug when NUMA was configured. I referenced cpu when it should have been cpu_buffer->cpu.
Ingo quickly fixed this bug by replacing cpu with 'i' because that was the loop counter. Unfortunately, the 'i' was the counter of pages, not CPUs. This caused a crash when the number of pages allocated for the buffers exceeded the number of pages, which would usually be the case.
--- kernel/trace/ring_buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/trace/ring_buffer.c +1 -1
@@ -232,7 +232,7 @@ static int rb_allocate_pages(struct ringfor (i =0 ; i < nr_pages; i++) { page =kzalloc_node (ALIGN (sizeof (*page),cache_line_size ()), -GFP_KERNEL ,cpu_to_node (i)); +GFP_KERNEL ,cpu_to_node (cpu_buffer->cpu));if (!page) goto free_pages;list_add (&page->list, &pages);
Steven Rostedt
maintainerRe: [PATCH] ring_buffer: map to cpu not page
Quoted 8 lines · Steven Rostedt
My original patch had a compile bug when NUMA was configured. I referenced cpu when it should have been
cpu_buffer->cpu.Ingo quickly fixed this bug by replacing cpu with 'i' because that was the loop counter. Unfortunately, the 'i' was the counter of pages, not CPUs. This caused a crash when the number of pages allocated for the buffers exceeded the number of pages, which would usually
That should have been:
"when the number of pages allocated for the buffers exceeded the number
of cpus".
Quoted 2 lines
be the case.
-- Steve
PATCH 1/1 x86 Topology cpu_to_node parameter check
In reply to Steven RostedtDeclare NUMA-less cpu_to_node with a check that the cpu parameter exists so people without NUMA test configs (namely Steven Rostedt and myself who ran into this error both in the same day with different implementations) stop doing this trivial mistake.
--- include/asm-x86/topology.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
include/asm-x86/topology.h +3 -3
@@ -182,9 +182,9 @@ extern int __node_distance(int, int);#else /* !CONFIG_NUMA */ -#define numa_node_id () 0 -#define cpu_to_node (cpu) 0 -#define early_cpu_to_node (cpu) 0 +#define numa_node_id () 0 +#define cpu_to_node (cpu) ((void)(cpu),0) +#define early_cpu_to_node (cpu) cpu_to_node(cpu)static inline const cpumask_t *_node_to_cpumask_ptr (int node) {
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Steven Rostedt
maintainerRe: [PATCH] x86 Topology cpu_to_node parameter check
Quoted 9 lines · Mathieu Desnoyers
--- include/asm-x86/topology.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)Index:
linux-2.6-lttng/include/asm-x86/topology.h
===================================================================
include/asm-x86/topology.h extern int __node_distance(int, int); · line 187
Quoted 9 lines
include/asm-x86/topology.h +3
-3@@ -182,9 +182,9 @@ extern int __node_distance(int, int);#else /* !CONFIG_NUMA */ -#define numa_node_id () 0 -#define cpu_to_node (cpu) 0 -#define early_cpu_to_node (cpu) 0 +#define numa_node_id () 0 +#define cpu_to_node (cpu) ((void)(cpu),0) +#define early_cpu_to_node (cpu) cpu_to_node(cpu)
Actually the proper way would be to have:
static inline int cpu_to_node(int cpu)
{
return 0;
}static inline int early_cpu_to_node(int cpu)
{
return 0;
}This way you also get typechecks.
-- Steve
Quoted 7 lines
include/asm-x86/topology.h +0
-1static inline const cpumask_t *_node_to_cpumask_ptr (int node) { --Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Re: [PATCH] x86 Topology cpu_to_node parameter check
Quoted 29 lines · * Steven Rostedt ([email protected]) wrote:
Quoted 9 lines · Mathieu Desnoyers
--- include/asm-x86/topology.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)Index:
linux-2.6-lttng/include/asm-x86/topology.h
===================================================================include/asm-x86/topology.h extern int __node_distance(int, int); · line 187
Quoted 9 lines
include/asm-x86/topology.h +3
-3@@ -182,9 +182,9 @@ extern int __node_distance(int, int);#else /* !CONFIG_NUMA */ -#define numa_node_id () 0 -#define cpu_to_node (cpu) 0 -#define early_cpu_to_node (cpu) 0 +#define numa_node_id () 0 +#define cpu_to_node (cpu) ((void)(cpu),0) +#define early_cpu_to_node (cpu) cpu_to_node(cpu)Actually the proper way would be to have:
static inline int
cpu_to_node(int cpu){ return 0; }
Quoted 7 lines
static inline int
early_cpu_to_node(int cpu){ return 0; }This way you also get typechecks.
That's how I did it first, but then I looked at asm-generic/topology.h and have seen it uses #defines. Should we change them too ?
Mathieu
Quoted 10 lines
-- Steve
Quoted 7 lines
include/asm-x86/topology.h +0
-1static inline const cpumask_t *_node_to_cpumask_ptr (int node) { --Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Steven Rostedt
maintainerRe: [PATCH] x86 Topology cpu_to_node parameter check
Quoted 4 lines · Mathieu Desnoyers
That's how I did it first, but then I looked at
asm-generic/topology.hand have seen it uses #defines. Should we change them too ?
The old way of doing this is with defines. But all new code should be static inline functions when feasible. This way we can get typechecking on the parameters even when the configuration is disabled.
Even if the rest of the file uses defines, the new code should be static inlines. Eventually, even the old defines will be converted.
-- Steve
Re: [PATCH] x86 Topology cpu_to_node parameter check
Quoted 7 lines · * Steven Rostedt ([email protected]) wrote:
Quoted 4 lines · Mathieu Desnoyers
That's how I did it first, but then I looked at
asm-generic/topology.hand have seen it uses #defines. Should we change them too ?
Quoted 9 lines
The old way of doing this is with defines. But all new code should be static inline functions when feasible. This way we can get typechecking on the parameters even when the configuration is disabled.
Even if the rest of the file uses defines, the new code should be static inlines. Eventually, even the old defines will be converted.
-- Steve
Argh, I think topology.h is utterly broken :-(
Have you noticed the subtile interaction between the
include/asm-x86/topology.h :
#define numa_node_id() 0 #define cpu_to_node(cpu) 0 #define early_cpu_to_node(cpu) 0
...
#include <asm-generic/topology.h>
andinclude/asm-generic/topology.h :
#ifndef cpu_to_node
#define cpu_to_node(cpu) ((void)(cpu),0)
#endif
If any architecture decide for some reason to use a static inline rather than a define, as currently done with node_to_first_cpu :
include/asm-x86/topology.h :
static inline int node_to_first_cpu(int node)
{
return first_cpu(cpu_online_map);
}...
#include <asm-generic/topology.h>
include/asm-generic/topology.h :
#ifndef node_to_first_cpu
#define node_to_first_cpu(node) ((void)(node),0)
#endif
(which will override the static inline !)
It results in an override of the arch-specific version. Nice eh ?
Mathieu
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Steven Rostedt
maintainerRe: [PATCH] x86 Topology cpu_to_node parameter check
Quoted 48 lines · Mathieu Desnoyers
Quoted 7 lines · * Steven Rostedt ([email protected]) wrote:
Quoted 4 lines · Mathieu Desnoyers
That's how I did it first, but then I looked at
asm-generic/topology.hand have seen it uses #defines. Should we change them too ?Quoted 9 lines
The old way of doing this is with defines. But all new code should be static inline functions when feasible. This way we can get typechecking on the parameters even when the configuration is disabled.
Even if the rest of the file uses defines, the new code should be static inlines. Eventually, even the old defines will be converted.
-- Steve
Argh, I think
topology.his utterly broken :-(Have you noticed the subtile interaction between the
include/asm-x86/topology.h:#define numa_node_id() 0 #define cpu_to_node(cpu) 0 #define early_cpu_to_node(cpu) 0...
#include <asm-generic/topology.h>and
include/asm-generic/topology.h:
#ifndefcpu_to_node
#definecpu_to_node(cpu)((void)(cpu),0)
#endifIf any architecture decide for some reason to use a static inline rather than a define, as currently done with
node_to_first_cpu:
include/asm-x86/topology.h:
static inline intnode_to_first_cpu(int node){ return first_cpu(cpu_online_map); }...
#include <asm-generic/topology.h>
Quoted 8 lines
include/asm-generic/topology.h:
#ifndefnode_to_first_cpu
#definenode_to_first_cpu(node)((void)(node),0)
#endif(which will override the static inline !)
It results in an override of the arch-specific version. Nice eh ?
Seems that they expect cpu_to_node to be a macro if NUMA is not configured.
Actually, since the asm-generic/topology.h does have the cpu shown (although not in inline format), the solution here is to simply remove the
#define cpu_to_node() 0
And we can still make the early_cpu_to_node a static inline since it is not referenced in the generic code.
-- Steve
PATCH 1/1 topology.h define mess fix
Quoted 7 lines · * Steven Rostedt ([email protected]) wrote:
Seems that they expect
cpu_to_nodeto be a macro if NUMA is not configured.Actually, since the
asm-generic/topology.hdoes have the cpu shown (although not in inline format), the solution here is to simply remove the
Quoted 7 lines
#define
cpu_to_node()0And we can still make the
early_cpu_to_nodea static inline since it is not referenced in the generic code.-- Steve
Or we take a deep breath and clean this up ?
Ingo, I build tested this on x86_64 (with and without NUMA), x86_32, powerpc, arm and mips. I applies to both -tip and 2.6.27-rc8. Could it be pulled into -tip for further testing ?
Note that checkpatch.pl spills a warning telling me to modify include/asm-*/ files (unexisting in my tree) rather than arch/*/include/asm/. Any idea why ?
Thanks,
Mathieu
topology.h define mess fix
Original goal : Declare NUMA-less cpu_to_node with a check that the cpu parameter exists so people without NUMA test configs (namely Steven Rostedt and myself who ran into this error both in the same day with different implementations) stop doing this trivial mistake.
End result :
Argh, I think topology.h is utterly broken :-(
Have you noticed the subtile interaction between the
include/asm-x86/topology.h :
#define numa_node_id() 0 #define cpu_to_node(cpu) 0 #define early_cpu_to_node(cpu) 0
...
#include <asm-generic/topology.h>
andinclude/asm-generic/topology.h :
#ifndef cpu_to_node
#define cpu_to_node(cpu) ((void)(cpu),0)
#endif
If any architecture decide for some reason to use a static inline rather than a define, as currently done with node_to_first_cpu :
include/asm-x86/topology.h :
static inline int node_to_first_cpu(int node)
{
return first_cpu(cpu_online_map);
}...
#include <asm-generic/topology.h>
include/asm-generic/topology.h :
#ifndef node_to_first_cpu
#define node_to_first_cpu(node) ((void)(node),0)
#endif
(which will override the static inline !)
It results in an override of the arch-specific version. Nice eh ?
This patch fixes this issue by declaring static inlines in asm-generic/topology.h and by requiring a _complete_ override of the topology functions when an architecture needs to override them. An architecture overriding the topology functions should not include asm-generic/topology.h anymore.
- alpha needs careful checking, as it did not implement parent_node nor node_to_first_cpu previously.
- Major cross-architecture built test is required.
--- arch/alpha/include/asm/topology.h | 38 +++++++++++++++++++ arch/ia64/include/asm/topology.h | 16 ++++---- arch/powerpc/include/asm/topology.h | 12 +++++- arch/sh/include/asm/topology.h | 11 ----- include/asm-generic/topology.h | 70 ++++++++++++++++++++---------------- include/asm-x86/topology.h | 66 +++++++++++++++++++++++++-------- 6 files changed, 144 insertions(+), 69 deletions(-)
include/asm-x86/topology.h +49 -17
@@ -38,6 +38,8 @@/* Node not present */ #define NUMA_NO_NODE (-1) +struct pci_bus ; +#ifdef CONFIG_NUMA #include <linux/cpumask.h> #include <asm/mpspec.h>
@@ -116,7 +118,6 @@ static inline cpumask_t node_to_cpumask(#endif /* !CONFIG_DEBUG_PER_CPU_MAPS */ -/* Replace default node_to_cpumask_ptr with optimized version */ #define node_to_cpumask_ptr (v, node) \ const cpumask_t *v = _node_to_cpumask_ptr(node)
@@ -129,8 +130,14 @@ static inline cpumask_t node_to_cpumask(* Returns the number of the node containing Node 'node'. This * architecture is flat, so it is a pretty simple function! */ -#define parent_node (node) (node) +static inline int parent_node (int node) +{ +return node; +} +/* +* Leave those as defines so we don't have to include linux/pci.h. +*/ #define pcibus_to_node (bus) __pcibus_to_node(bus)#define pcibus_to_cpumask (bus) __pcibus_to_cpumask(bus)
@@ -180,42 +187,67 @@ extern int __node_distance(int, int);#define node_distance (a, b) __node_distance(a, b)#endif +/* Returns the number of the first CPU on Node 'node'. */ +static inline int node_to_first_cpu (int node) +{ +node_to_cpumask_ptr (mask, node); +return first_cpu (*mask); +} +#else /* !CONFIG_NUMA */ -#define numa_node_id () 0 -#define cpu_to_node (cpu) 0 -#define early_cpu_to_node (cpu) 0 +static inline int numa_node_id (void ) +{ +return 0 ; +} -static inline const cpumask_t *_node_to_cpumask_ptr (int node) +/* +* We override asm-generic/topology.h. +*/ +static inline int cpu_to_node (int cpu) { -return &cpu_online_map; +return 0 ; } + +static inline int parent_node (int node) +{ +return 0 ; +} +static inline cpumask_t node_to_cpumask (int node) {return cpu_online_map; } +static inline int node_to_first_cpu (int node) {return first_cpu (cpu_online_map); } +static inline int pcibus_to_node (struct pci_bus *bus) +{ +return -1 ; +} + +static inline cpumask_t pcibus_to_cpumask (struct pci_bus *bus) +{ +return pcibus_to_node (bus) ==-1 ? +CPU_MASK_ALL : +node_to_cpumask (pcibus_to_node (bus)); +} + +static inline const cpumask_t *_node_to_cpumask_ptr (int node) +{ +return &cpu_online_map; +} +/* Replace default node_to_cpumask_ptr with optimized version */ #define node_to_cpumask_ptr (v, node) \ const cpumask_t *v = _node_to_cpumask_ptr(node)#define node_to_cpumask_ptr_next (v, node) \ v = _node_to_cpumask_ptr(node) -#endif - -#include <asm-generic/topology.h> -#ifdef CONFIG_NUMA -/* Returns the number of the first CPU on Node 'node'. */ -static inline int node_to_first_cpu (int node) -{ -node_to_cpumask_ptr (mask, node); -return first_cpu (*mask); -}#endif extern cpumask_t cpu_coregroup_map (int cpu);
arch/alpha/include/asm/topology.h +37 -1
@@ -41,7 +41,43 @@ static inline cpumask_t node_to_cpumask(#define pcibus_to_cpumask (bus) (cpu_online_map) +struct pci_bus ; + +static inline int parent_node (int node) +{ +return node; +} + +static inline int pcibus_to_node (struct pci_bus *bus) +{ +return -1 ; +} + +static inline cpumask_t pcibus_to_cpumask (struct pci_bus *bus) +{ +return pcibus_to_node (bus) ==-1 ? +CPU_MASK_ALL : +node_to_cpumask (pcibus_to_node (bus)); +} + +/* returns pointer to cpumask for specified node */ +#define node_to_cpumask_ptr (v, node) \ + cpumask_t _##v = node_to_cpumask(node); \ + const cpumask_t *v = &_##v + +#define node_to_cpumask_ptr_next (v, node) \ + _##v = node_to_cpumask(node) + +static inline int node_to_first_cpu (int node) +{ +node_to_cpumask_ptr (mask, node); +return first_cpu (*mask); +} + +#else + +#include <asm-generic/topology.h> +#endif /* !CONFIG_NUMA */ -# include <asm-generic/topology.h> #endif /* _ASM_ALPHA_TOPOLOGY_H */
arch/ia64/include/asm/topology.h +9 -7
@@ -104,6 +104,15 @@ void build_cpu_to_node_map(void); .nr_balance_failed = 0, \ } +#define pcibus_to_cpumask (bus) (pcibus_to_node(bus) == -1 ? \ + CPU_MASK_ALL : \ + node_to_cpumask(pcibus_to_node(bus)) \ + ) + +#else + +#include <asm-generic/topology.h> +#endif /* CONFIG_NUMA */ #ifdef CONFIG_SMP
@@ -116,11 +125,4 @@ void build_cpu_to_node_map(void);extern void arch_fix_phys_package_id (int num,u32 slot); -#define pcibus_to_cpumask (bus) (pcibus_to_node(bus) == -1 ? \ - CPU_MASK_ALL : \ - node_to_cpumask(pcibus_to_node(bus)) \ - ) - -#include <asm-generic/topology.h> -#endif /* _ASM_IA64_TOPOLOGY_H */
arch/powerpc/include/asm/topology.h +10 -2
@@ -77,6 +77,14 @@ extern void __init dump_numa_cpu_topologextern int sysfs_add_device_to_node (struct sys_device *dev,int nid);extern void sysfs_remove_device_from_node (struct sys_device *dev,int nid); +/* returns pointer to cpumask for specified node */ +#define node_to_cpumask_ptr (v, node) \ + cpumask_t _##v = node_to_cpumask(node); \ + const cpumask_t *v = &_##v + +#define node_to_cpumask_ptr_next (v, node) \ + _##v = node_to_cpumask(node) +#else static inline int of_node_to_nid (struct device_node *device)
@@ -96,10 +104,10 @@ static inline void sysfs_remove_device_f { } -#endif /* CONFIG_NUMA */ -#include <asm-generic/topology.h> +#endif /* CONFIG_NUMA */ +#ifdef CONFIG_SMP #include <asm/cputable.h> #define smt_capable () (cpu_has_feature(CPU_FTR_SMT))
arch/sh/include/asm/topology.h +0 -11
@@ -29,17 +29,6 @@ .nr_balance_failed = 0, \ } -#define cpu_to_node (cpu) ((void)(cpu),0) -#define parent_node (node) ((void)(node),0) - -#define node_to_cpumask (node) ((void)node, cpu_online_map) -#define node_to_first_cpu (node) ((void)(node),0) - -#define pcibus_to_node (bus) ((void)(bus), -1) -#define pcibus_to_cpumask (bus) (pcibus_to_node(bus) == -1 ? \ - CPU_MASK_ALL : \ - node_to_cpumask(pcibus_to_node(bus)) \ - )#endif #include <asm-generic/topology.h>
include/asm-generic/topology.h +39 -31
83 lines not on this page · raw message
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
RE: [PATCH] topology.h define mess fix
Quoted 1 line
- Major cross-architecture built test is required.
Some problems on ia64. With defconfig build (which has CONFIG_NUMA=y) I see this:
kernel/sched.c: In function 'find_next_best_node':kernel/sched.c:6920: error: implicit declaration of function 'node_to_cpumask_ptr' kernel/sched.c:6920: error: '__tmp__' undeclared (first use in this function) kernel/sched.c:6920: error: (Each undeclared identifier is reported only once kernel/sched.c:6920: error: for each function it appears in.) kernel/sched.c: In function 'sched_domain_node_span':kernel/sched.c:6952: error: 'nodemask' undeclared (first use in this function) kernel/sched.c:6953: warning: ISO C90 forbids mixed declarations and code kernel/sched.c:6964: error: implicit declaration of function 'node_to_cpumask_ptr_next' kernel/sched.c: In function '__build_sched_domains':kernel/sched.c:7510: error: 'pnodemask' undeclared (first use in this function)
On an "allnoconfig" build (which curiously also has CONFIG_NUMA=y :-) I see
mm/page_alloc.c: In function 'find_next_best_node':mm/page_alloc.c:2086: error: implicit declaration of function 'node_to_cpumask_ptr' mm/page_alloc.c:2086: error: 'tmp' undeclared (first use in this function) mm/page_alloc.c:2086: error: (Each undeclared identifier is reported only once mm/page_alloc.c:2086: error: for each function it appears in.) mm/page_alloc.c:2107: error: implicit declaration of function 'node_to_cpumask_ptr_next'
There are most probably more errors ... but this is where the build stopped.
-Tony
PATCH 1/1 topology.h define mess fix v2
Quoted 5 lines · * Luck, Tony ([email protected]) wrote:
Quoted 1 line
- Major cross-architecture built test is required.
Some problems on ia64. With defconfig build (which has
CONFIG_NUMA=y) I see this:
[...]
Ah, I did not select config "generic" for ia64, and thus did not get CONFIG_NUMA. Here is a v2 which fixes this.
Thanks for testing this.
Mathieu
topology.h define mess fix v2
Update : build fix for ia64 CONFIG_NUMA.
Original goal : Declare NUMA-less cpu_to_node with a check that the cpu parameter exists so people without NUMA test configs (namely Steven Rostedt and myself who ran into this error both in the same day with different implementations) stop doing this trivial mistake.
End result :
Argh, I think topology.h is utterly broken :-(
Have you noticed the subtile interaction between the
include/asm-x86/topology.h :
#define numa_node_id() 0 #define cpu_to_node(cpu) 0 #define early_cpu_to_node(cpu) 0
...
#include <asm-generic/topology.h>
andinclude/asm-generic/topology.h :
#ifndef cpu_to_node
#define cpu_to_node(cpu) ((void)(cpu),0)
#endif
If any architecture decide for some reason to use a static inline rather than a define, as currently done with node_to_first_cpu :
include/asm-x86/topology.h :
static inline int node_to_first_cpu(int node)
{
return first_cpu(cpu_online_map);
}...
#include <asm-generic/topology.h>
include/asm-generic/topology.h :
#ifndef node_to_first_cpu
#define node_to_first_cpu(node) ((void)(node),0)
#endif
(which will override the static inline !)
It results in an override of the arch-specific version. Nice eh ?
This patch fixes this issue by declaring static inlines in asm-generic/topology.h and by requiring a _complete_ override of the topology functions when an architecture needs to override them. An architecture overriding the topology functions should not include asm-generic/topology.h anymore.
- alpha needs careful checking, as it did not implement parent_node nor node_to_first_cpu previously.
- Major cross-architecture built test is required.
--- arch/alpha/include/asm/topology.h | 38 +++++++++++++++++++ arch/ia64/include/asm/topology.h | 24 ++++++++---- arch/powerpc/include/asm/topology.h | 12 +++++- arch/sh/include/asm/topology.h | 11 ----- include/asm-generic/topology.h | 70 ++++++++++++++++++++---------------- include/asm-x86/topology.h | 66 +++++++++++++++++++++++++-------- 6 files changed, 152 insertions(+), 69 deletions(-)
include/asm-x86/topology.h +49 -17
@@ -38,6 +38,8 @@/* Node not present */ #define NUMA_NO_NODE (-1) +struct pci_bus ; +#ifdef CONFIG_NUMA #include <linux/cpumask.h> #include <asm/mpspec.h>
@@ -116,7 +118,6 @@ static inline cpumask_t node_to_cpumask(#endif /* !CONFIG_DEBUG_PER_CPU_MAPS */ -/* Replace default node_to_cpumask_ptr with optimized version */ #define node_to_cpumask_ptr (v, node) \ const cpumask_t *v = _node_to_cpumask_ptr(node)
@@ -129,8 +130,14 @@ static inline cpumask_t node_to_cpumask(* Returns the number of the node containing Node 'node'. This * architecture is flat, so it is a pretty simple function! */ -#define parent_node (node) (node) +static inline int parent_node (int node) +{ +return node; +} +/* +* Leave those as defines so we don't have to include linux/pci.h. +*/ #define pcibus_to_node (bus) __pcibus_to_node(bus)#define pcibus_to_cpumask (bus) __pcibus_to_cpumask(bus)
@@ -180,42 +187,67 @@ extern int __node_distance(int, int);#define node_distance (a, b) __node_distance(a, b)#endif +/* Returns the number of the first CPU on Node 'node'. */ +static inline int node_to_first_cpu (int node) +{ +node_to_cpumask_ptr (mask, node); +return first_cpu (*mask); +} +#else /* !CONFIG_NUMA */ -#define numa_node_id () 0 -#define cpu_to_node (cpu) 0 -#define early_cpu_to_node (cpu) 0 +static inline int numa_node_id (void ) +{ +return 0 ; +} -static inline const cpumask_t *_node_to_cpumask_ptr (int node) +/* +* We override asm-generic/topology.h. +*/ +static inline int cpu_to_node (int cpu) { -return &cpu_online_map; +return 0 ; } + +static inline int parent_node (int node) +{ +return 0 ; +} +static inline cpumask_t node_to_cpumask (int node) {return cpu_online_map; } +static inline int node_to_first_cpu (int node) {return first_cpu (cpu_online_map); } +static inline int pcibus_to_node (struct pci_bus *bus) +{ +return -1 ; +} + +static inline cpumask_t pcibus_to_cpumask (struct pci_bus *bus) +{ +return pcibus_to_node (bus) ==-1 ? +CPU_MASK_ALL : +node_to_cpumask (pcibus_to_node (bus)); +} + +static inline const cpumask_t *_node_to_cpumask_ptr (int node) +{ +return &cpu_online_map; +} +/* Replace default node_to_cpumask_ptr with optimized version */ #define node_to_cpumask_ptr (v, node) \ const cpumask_t *v = _node_to_cpumask_ptr(node)#define node_to_cpumask_ptr_next (v, node) \ v = _node_to_cpumask_ptr(node) -#endif - -#include <asm-generic/topology.h> -#ifdef CONFIG_NUMA -/* Returns the number of the first CPU on Node 'node'. */ -static inline int node_to_first_cpu (int node) -{ -node_to_cpumask_ptr (mask, node); -return first_cpu (*mask); -}#endif extern cpumask_t cpu_coregroup_map (int cpu);
arch/alpha/include/asm/topology.h +37 -1
@@ -41,7 +41,43 @@ static inline cpumask_t node_to_cpumask(#define pcibus_to_cpumask (bus) (cpu_online_map) +struct pci_bus ; + +static inline int parent_node (int node) +{ +return node; +} + +static inline int pcibus_to_node (struct pci_bus *bus) +{ +return -1 ; +} + +static inline cpumask_t pcibus_to_cpumask (struct pci_bus *bus) +{ +return pcibus_to_node (bus) ==-1 ? +CPU_MASK_ALL : +node_to_cpumask (pcibus_to_node (bus)); +} + +/* returns pointer to cpumask for specified node */ +#define node_to_cpumask_ptr (v, node) \ + cpumask_t _##v = node_to_cpumask(node); \ + const cpumask_t *v = &_##v + +#define node_to_cpumask_ptr_next (v, node) \ + _##v = node_to_cpumask(node) + +static inline int node_to_first_cpu (int node) +{ +node_to_cpumask_ptr (mask, node); +return first_cpu (*mask); +} + +#else + +#include <asm-generic/topology.h> +#endif /* !CONFIG_NUMA */ -# include <asm-generic/topology.h> #endif /* _ASM_ALPHA_TOPOLOGY_H */
arch/ia64/include/asm/topology.h +17 -7
@@ -104,6 +104,23 @@ void build_cpu_to_node_map(void); .nr_balance_failed = 0, \ } +#define pcibus_to_cpumask (bus) (pcibus_to_node(bus) == -1 ? \ + CPU_MASK_ALL : \ + node_to_cpumask(pcibus_to_node(bus)) \ + ) + +/* returns pointer to cpumask for specified node */ +#define node_to_cpumask_ptr (v, node) \ + cpumask_t _##v = node_to_cpumask(node); \ + const cpumask_t *v = &_##v + +#define node_to_cpumask_ptr_next (v, node) \ + _##v = node_to_cpumask(node) + +#else + +#include <asm-generic/topology.h> +#endif /* CONFIG_NUMA */ #ifdef CONFIG_SMP
@@ -116,11 +133,4 @@ void build_cpu_to_node_map(void);extern void arch_fix_phys_package_id (int num,u32 slot); -#define pcibus_to_cpumask (bus) (pcibus_to_node(bus) == -1 ? \ - CPU_MASK_ALL : \ - node_to_cpumask(pcibus_to_node(bus)) \ - ) - -#include <asm-generic/topology.h> -#endif /* _ASM_IA64_TOPOLOGY_H */
arch/powerpc/include/asm/topology.h +10 -2
@@ -77,6 +77,14 @@ extern void __init dump_numa_cpu_topologextern int sysfs_add_device_to_node (struct sys_device *dev,int nid);extern void sysfs_remove_device_from_node (struct sys_device *dev,int nid); +/* returns pointer to cpumask for specified node */ +#define node_to_cpumask_ptr (v, node) \ + cpumask_t _##v = node_to_cpumask(node); \ + const cpumask_t *v = &_##v + +#define node_to_cpumask_ptr_next (v, node) \ + _##v = node_to_cpumask(node) +#else static inline int of_node_to_nid (struct device_node *device)
@@ -96,10 +104,10 @@ static inline void sysfs_remove_device_f { } -#endif /* CONFIG_NUMA */ -#include <asm-generic/topology.h> +#endif /* CONFIG_NUMA */ +#ifdef CONFIG_SMP #include <asm/cputable.h> #define smt_capable () (cpu_has_feature(CPU_FTR_SMT))
arch/sh/include/asm/topology.h +0 -11
@@ -29,17 +29,6 @@ .nr_balance_failed = 0, \ } -#define cpu_to_node (cpu) ((void)(cpu),0) -#define parent_node (node) ((void)(node),0) - -#define node_to_cpumask (node) ((void)node, cpu_online_map) -#define node_to_first_cpu (node) ((void)(node),0) - -#define pcibus_to_node (bus) ((void)(bus), -1) -#define pcibus_to_cpumask (bus) (pcibus_to_node(bus) == -1 ? \ - CPU_MASK_ALL : \ - node_to_cpumask(pcibus_to_node(bus)) \ - )#endif #include <asm-generic/topology.h>
include/asm-generic/topology.h +39 -31
83 lines not on this page · raw message
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Ingo Molnar
AppliedRe: [PATCH] ring_buffer: map to cpu not page
In reply to Steven RostedtQuoted 10 lines · Steven Rostedt
My original patch had a compile bug when NUMA was configured. I referenced cpu when it should have been
cpu_buffer->cpu.Ingo quickly fixed this bug by replacing cpu with 'i' because that was the loop counter. Unfortunately, the 'i' was the counter of pages, not CPUs. This caused a crash when the number of pages allocated for the buffers exceeded the number of pages, which would usually be the case.
Signed-off-by Steven Rostedt <[email protected]>
kernel/trace/ring_buffer.c static int rb_allocate_pages(struct ring · line 235
Quoted 4 lines
kernel/trace/ring_buffer.c +1
-1for (i =0 ; i < nr_pages; i++) { page =kzalloc_node (ALIGN (sizeof (*page),cache_line_size ()), -GFP_KERNEL ,cpu_to_node (i)); +GFP_KERNEL ,cpu_to_node (cpu_buffer->cpu));
oh, stupid typo of the year :-)
applied to tip/tracing/ring-buffer, thanks for tracking it down! I've reactivated the topic branch for tip/master and i'm running a few tests before pushing it out for wider testing.
Ingo
Re: [PATCH] ring_buffer: allocate buffer page pointer
In reply to Ingo MolnarQuoted 36 lines · On Thu, 2 Oct 2008 10:50:30 +0200 Ingo Molnar <[email protected]> wrote:
Quoted 5 lines · Steven Rostedt
The current method of overlaying the page frame as the buffer page pointer can be very dangerous and limits our ability to do other things with a page from the buffer, like send it off to disk.
Quoted 7 lines
This patch allocates the
buffer_pageinstead of overlaying the page's page frame. The use of thebuffer_pagehas hardly changed due to this.Signed-off-by Steven Rostedt <[email protected]>--- kernel/trace/ring_buffer.c | 54 ++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 22 deletions(-)applied to tip/tracing/ftrace, with the extended changlog below - i think this commit warrants that extra mention.
Ingo
--------------->
Quoted 1 line
From
da78331b4ced2763322d732ac5ba275965853bdeMon Sep 17 00:00:00 2001From: Steven Rostedt <[email protected]>
Date: Wed, 1 Oct 2008 10:52:51 -0400
Subject: [PATCH] ftrace: type cast filter+verifierThe mmiotrace map had a bug that would typecast the entry from the trace to the wrong type. That is a known danger of C typecasts, there's absolutely zero checking done on them.
Help that problem a bit by using a GCC extension to implement a type filter that restricts the types that a trace record can be cast into, and by adding a dynamic check (in debug mode) to verify the type of the entry.
Quoted 5 lines
This patch adds a macro to assign all entries of ftrace using the type of the variable and checking the entry id. The typecasts are now done in the macro for only those types that it knows about, which should be all the types that are allowed to be read from the tracer.
I'm somewhat at a loss here because I'm unable to find any version of kernel/trace/trace.c which looks anything like the one which is being patched, but...
kernel/trace/trace.c print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) · line 1353
Quoted 7 lines
kernel/trace/trace.c +0
-1@@ -1350,7 +1350,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) }switch (entry->type) {case TRACE_FN : { -struct ftrace_entry *field = (struct ftrace_entry *)entry;
Why was this code using a cast in the first place? It should be using entry->some_field_i_dont_have_here? That was the whole point in using the anonymous union in struct trace_entry?
Re: [PATCH] ring_buffer: allocate buffer page pointer
Quoted 44 lines · Andrew Morton
Quoted 36 lines · On Thu, 2 Oct 2008 10:50:30 +0200 Ingo Molnar <[email protected]> wrote:
Quoted 5 lines · Steven Rostedt
The current method of overlaying the page frame as the buffer page pointer can be very dangerous and limits our ability to do other things with a page from the buffer, like send it off to disk.
Quoted 7 lines
This patch allocates the
buffer_pageinstead of overlaying the page's page frame. The use of thebuffer_pagehas hardly changed due to this.Signed-off-by Steven Rostedt <[email protected]>--- kernel/trace/ring_buffer.c | 54 ++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 22 deletions(-)applied to tip/tracing/ftrace, with the extended changlog below - i think this commit warrants that extra mention.
Ingo
--------------->
Quoted 1 line
From
da78331b4ced2763322d732ac5ba275965853bdeMon Sep 17 00:00:00 2001From: Steven Rostedt <[email protected]>
Date: Wed, 1 Oct 2008 10:52:51 -0400
Subject: [PATCH] ftrace: type cast filter+verifierThe mmiotrace map had a bug that would typecast the entry from the trace to the wrong type. That is a known danger of C typecasts, there's absolutely zero checking done on them.
Help that problem a bit by using a GCC extension to implement a type filter that restricts the types that a trace record can be cast into, and by adding a dynamic check (in debug mode) to verify the type of the entry.
Quoted 5 lines
This patch adds a macro to assign all entries of ftrace using the type of the variable and checking the entry id. The typecasts are now done in the macro for only those types that it knows about, which should be all the types that are allowed to be read from the tracer.
Quoted 3 lines
I'm somewhat at a loss here because I'm unable to find any version of
kernel/trace/trace.cwhich looks anything like the one which is being patched, but...
it's in tip/tracing/ring-buffer (also tip/master), but we are still working on it (i just triggered a crash with it) so i havent pushed it out into the auto-ftrace-next branch yet.
Quoted 11 lines
kernel/trace/trace.c print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) · line 1353
Quoted 7 lines
kernel/trace/trace.c +0
-1@@ -1350,7 +1350,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) }switch (entry->type) {case TRACE_FN : { -struct ftrace_entry *field = (struct ftrace_entry *)entry;Why was this code using a cast in the first place? It should be using
entry->some_field_i_dont_have_here? That was the whole point in using the anonymous union in structtrace_entry?
this whole mega-thread was about removing that union and turning the tracer into a type-opaque entity. I warned about the inevitable fragility - but with this type filter approach the risks should be substantially lower.
Ingo
Steven Rostedt
maintainerRe: [PATCH] ring_buffer: allocate buffer page pointer
In reply to Andrew MortonQuoted 10 lines · Andrew Morton
Quoted 6 lines
This patch adds a macro to assign all entries of ftrace using the type of the variable and checking the entry id. The typecasts are now done in the macro for only those types that it knows about, which should be all the types that are allowed to be read from the tracer.
I'm somewhat at a loss here because I'm unable to find any version of
kernel/trace/trace.cwhich looks anything like the one which is being patched, but...
As Ingo mentioned, you don't have this yet. And be happy that you don't ;-)
This patch is to fix the patch that did this.
Quoted 12 lines
kernel/trace/trace.c print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) · line 1353
Quoted 8 lines
kernel/trace/trace.c +0
-1@@ -1350,7 +1350,9 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) }switch (entry->type) {case TRACE_FN : { -struct ftrace_entry *field = (struct ftrace_entry *)entry;Why was this code using a cast in the first place? It should be using
entry->some_field_i_dont_have_here? That was the whole point in using the anonymous union in structtrace_entry?
Because the ring_buffer now allows for variable length entries, having a one size fits all entry is not optimal.
But because C is not the best for typecasting, we have this macro to help solve the issue. Instead of registering everything into a single union and causing small fields to be large, we have a macro you can register your type with instead.
-- Steve
Quoted 20 lines · Steven Rostedt
Quoted 6 lines · Linus Torvalds
Trace buffers are different, though. Do people realize that doing the overloading means that you never EVER can use those buffers for anything else? Do people realize that it means that
splice()and friends are out of the question?Quoted 7 lines
Quoted 1 line
Trouble is, looking at it I see no easy way out,
Quite frankly, we could just put it at the head of the page itself. Having a "whole page" for the trace data is not possible anyway, since the trace header itself will always eat 8 bytes.
And I do think it would potentially be a better model. Or at least safer.
Actually, looking at the code, there is no reason I need to keep this in the frame buffer itself. I've also encapsulated the accesses to the incrementing of the pointers so it would be trivial to try other approaches.
Quoted 8 lines
The problem we had with the big array struct is that we can want large buffers and to do that with pointers means we would need to either come up with a large allocator or use vmap.
But I just realized that I could also just make a link list of page pointers and do the exact same thing without having to worry about page frames. Again, the way I coded this up, it is quite trivial to replace the handling of the pages with other schemes.
The list_head in the page frame should be available regardless of splice() stuffs.
Steven Rostedt
maintainerQuoted 10 lines · Peter Zijlstra
Quoted 10 lines
Actually, looking at the code, there is no reason I need to keep this in the frame buffer itself. I've also encapsulated the accesses to the incrementing of the pointers so it would be trivial to try other approaches.
The problem we had with the big array struct is that we can want large buffers and to do that with pointers means we would need to either come up with a large allocator or use vmap.
Quoted 7 lines
Quoted 4 lines
But I just realized that I could also just make a link list of page pointers and do the exact same thing without having to worry about page frames. Again, the way I coded this up, it is quite trivial to replace the handling of the pages with other schemes.
The
list_headin the page frame should be available regardless ofsplice()stuffs.
Regardless, there's more info we want to store for each page than the list head. Especially when we start converting this to lockless. I rather get out of the overlaying of the page frames, its nice to save the space, but really scares the hell out of me. I can just imagine this blowing up if we redo the paging, and I dislike this transparent coupling between the tracer buffer and the pages.
-- Steve
Quoted 19 lines · Steven Rostedt
Quoted 10 lines · Peter Zijlstra
Quoted 10 lines
Actually, looking at the code, there is no reason I need to keep this in the frame buffer itself. I've also encapsulated the accesses to the incrementing of the pointers so it would be trivial to try other approaches.
The problem we had with the big array struct is that we can want large buffers and to do that with pointers means we would need to either come up with a large allocator or use vmap.
Quoted 7 lines
Quoted 4 lines
But I just realized that I could also just make a link list of page pointers and do the exact same thing without having to worry about page frames. Again, the way I coded this up, it is quite trivial to replace the handling of the pages with other schemes.
The
list_headin the page frame should be available regardless ofsplice()stuffs.
Quoted 6 lines
Regardless, there's more info we want to store for each page than the list head. Especially when we start converting this to lockless. I rather get out of the overlaying of the page frames, its nice to save the space, but really scares the hell out of me. I can just imagine this blowing up if we redo the paging, and I dislike this transparent coupling between the tracer buffer and the pages.
The problem with storing the page link information inside the page is that it doesnt transfer to another address space, so if you do indeed mmap these pages, then the link information is bogus.
Of course, in such a situation you could ignore these headers, but somehow that doesn't sound too apealing.
Steven Rostedt
maintainerQuoted 7 lines · Peter Zijlstra
The problem with storing the page link information inside the page is that it doesnt transfer to another address space, so if you do indeed mmap these pages, then the link information is bogus.
Of course, in such a situation you could ignore these headers, but somehow that doesn't sound too apealing.
No that's not what I'm proposing. I'm proposing to allocate a page_header structure for every page we alloc, and make a link list of them. In other words:
struct ring_buffer_per_cpu {
[...]
struct list_head pages;
[...]
};struct buffer_page {
[...];
void *page;
struct list_head list;
[...];
};In ring_buffer_allocate_cpu:
struct buffer_page *bpage;
struct unsigned long addr;
[...]
for every page() {
bpage = kzalloc(sizeof(*bpage), GFP_KERNEL);
addr = get_free_page();
bpage->page = (void *)addr;
list_add(&bpage->list, &cpu_buffer->pages);
}Obviously need to add the error checking, but you get the idea. Here I do not need to change any of the later logic, because we are still dealing with the buffer_page. I only need to update way to index the page which is already encapsulated in its own function.
-- Steve
Steven Rostedt
maintainerQuoted 5 lines · Steven Rostedt
In
ring_buffer_allocate_cpu:struct buffer_page *bpage; struct unsigned long addr;
Of course we would not be declaring a "struct unsigned long" ;-)
-- Steve
Em Fri, Sep 26, 2008 at 02:05:44PM -0400, Steven Rostedt escreveu:
include/linux/ring_buffer.h line 112
Quoted 10 lines
+ */
include/linux/ring_buffer.h new file +9
-0+static inline void * +ring_buffer_event_data (struct ring_buffer_event *event) +{ +BUG_ON (event->type !=RB_TYPE_DATA ); +/* If length is in len field, then array[0] has the data */ +if (event->len) +return (void *)&event->array[0 ]; +/* Otherwise length is in array[0] and array[1] has the data */ +return (void *)&event->array[1 ];
Nitpick: Why cast to void *?
And sometimes you use the rb_ prefix, in other cases you use the longer for ring_buffer_, is the ring_ namespace already used? Or can we make it use rb_ consistently to shorten the names?
- Arnaldo
Steven Rostedt
maintainerQuoted 13 lines · Arnaldo Carvalho de Melo
Em Fri, Sep 26, 2008 at 02:05:44PM -0400, Steven Rostedt escreveu:
include/linux/ring_buffer.h line 112
Quoted 10 lines
+ */
include/linux/ring_buffer.h new file +9
-0+static inline void * +ring_buffer_event_data (struct ring_buffer_event *event) +{ +BUG_ON (event->type !=RB_TYPE_DATA ); +/* If length is in len field, then array[0] has the data */ +if (event->len) +return (void *)&event->array[0 ]; +/* Otherwise length is in array[0] and array[1] has the data */ +return (void *)&event->array[1 ];Nitpick: Why cast to void *?
5 day hacking marathon, I cast everything ;-)
Quoted 4 lines
And sometimes you use the
rb_prefix, in other cases you use the longer forring_buffer_, is thering_namespace already used? Or can we make it userb_consistently to shorten the names?
I started using the rb_ because I was constantly breaking the 80 character
line limit with ring_buffer ;-) OK, for v8, I'll rename all static
internal functions to rb_ and keep the global ones ring_buffer_
Thanks,
-- Steve
Quoted 4 lines · Steven Rostedt
I started using the
rb_because I was constantly breaking the 80 character
line limit withring_buffer;-) OK, for v8, I'll rename all static
internal functions torb_and keep the global onesring_buffer_
It would probably be better to use something else than 'rb_', because that prefix is already used by the red-black trees, and exported as such (eg "rb_next()" etc).
But at least as long as it's static, it's probably not _too_ noticeable if the rest of the names don't overlap. We _do_ include <linux/rbtree.h> almost everywhere, since we use those things in the VM, in timers etc, so it comes in through pretty much all headers.
Linus
Steven Rostedt
maintainerQuoted 7 lines · Linus Torvalds
Quoted 3 lines
I started using the
rb_because I was constantly breaking the 80 character
line limit withring_buffer;-) OK, for v8, I'll rename all static
internal functions torb_and keep the global onesring_buffer_It would probably be better to use something else than '
rb_', because that prefix is already used by the red-black trees, and exported as such (eg "rb_next()" etc).
Good point.
Quoted 5 lines
But at least as long as it's static, it's probably not _too_ noticeable if the rest of the names don't overlap. We _do_ include <
linux/rbtree.h> almost everywhere, since we use those things in the VM, in timers etc, so it comes in through pretty much all headers.
Well, I just compiled it and it didn't have any name collisions, but that doesn't mean that this wont change in the future.
What would you suggest? buffer_ ? ringbuf_ ?
-- Steve
Steven Rostedt
maintainerQuoted 8 lines · Steven Rostedt
Quoted 5 lines
But at least as long as it's static, it's probably not _too_ noticeable if the rest of the names don't overlap. We _do_ include <
linux/rbtree.h> almost everywhere, since we use those things in the VM, in timers etc, so it comes in through pretty much all headers.Well, I just compiled it and it didn't have any name collisions, but that doesn't mean that this wont change in the future.
For kicks I just added #include <linux/rbtree.h> and it still passed. I don't think we'll be adding new functions to rbtree.h, so it may be fine to stay with the rb_ prefix.
-- Steve
Steven Rostedt
maintainerRFC PATCH v3 2/2 ftrace: make work with new ring buffer
In reply to Steven RostedtNote: This patch is a proof of concept, and breaks a lot of
functionality of ftrace.
This patch simply makes ftrace work with the developmental ring buffer.
--- kernel/trace/trace.c | 776 ++++++++------------------------------ kernel/trace/trace.h | 22 - kernel/trace/trace_functions.c | 2 kernel/trace/trace_irqsoff.c | 6 kernel/trace/trace_mmiotrace.c | 10 kernel/trace/trace_sched_switch.c | 2 kernel/trace/trace_sched_wakeup.c | 2 7 files changed, 195 insertions(+), 625 deletions(-)
kernel/trace/trace.c +177 -599
@@ -31,25 +31,24 @@#include <linux/writeback.h> #include <linux/stacktrace.h> +#include <linux/ring_buffer.h> #include "trace.h" +#define sdr_print(x, y...) printk("%s:%d " x "\n", __FUNCTION__, __LINE__, y) + +#define TRACE_BUFFER_FLAGS (RB_FL_OVERWRITE) +unsigned long __read_mostly tracing_max_latency = (cycle_t )ULONG_MAX ;unsigned long __read_mostly tracing_thresh; -static unsigned long __read_mostly tracing_nr_buffers;static cpumask_t __read_mostly tracing_buffer_mask;#define for_each_tracing_cpu (cpu) \ for_each_cpu_mask(cpu, tracing_buffer_mask) -static int trace_alloc_page (void ); -static int trace_free_page (void ); -static int tracing_disabled =1 ; -static unsigned long tracing_pages_allocated; -long ns2usecs (cycle_t nsec) {
@@ -100,11 +99,11 @@ static int tracer_enabled = 1;int ftrace_function_enabled;/* -* trace_nr_entries is the number of entries that is allocated -* for a buffer. Note, the number of entries is always rounded -* to ENTRIES_PER_PAGE. +* trace_buf_size is the size in bytes that is allocated +* for a buffer. Note, the number of bytes is always rounded +* to page size. */ -static unsigned long trace_nr_entries =65536UL ; +static unsigned long trace_buf_size =65536UL ;/* trace_types holds a link list of available tracers. */ static struct tracer *trace_types__read_mostly ;
@@ -139,8 +138,8 @@ static notrace void no_trace_init(struct ftrace_function_enabled =0 ;if (tr->ctrl) -for_each_online_cpu (cpu) -tracing_reset (tr->data[cpu]); +for_each_tracing_cpu (cpu) +tracing_reset (tr, cpu); tracer_enabled =0 ; }
@@ -167,23 +166,21 @@ void trace_wake_up(void)wake_up (&trace_wait); } -#define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(struct trace_entry)) - -static int __init set_nr_entries (char *str) +static int __init set_buf_size (char *str) { -unsigned long nr_entries; +unsigned long buf_size;int ret;if (!str)return 0 ; - ret =strict_strtoul (str,0 , &nr_entries); + ret =strict_strtoul (str,0 , &buf_size);/* nr_entries can not be zero */ -if (ret <0 || nr_entries ==0 ) +if (ret <0 || buf_size ==0 )return 0 ; - trace_nr_entries = nr_entries; + trace_buf_size = buf_size;return 1 ; } -__setup ("trace_entries=" , set_nr_entries); +__setup ("trace_buf_size=" , set_buf_size);unsigned long nsecs_to_usecs (unsigned long nsecs) {
@@ -266,54 +263,6 @@ __update_max_tr(struct trace_array *tr,tracing_record_cmdline (current); } -#define CHECK_COND (cond) \ - if (unlikely(cond)) { \ - tracing_disabled = 1; \ - WARN_ON(1); \ - return -1; \ - } - -/** -* check_pages - integrity check of trace buffers -* -* As a safty measure we check to make sure the data pages have not -* been corrupted. -*/ -int check_pages (struct trace_array_cpu *data) -{ -struct page *page, *tmp; - -CHECK_COND (data->trace_pages.next->prev != &data->trace_pages); -CHECK_COND (data->trace_pages.prev->next != &data->trace_pages); - -list_for_each_entry_safe (page, tmp, &data->trace_pages, lru) { -CHECK_COND (page->lru.next->prev != &page->lru); -CHECK_COND (page->lru.prev->next != &page->lru); - } - -return 0 ; -} - -/** -* head_page - page address of the first page in per_cpu buffer. -* -* head_page returns the page address of the first page in -* a per_cpu buffer. This also preforms various consistency -* checks to make sure the buffer has not been corrupted. -*/ -void *head_page (struct trace_array_cpu *data) -{ -struct page *page; - -if (list_empty (&data->trace_pages)) -return NULL ; - - page = list_entry(data->trace_pages.next, struct page, lru); -BUG_ON (&page->lru == &data->trace_pages); - -return page_address (page); -} -/** * trace_seq_printf - sequence printing of trace information * @s: trace sequence descriptor
@@ -460,34 +409,6 @@ trace_print_seq(struct seq_file *m, strutrace_seq_reset (s); } -/* -* flip the trace buffers between two trace descriptors. -* This usually is the buffers between the global_trace and -* the max_tr to record a snapshot of a current trace. -* -* The ftrace_max_lock must be held. -*/ -static void -flip_trace (struct trace_array_cpu *tr1,struct trace_array_cpu *tr2) -{ -struct list_head flip_pages; - -INIT_LIST_HEAD (&flip_pages); - -memcpy (&tr1->trace_head_idx, &tr2->trace_head_idx, -sizeof (struct trace_array_cpu ) - - offsetof(struct trace_array_cpu , trace_head_idx)); - -check_pages (tr1); -check_pages (tr2); -list_splice_init (&tr1->trace_pages, &flip_pages); -list_splice_init (&tr2->trace_pages, &tr1->trace_pages); -list_splice_init (&flip_pages, &tr2->trace_pages); -BUG_ON (!list_empty (&flip_pages)); -check_pages (tr1); -check_pages (tr2); -} -/** * update_max_tr - snapshot all trace buffers from global_trace to max_tr * @tr: tracer
@@ -500,17 +421,15 @@ flip_trace(struct trace_array_cpu *tr1,void update_max_tr (struct trace_array *tr,struct task_struct *tsk,int cpu) { -struct trace_array_cpu *data; -int i; +struct ring_buffer *buf = tr->buffer;WARN_ON_ONCE (!irqs_disabled ());__raw_spin_lock (&ftrace_max_lock); -/* clear out all the previous traces */ -for_each_tracing_cpu (i) { - data = tr->data[i]; -flip_trace (max_tr.data[i], data); -tracing_reset (data); - } + + tr->buffer = max_tr.buffer; + max_tr.buffer = buf; + +ring_buffer_reset (tr->buffer);__update_max_tr (tr, tsk, cpu);__raw_spin_unlock (&ftrace_max_lock);
@@ -527,16 +446,15 @@ update_max_tr(struct trace_array *tr, stvoid update_max_tr_single (struct trace_array *tr,struct task_struct *tsk,int cpu) { -struct trace_array_cpu *data = tr->data[cpu]; -int i; +int ret;WARN_ON_ONCE (!irqs_disabled ());__raw_spin_lock (&ftrace_max_lock); -for_each_tracing_cpu (i) -tracing_reset (max_tr.data[i]); -flip_trace (max_tr.data[cpu], data); -tracing_reset (data); +ring_buffer_reset (max_tr.buffer); + ret =ring_buffer_swap_cpu (max_tr.buffer, tr->buffer, cpu); + +WARN_ON_ONCE (ret);__update_max_tr (tr, tsk, cpu);__raw_spin_unlock (&ftrace_max_lock);
@@ -573,7 +491,6 @@ int register_tracer(struct tracer *type)#ifdef CONFIG_FTRACE_STARTUP_TEST if (type->selftest) {struct tracer *saved_tracer = current_trace; -struct trace_array_cpu *data;struct trace_array *tr = &global_trace;int saved_ctrl = tr->ctrl;int i;
@@ -585,10 +502,7 @@ int register_tracer(struct tracer *type)* If we fail, we do not register this tracer. */ for_each_tracing_cpu (i) { - data = tr->data[i]; -if (!head_page (data)) -continue ; -tracing_reset (data); +tracing_reset (tr, i); } current_trace = type; tr->ctrl =0 ;
@@ -604,10 +518,7 @@ int register_tracer(struct tracer *type) }/* Only reset on passing, to avoid touching corrupted buffers */ for_each_tracing_cpu (i) { - data = tr->data[i]; -if (!head_page (data)) -continue ; -tracing_reset (data); +tracing_reset (tr, i); }printk (KERN_CONT "PASSED\n" ); }
@@ -653,13 +564,9 @@ void unregister_tracer(struct tracer *tymutex_unlock (&trace_types_lock); } -void tracing_reset (struct trace_array_cpu *data) +void tracing_reset (struct trace_array *tr,int cpu) { - data->trace_idx =0 ; - data->overrun =0 ; - data->trace_head = data->trace_tail =head_page (data); - data->trace_head_idx =0 ; - data->trace_tail_idx =0 ; +ring_buffer_reset_cpu (tr->buffer, cpu); }#define SAVED_CMDLINES 128
@@ -745,70 +652,6 @@ void tracing_record_cmdline(struct task_trace_save_cmdline (tsk); } -static inline struct list_head * -trace_next_list (struct trace_array_cpu *data,struct list_head *next) -{ -/* -* Roundrobin - but skip the head (which is not a real page): -*/ - next = next->next; -if (unlikely (next == &data->trace_pages)) - next = next->next; -BUG_ON (next == &data->trace_pages); - -return next; -} - -static inline void * -trace_next_page (struct trace_array_cpu *data,void *addr) -{ -struct list_head *next; -struct page *page; - - page =virt_to_page (addr); - - next =trace_next_list (data, &page->lru); - page = list_entry(next, struct page, lru); - -return page_address (page); -} - -static inline struct trace_entry * -tracing_get_trace_entry (struct trace_array *tr,struct trace_array_cpu *data) -{ -unsigned long idx, idx_next; -struct trace_entry *entry; - - data->trace_idx++; - idx = data->trace_head_idx; - idx_next = idx +1 ; - -BUG_ON (idx *TRACE_ENTRY_SIZE >=PAGE_SIZE ); - - entry = data->trace_head + idx *TRACE_ENTRY_SIZE ; - -if (unlikely (idx_next >=ENTRIES_PER_PAGE )) { - data->trace_head =trace_next_page (data, data->trace_head); - idx_next =0 ; - } - -if (data->trace_head == data->trace_tail && - idx_next == data->trace_tail_idx) { -/* overrun */ - data->overrun++; - data->trace_tail_idx++; -if (data->trace_tail_idx >=ENTRIES_PER_PAGE ) { - data->trace_tail = -trace_next_page (data, data->trace_tail); - data->trace_tail_idx =0 ; - } - } - - data->trace_head_idx = idx_next; - -return entry; -} -static inline void tracing_generic_entry_update (struct trace_entry *entry,unsigned long flags) {
@@ -819,7 +662,6 @@ tracing_generic_entry_update(struct trac entry->preempt_count = pc &0xff ; entry->pid = (tsk) ? tsk->pid :0 ; - entry->t =ftrace_now (raw_smp_processor_id ()); entry->flags = (irqs_disabled_flags (flags) ?TRACE_FLAG_IRQS_OFF :0 ) | ((pc &HARDIRQ_MASK ) ?TRACE_FLAG_HARDIRQ :0 ) | ((pc & SOFTIRQ_MASK) ? TRACE_FLAG_SOFTIRQ : 0) |
@@ -833,15 +675,14 @@ trace_function(struct trace_array *tr, sstruct trace_entry *entry;unsigned long irq_flags; -raw_local_irq_save (irq_flags); -__raw_spin_lock (&data->lock); - entry =tracing_get_trace_entry (tr, data); + entry =ring_buffer_lock_reserve (tr->buffer,sizeof (*entry), &irq_flags); +if (!entry) +return ;tracing_generic_entry_update (entry, flags); entry->type =TRACE_FN ; entry->fn.ip = ip; entry->fn.parent_ip = parent_ip; -__raw_spin_unlock (&data->lock); -raw_local_irq_restore (irq_flags); +ring_buffer_unlock_commit (tr->buffer, entry, irq_flags); }void
@@ -859,16 +700,13 @@ void __trace_mmiotrace_rw(struct trace_astruct trace_entry *entry;unsigned long irq_flags; -raw_local_irq_save (irq_flags); -__raw_spin_lock (&data->lock); - - entry =tracing_get_trace_entry (tr, data); + entry =ring_buffer_lock_reserve (tr->buffer,sizeof (*entry), &irq_flags); +if (!entry) +return ;tracing_generic_entry_update (entry,0 ); entry->type =TRACE_MMIO_RW ; entry->mmiorw = *rw; - -__raw_spin_unlock (&data->lock); -raw_local_irq_restore (irq_flags); +ring_buffer_unlock_commit (tr->buffer, entry, irq_flags);trace_wake_up (); }
@@ -879,16 +717,13 @@ void __trace_mmiotrace_map(struct trace_struct trace_entry *entry;unsigned long irq_flags; -raw_local_irq_save (irq_flags); -__raw_spin_lock (&data->lock); - - entry =tracing_get_trace_entry (tr, data); + entry =ring_buffer_lock_reserve (tr->buffer,sizeof (*entry), &irq_flags); +if (!entry) +return ;tracing_generic_entry_update (entry,0 ); entry->type =TRACE_MMIO_MAP ; entry->mmiomap = *map; - -__raw_spin_unlock (&data->lock); -raw_local_irq_restore (irq_flags); +ring_buffer_unlock_commit (tr->buffer, entry, irq_flags);trace_wake_up (); }
@@ -901,11 +736,14 @@ void __trace_stack(struct trace_array *t {struct trace_entry *entry;struct stack_trace trace; +unsigned long irq_flags;if (!(trace_flags &TRACE_ITER_STACKTRACE ))return ; - entry =tracing_get_trace_entry (tr, data); + entry =ring_buffer_lock_reserve (tr->buffer,sizeof (*entry), &irq_flags); +if (!entry) +return ;tracing_generic_entry_update (entry, flags); entry->type =TRACE_STACK ;
@@ -917,6 +755,7 @@ void __trace_stack(struct trace_array *t trace.entries = entry->stack.caller;save_stack_trace (&trace); +ring_buffer_unlock_commit (tr->buffer, entry, irq_flags); }void
@@ -928,17 +767,16 @@ __trace_special(void *__tr, void *__datastruct trace_entry *entry;unsigned long irq_flags; -raw_local_irq_save (irq_flags); -__raw_spin_lock (&data->lock); - entry =tracing_get_trace_entry (tr, data); + entry =ring_buffer_lock_reserve (tr->buffer,sizeof (*entry), &irq_flags); +if (!entry) +return ;tracing_generic_entry_update (entry,0 ); entry->type =TRACE_SPECIAL ; entry->special.arg1 = arg1; entry->special.arg2 = arg2; entry->special.arg3 = arg3; +ring_buffer_unlock_commit (tr->buffer, entry, irq_flags);__trace_stack (tr, data, irq_flags,4 ); -__raw_spin_unlock (&data->lock); -raw_local_irq_restore (irq_flags);trace_wake_up (); }
@@ -953,9 +791,9 @@ tracing_sched_switch_trace(struct trace_struct trace_entry *entry;unsigned long irq_flags; -raw_local_irq_save (irq_flags); -__raw_spin_lock (&data->lock); - entry =tracing_get_trace_entry (tr, data); + entry =ring_buffer_lock_reserve (tr->buffer,sizeof (*entry), &irq_flags); +if (!entry) +return ;tracing_generic_entry_update (entry, flags); entry->type =TRACE_CTX ; entry->ctx.prev_pid = prev->pid;
@@ -964,9 +802,8 @@ tracing_sched_switch_trace(struct trace_ entry->ctx.next_pid = next->pid; entry->ctx.next_prio = next->prio; entry->ctx.next_state = next->state; +ring_buffer_unlock_commit (tr->buffer, entry, irq_flags);__trace_stack (tr, data, flags,5 ); -__raw_spin_unlock (&data->lock); -raw_local_irq_restore (irq_flags); }void
@@ -979,9 +816,9 @@ tracing_sched_wakeup_trace(struct trace_struct trace_entry *entry;unsigned long irq_flags; -raw_local_irq_save (irq_flags); -__raw_spin_lock (&data->lock); - entry =tracing_get_trace_entry (tr, data); + entry =ring_buffer_lock_reserve (tr->buffer,sizeof (*entry), &irq_flags); +if (!entry) +return ;tracing_generic_entry_update (entry, flags); entry->type =TRACE_WAKE ; entry->ctx.prev_pid = curr->pid;
@@ -990,9 +827,8 @@ tracing_sched_wakeup_trace(struct trace_ entry->ctx.next_pid = wakee->pid; entry->ctx.next_prio = wakee->prio; entry->ctx.next_state = wakee->state; +ring_buffer_unlock_commit (tr->buffer, entry, irq_flags);__trace_stack (tr, data, flags,6 ); -__raw_spin_unlock (&data->lock); -raw_local_irq_restore (irq_flags);trace_wake_up (); }
@@ -1074,105 +910,66 @@ enum trace_file_type { };static struct trace_entry * -trace_entry_idx (struct trace_array *tr,struct trace_array_cpu *data, -struct trace_iterator *iter,int cpu) -{ -struct page *page; -struct trace_entry *array; - -if (iter->next_idx[cpu] >= tr->entries || - iter->next_idx[cpu] >= data->trace_idx || - (data->trace_head == data->trace_tail && - data->trace_head_idx == data->trace_tail_idx)) -return NULL ; - -if (!iter->next_page[cpu]) { -/* Initialize the iterator for this cpu trace buffer */ -WARN_ON (!data->trace_tail); - page =virt_to_page (data->trace_tail); - iter->next_page[cpu] = &page->lru; - iter->next_page_idx[cpu] = data->trace_tail_idx; - } - - page = list_entry(iter->next_page[cpu], struct page, lru); -BUG_ON (&data->trace_pages == &page->lru); - - array =page_address (page); - -WARN_ON (iter->next_page_idx[cpu] >=ENTRIES_PER_PAGE ); -return &array[iter->next_page_idx[cpu]]; -} - -static struct trace_entry * -find_next_entry (struct trace_iterator *iter,int *ent_cpu) +find_next_entry (struct trace_iterator *iter,int *ent_cpu,u64 *ent_ts) { -struct trace_array *tr = iter->tr; +struct ring_buffer *buffer = iter->tr->buffer; +struct ring_buffer_event *event;struct trace_entry *ent, *next =NULL ; +u64 next_ts =0 , ts;int next_cpu =-1 ;int cpu;for_each_tracing_cpu (cpu) { -if (!head_page (tr->data[cpu])) +struct ring_buffer_iter *buf_iter; + +if (ring_buffer_empty_cpu (buffer, cpu))continue ; - ent =trace_entry_idx (tr, tr->data[cpu], iter, cpu); + + buf_iter = iter->buffer_iter[cpu]; + event =ring_buffer_iter_peek (buf_iter, &ts); + ent = event ?ring_buffer_event_data (event) :NULL ; +/* * Pick the entry with the smallest timestamp: */ -if (ent && (!next || ent->t < next->t)) { +if (ent && (!next || ts < next_ts)) { next = ent; next_cpu = cpu; + next_ts = ts; } }if (ent_cpu) *ent_cpu = next_cpu; +if (ent_ts) + *ent_ts = next_ts; +return next; }static void trace_iterator_increment (struct trace_iterator *iter) { iter->idx++; - iter->next_idx[iter->cpu]++; - iter->next_page_idx[iter->cpu]++; - -if (iter->next_page_idx[iter->cpu] >=ENTRIES_PER_PAGE ) { -struct trace_array_cpu *data = iter->tr->data[iter->cpu]; - - iter->next_page_idx[iter->cpu] =0 ; - iter->next_page[iter->cpu] = -trace_next_list (data, iter->next_page[iter->cpu]); - } +ring_buffer_read (iter->buffer_iter[iter->cpu],NULL ); }static void trace_consume (struct trace_iterator *iter) { -struct trace_array_cpu *data = iter->tr->data[iter->cpu]; - - data->trace_tail_idx++; -if (data->trace_tail_idx >=ENTRIES_PER_PAGE ) { - data->trace_tail =trace_next_page (data, data->trace_tail); - data->trace_tail_idx =0 ; - } - -/* Check if we empty it, then reset the index */ -if (data->trace_head == data->trace_tail && - data->trace_head_idx == data->trace_tail_idx) - data->trace_idx =0 ; +ring_buffer_consume (iter->tr->buffer, iter->cpu, &iter->ts); }static void *find_next_entry_inc (struct trace_iterator *iter) {struct trace_entry *next;int next_cpu =-1 ; +u64 ts; - next =find_next_entry (iter, &next_cpu); - - iter->prev_ent = iter->ent; - iter->prev_cpu = iter->cpu; + next =find_next_entry (iter, &next_cpu, &ts); iter->ent = next; iter->cpu = next_cpu; + iter->ts = ts;if (next)trace_iterator_increment (iter);
@@ -1210,7 +1007,7 @@ static void *s_start(struct seq_file *m,struct trace_iterator *iter = m->private;void *p =NULL ;loff_t l =0 ; -int i; +int cpu;mutex_lock (&trace_types_lock);
@@ -1229,12 +1026,9 @@ static void *s_start(struct seq_file *m, iter->ent =NULL ; iter->cpu =0 ; iter->idx =-1 ; - iter->prev_ent =NULL ; - iter->prev_cpu =-1 ; -for_each_tracing_cpu (i) { - iter->next_idx[i] =0 ; - iter->next_page[i] =NULL ; +for_each_tracing_cpu (cpu) { +ring_buffer_iter_reset (iter->buffer_iter[cpu]); }for (p = iter; p && l < *pos; p =s_next (m, p, &l))
@@ -1357,21 +1151,12 @@ print_trace_header(struct seq_file *m, sstruct tracer *type = current_trace;unsigned long total =0 ;unsigned long entries =0 ; -int cpu;const char *name ="preemption" ;if (type) name = type->name; -for_each_tracing_cpu (cpu) { -if (head_page (tr->data[cpu])) { - total += tr->data[cpu]->trace_idx; -if (tr->data[cpu]->trace_idx > tr->entries) - entries += tr->entries; -else - entries += tr->data[cpu]->trace_idx; - } - } + entries =ring_buffer_entries (iter->tr->buffer);seq_printf (m,"%s latency trace v1.1.5 on %s\n" , name,UTS_RELEASE );
@@ -1457,7 +1242,7 @@ lat_print_generic(struct trace_seq *s, sunsigned long preempt_mark_thresh =100 ;static void -lat_print_timestamp (struct trace_seq *s,unsigned long long abs_usecs, +lat_print_timestamp (struct trace_seq *s,u64 abs_usecs,unsigned long rel_usecs) {trace_seq_printf (s," %4lldus" , abs_usecs);
@@ -1476,20 +1261,22 @@ print_lat_fmt(struct trace_iterator *ite {struct trace_seq *s = &iter->seq;unsigned long sym_flags = (trace_flags &TRACE_ITER_SYM_MASK ); -struct trace_entry *next_entry =find_next_entry (iter,NULL ); +struct trace_entry *next_entry;unsigned long verbose = (trace_flags &TRACE_ITER_VERBOSE );struct trace_entry *entry = iter->ent;unsigned long abs_usecs;unsigned long rel_usecs; +u64 next_ts;char *comm;int S ,T ;int i;unsigned state; + next_entry =find_next_entry (iter,NULL , &next_ts);if (!next_entry) - next_entry = entry; - rel_usecs =ns2usecs (next_entry->t - entry->t); - abs_usecs =ns2usecs (entry->t - iter->tr->time_start); + next_ts = iter->ts; + rel_usecs =ns2usecs (next_ts - iter->ts); + abs_usecs =ns2usecs (iter->ts - iter->tr->time_start);if (verbose) { comm =trace_find_cmdline (entry->pid);
@@ -1498,7 +1285,7 @@ print_lat_fmt(struct trace_iterator *ite comm, entry->pid, cpu, entry->flags, entry->preempt_count, trace_idx, -ns2usecs (entry->t), +ns2usecs (iter->ts), abs_usecs/1000 , abs_usecs %1000 , rel_usecs/1000 , rel_usecs % 1000);
@@ -1569,7 +1356,7 @@ static int print_trace_fmt(struct trace_ comm =trace_find_cmdline (iter->ent->pid); - t =ns2usecs (entry->t); + t =ns2usecs (iter->ts); usec_rem =do_div (t,1000000ULL ); secs = (unsigned long )t;
@@ -1660,7 +1447,7 @@ static int print_raw_fmt(struct trace_it entry = iter->ent; ret =trace_seq_printf (s,"%d %d %llu " , - entry->pid, iter->cpu, entry->t); + entry->pid, iter->cpu, iter->ts);if (!ret)return 0 ;
@@ -1725,7 +1512,7 @@ static int print_hex_fmt(struct trace_itSEQ_PUT_HEX_FIELD_RET (s, entry->pid);SEQ_PUT_HEX_FIELD_RET (s, iter->cpu); -SEQ_PUT_HEX_FIELD_RET (s, entry->t); +SEQ_PUT_HEX_FIELD_RET (s, iter->ts);switch (entry->type) {case TRACE_FN :
@@ -1769,7 +1556,7 @@ static int print_bin_fmt(struct trace_itSEQ_PUT_FIELD_RET (s, entry->pid);SEQ_PUT_FIELD_RET (s, entry->cpu); -SEQ_PUT_FIELD_RET (s, entry->t); +SEQ_PUT_FIELD_RET (s, iter->ts);switch (entry->type) {case TRACE_FN :
@@ -1796,16 +1583,10 @@ static int print_bin_fmt(struct trace_itstatic int trace_empty (struct trace_iterator *iter) { -struct trace_array_cpu *data;int cpu;for_each_tracing_cpu (cpu) { - data = iter->tr->data[cpu]; - -if (head_page (data) && data->trace_idx && - (data->trace_tail != data->trace_head || - data->trace_tail_idx != data->trace_head_idx)) -return 0 ; +ring_buffer_iter_empty (iter->buffer_iter[cpu]); }return 1 ; }
@@ -1869,6 +1650,8 @@ static struct trace_iterator * __tracing_open(struct inode *inode, struct file *file, int *ret) { struct trace_iterator *iter; +struct seq_file *m; +int cpu;if (tracing_disabled) { *ret = -ENODEV ;
@@ -1889,28 +1672,43 @@ __tracing_open(struct inode *inode, stru iter->trace = current_trace; iter->pos =-1 ; +for_each_tracing_cpu (cpu) { + iter->buffer_iter[cpu] = +ring_buffer_read_start (iter->tr->buffer, cpu); +if (!iter->buffer_iter[cpu]) + goto fail_buffer; + } +/* TODO stop tracer */ *ret =seq_open (file, &tracer_seq_ops); -if (!*ret) { -struct seq_file *m = file->private_data; - m->private = iter; +if (*ret) + goto fail_buffer; -/* stop the trace while dumping */ -if (iter->tr->ctrl) { - tracer_enabled =0 ; - ftrace_function_enabled =0 ; - } + m = file->private_data; + m->private = iter; -if (iter->trace && iter->trace->open) - iter->trace->open (iter); - }else { -kfree (iter); - iter =NULL ; +/* stop the trace while dumping */ +if (iter->tr->ctrl) { + tracer_enabled =0 ; + ftrace_function_enabled =0 ; } + +if (iter->trace && iter->trace->open) + iter->trace->open (iter); +mutex_unlock (&trace_types_lock); out:return iter; + + fail_buffer: +for_each_tracing_cpu (cpu) { +if (iter->buffer_iter[cpu]) +ring_buffer_read_finish (iter->buffer_iter[cpu]); + } +mutex_unlock (&trace_types_lock); + +return ERR_PTR (-ENOMEM ); }int tracing_open_generic (struct inode *inode,struct file *filp)
@@ -1926,8 +1724,14 @@ int tracing_release(struct inode *inode, {struct seq_file *m = (struct seq_file *)file->private_data;struct trace_iterator *iter = m->private; +int cpu;mutex_lock (&trace_types_lock); +for_each_tracing_cpu (cpu) { +if (iter->buffer_iter[cpu]) +ring_buffer_read_finish (iter->buffer_iter[cpu]); + } +if (iter->trace && iter->trace->close) iter->trace->close (iter);
@@ -2500,13 +2304,10 @@ tracing_read_pipe(struct file *filp, cha size_t cnt, loff_t *ppos) { struct trace_iterator *iter = filp->private_data; -struct trace_array_cpu *data; -static cpumask_t mask;unsigned long flags;#ifdef CONFIG_FTRACE int ftrace_save;#endif -int cpu;ssize_t sret;/* return any leftover data */
@@ -2595,32 +2396,13 @@ tracing_read_pipe(struct file *filp, cha* and then release the locks again. */ -cpus_clear (mask); -local_irq_save (flags); +local_irq_disable ();#ifdef CONFIG_FTRACE ftrace_save = ftrace_enabled; ftrace_enabled =0 ;#endif smp_wmb (); -for_each_tracing_cpu (cpu) { - data = iter->tr->data[cpu]; - -if (!head_page (data) || !data->trace_idx) -continue ; - -atomic_inc (&data->disabled); -cpu_set (cpu, mask); - } - -for_each_cpu_mask (cpu, mask) { - data = iter->tr->data[cpu]; -__raw_spin_lock (&data->lock); - -if (data->overrun > iter->last_overrun[cpu]) - iter->overrun[cpu] += - data->overrun - iter->last_overrun[cpu]; - iter->last_overrun[cpu] = data->overrun; - } +ring_buffer_lock (iter->tr->buffer, &flags);while (find_next_entry_inc (iter) !=NULL ) {int ret;
@@ -2639,19 +2421,11 @@ tracing_read_pipe(struct file *filp, chabreak ; } -for_each_cpu_mask (cpu, mask) { - data = iter->tr->data[cpu]; -__raw_spin_unlock (&data->lock); - } - -for_each_cpu_mask (cpu, mask) { - data = iter->tr->data[cpu]; -atomic_dec (&data->disabled); - } +ring_buffer_unlock (iter->tr->buffer, flags);#ifdef CONFIG_FTRACE ftrace_enabled = ftrace_save;#endif -local_irq_restore (flags); +local_irq_enable ();/* Now copy what we have to the user */ sret =trace_seq_to_user (&iter->seq, ubuf, cnt);
@@ -2684,7 +2458,7 @@ tracing_entries_write(struct file *filp, {unsigned long val;char buf[64 ]; -int i, ret; +int ret;if (cnt >=sizeof (buf))return -EINVAL ;
@@ -2711,52 +2485,31 @@ tracing_entries_write(struct file *filp, goto out; } -if (val > global_trace.entries) { -long pages_requested; -unsigned long freeable_pages; - -/* make sure we have enough memory before mapping */ - pages_requested = - (val + (ENTRIES_PER_PAGE -1 )) /ENTRIES_PER_PAGE ; - -/* account for each buffer (and max_tr) */ - pages_requested *= tracing_nr_buffers *2 ; - -/* Check for overflow */ -if (pages_requested <0 ) { - cnt = -ENOMEM ; +if (val != global_trace.entries) { + ret =ring_buffer_resize (global_trace.buffer, val); +if (ret <0 ) { + cnt = ret; goto out; } - freeable_pages =determine_dirtyable_memory (); - -/* we only allow to request 1/4 of useable memory */ -if (pages_requested > - ((freeable_pages + tracing_pages_allocated) /4 )) { - cnt = -ENOMEM ; - goto out; - } - -while (global_trace.entries < val) { -if (trace_alloc_page ()) { - cnt = -ENOMEM ; - goto out; + ret =ring_buffer_resize (max_tr.buffer, val); +if (ret <0 ) { +int r; + cnt = ret; + r =ring_buffer_resize (global_trace.buffer, + global_trace.entries); +if (r <0 ) { +/* AARGH! We are left with different +* size max buffer!!!! */ +WARN_ON (1 ); + tracing_disabled =1 ; } -/* double check that we don't go over the known pages */ -if (tracing_pages_allocated > pages_requested) -break ; + goto out; } - }else { -/* include the number of entries in val (inc of page entries) */ -while (global_trace.entries > val + (ENTRIES_PER_PAGE -1 )) -trace_free_page (); + global_trace.entries = val; } -/* check integrity */ -for_each_tracing_cpu (i) -check_pages (global_trace.data[i]); - filp->f_pos += cnt;/* If check pages failed, return ENOMEM */
@@ -2930,190 +2683,41 @@ static __init void tracer_init_debugfs(v#endif } -static int trace_alloc_page (void ) +__init static int tracer_alloc_buffers (void ) {struct trace_array_cpu *data; -struct page *page, *tmp; -LIST_HEAD (pages); -void *array; -unsigned pages_allocated =0 ;int i; -/* first allocate a page for each CPU */ -for_each_tracing_cpu (i) { - array = (void *)__get_free_page (GFP_KERNEL ); -if (array ==NULL ) { -printk (KERN_ERR "tracer: failed to allocate page" -"for trace buffer!\n" ); - goto free_pages; - } - - pages_allocated++; - page =virt_to_page (array); -list_add (&page->lru, &pages); +/* TODO: make the number of buffers hot pluggable with CPUS */ + tracing_buffer_mask = cpu_possible_map; -/* Only allocate if we are actually using the max trace */ -#ifdef CONFIG_TRACER_MAX_TRACE - array = (void *)__get_free_page (GFP_KERNEL ); -if (array ==NULL ) { -printk (KERN_ERR "tracer: failed to allocate page" -"for trace buffer!\n" ); - goto free_pages; - } - pages_allocated++; - page =virt_to_page (array); -list_add (&page->lru, &pages); -#endif + global_trace.buffer =ring_buffer_alloc (trace_buf_size, +TRACE_BUFFER_FLAGS ); +if (!global_trace.buffer) { +printk (KERN_ERR "tracer: failed to allocate ring buffer!\n" ); +WARN_ON (1 ); +return 0 ; } - -/* Now that we successfully allocate a page per CPU, add them */ -for_each_tracing_cpu (i) { - data = global_trace.data[i]; - page = list_entry(pages.next, struct page, lru); -list_del_init (&page->lru); -list_add_tail (&page->lru, &data->trace_pages); -ClearPageLRU (page); + global_trace.entries =ring_buffer_size (global_trace.buffer);#ifdef CONFIG_TRACER_MAX_TRACE - data = max_tr.data[i]; - page = list_entry(pages.next, struct page, lru); -list_del_init (&page->lru); -list_add_tail (&page->lru, &data->trace_pages); -SetPageLRU (page); -#endif - } - tracing_pages_allocated += pages_allocated; - global_trace.entries +=ENTRIES_PER_PAGE ; - -return 0 ; - - free_pages: -list_for_each_entry_safe (page, tmp, &pages, lru) { -list_del_init (&page->lru); -__free_page (page); + max_tr.buffer =ring_buffer_alloc (trace_buf_size, +TRACE_BUFFER_FLAGS ); +if (!max_tr.buffer) { +printk (KERN_ERR "tracer: failed to allocate max ring buffer!\n" ); +WARN_ON (1 ); +ring_buffer_free (global_trace.buffer); +return 0 ; } -return -ENOMEM ; -} - -static int trace_free_page (void ) -{ -struct trace_array_cpu *data; -struct page *page; -struct list_head *p; -int i; -int ret =0 ; - -/* free one page from each buffer */ -for_each_tracing_cpu (i) { - data = global_trace.data[i]; - p = data->trace_pages.next; -if (p == &data->trace_pages) { -/* should never happen */ -WARN_ON (1 ); - tracing_disabled =1 ; - ret =-1 ; -break ; - } - page = list_entry(p, struct page, lru); -ClearPageLRU (page); -list_del (&page->lru); - tracing_pages_allocated--; - tracing_pages_allocated--; -__free_page (page); - -tracing_reset (data); - -#ifdef CONFIG_TRACER_MAX_TRACE - data = max_tr.data[i]; - p = data->trace_pages.next; -if (p == &data->trace_pages) { -/* should never happen */ -WARN_ON (1 ); - tracing_disabled =1 ; - ret =-1 ; -break ; - } - page = list_entry(p, struct page, lru); -ClearPageLRU (page); -list_del (&page->lru); -__free_page (page); - -tracing_reset (data); + max_tr.entries =ring_buffer_size (max_tr.buffer); +WARN_ON (max_tr.entries != global_trace.entries);#endif - } - global_trace.entries -=ENTRIES_PER_PAGE ; - -return ret; -} - -__init static int tracer_alloc_buffers (void ) -{ -struct trace_array_cpu *data; -void *array; -struct page *page; -int pages =0 ; -int ret = -ENOMEM ; -int i; - -/* TODO: make the number of buffers hot pluggable with CPUS */ - tracing_nr_buffers =num_possible_cpus (); - tracing_buffer_mask = cpu_possible_map;/* Allocate the first page for all buffers */ for_each_tracing_cpu (i) { data = global_trace.data[i] = &per_cpu (global_trace_cpu, i); max_tr.data[i] = &per_cpu (max_data, i); - - array = (void *)__get_free_page (GFP_KERNEL ); -if (array ==NULL ) { -printk (KERN_ERR "tracer: failed to allocate page" -"for trace buffer!\n" ); - goto free_buffers; - } - -/* set the array to the list */ -INIT_LIST_HEAD (&data->trace_pages); - page =virt_to_page (array); -list_add (&page->lru, &data->trace_pages); -/* use the LRU flag to differentiate the two buffers */ -ClearPageLRU (page); - - data->lock = (raw_spinlock_t )__RAW_SPIN_LOCK_UNLOCKED; - max_tr.data[i]->lock = (raw_spinlock_t )__RAW_SPIN_LOCK_UNLOCKED; - -/* Only allocate if we are actually using the max trace */ -#ifdef CONFIG_TRACER_MAX_TRACE - array = (void *)__get_free_page (GFP_KERNEL ); -if (array ==NULL ) { -printk (KERN_ERR "tracer: failed to allocate page" -"for trace buffer!\n" ); - goto free_buffers; - } - -INIT_LIST_HEAD (&max_tr.data[i]->trace_pages); - page =virt_to_page (array); -list_add (&page->lru, &max_tr.data[i]->trace_pages); -SetPageLRU (page); -#endif - } - -/* -* Since we allocate by orders of pages, we may be able to -* round up a bit. -*/ - global_trace.entries =ENTRIES_PER_PAGE ; - pages++; - -while (global_trace.entries < trace_nr_entries) { -if (trace_alloc_page ()) -break ; - pages++; } - max_tr.entries = global_trace.entries; - -pr_info ("tracer: %d pages allocated for %ld entries of %ld bytes\n" , - pages, trace_nr_entries, (long )TRACE_ENTRY_SIZE ); -pr_info (" actual entries %ld\n" , global_trace.entries);tracer_init_debugfs ();
@@ -3127,31 +2731,5 @@ __init static int tracer_alloc_buffers(v tracing_disabled =0 ;return 0 ; - - free_buffers: -for (i-- ; i >=0 ; i--) { -struct page *page, *tmp; -struct trace_array_cpu *data = global_trace.data[i]; - -if (data) { -list_for_each_entry_safe (page, tmp, - &data->trace_pages, lru) { -list_del_init (&page->lru); -__free_page (page); - } - } - -#ifdef CONFIG_TRACER_MAX_TRACE - data = max_tr.data[i]; -if (data) { -list_for_each_entry_safe (page, tmp, - &data->trace_pages, lru) { -list_del_init (&page->lru); -__free_page (page); - } - } -#endif - } -return ret; }fs_initcall (tracer_alloc_buffers);
kernel/trace/trace.h +5 -17
@@ -6,6 +6,7 @@#include <linux/sched.h> #include <linux/clocksource.h> #include <linux/mmiotrace.h> +#include <linux/ring_buffer.h> enum trace_type { __TRACE_FIRST_TYPE =0 ,
@@ -72,7 +73,6 @@ struct trace_entry {char flags;char preempt_count;int pid; -cycle_t t;union {struct ftrace_entry fn;struct ctx_switch_entry ctx;
@@ -91,16 +91,9 @@ struct trace_entry {* the trace, etc.) */ struct trace_array_cpu { -struct list_head trace_pages;atomic_t disabled; -raw_spinlock_t lock; -struct lock_class_key lock_key;/* these fields get copied into max-trace: */ -unsigned trace_head_idx; -unsigned trace_tail_idx; -void *trace_head;/* producer */ -void *trace_tail;/* consumer */ unsigned long trace_idx;unsigned long overrun;unsigned long saved_latency;
@@ -124,6 +117,7 @@ struct trace_iterator;* They have on/off state as well: */ struct trace_array { +struct ring_buffer *buffer;unsigned long entries;long ctrl;int cpu;
@@ -171,26 +165,20 @@ struct trace_iterator {struct trace_array *tr;struct tracer *trace;void *private; -long last_overrun[NR_CPUS ]; -long overrun[NR_CPUS ]; +struct ring_buffer_iter *buffer_iter[NR_CPUS ];/* The below is zeroed out in pipe_read */ struct trace_seq seq;struct trace_entry *ent;int cpu; - -struct trace_entry *prev_ent; -int prev_cpu; +u64 ts;unsigned long iter_flags;loff_t pos; -unsigned long next_idx[NR_CPUS ]; -struct list_head *next_page[NR_CPUS ]; -unsigned next_page_idx[NR_CPUS ];long idx; }; -void tracing_reset (struct trace_array_cpu *data); +void tracing_reset (struct trace_array *tr,int cpu);int tracing_open_generic (struct inode *inode,struct file *filp);struct dentry *tracing_init_dentry (void );void init_tracer_sysprof_debugfs (struct dentry *d_tracer);
kernel/trace/trace_functions.c +1 -1
@@ -23,7 +23,7 @@ static void function_reset(struct trace_ tr->time_start =ftrace_now (tr->cpu);for_each_online_cpu (cpu) -tracing_reset (tr->data[cpu]); +tracing_reset (tr, cpu); }static void start_function_trace (struct trace_array *tr)
kernel/trace/trace_irqsoff.c +3 -3
@@ -173,7 +173,7 @@ out_unlock: out: data->critical_sequence = max_sequence; data->preempt_timestamp =ftrace_now (cpu); -tracing_reset (data); +tracing_reset (tr, cpu);trace_function (tr, data,CALLER_ADDR0 , parent_ip, flags); }
@@ -203,7 +203,7 @@ start_critical_timing(unsigned long ip, data->critical_sequence = max_sequence; data->preempt_timestamp =ftrace_now (cpu); data->critical_start = parent_ip ? : ip; -tracing_reset (data); +tracing_reset (tr, cpu);local_save_flags (flags);
@@ -234,7 +234,7 @@ stop_critical_timing(unsigned long ip, u data = tr->data[cpu]; -if (unlikely (!data) ||unlikely (!head_page (data)) || +if (unlikely (!data) || !data->critical_start ||atomic_read (&data->disabled))return ;
kernel/trace/trace_mmiotrace.c +7 -3
@@ -27,7 +27,7 @@ static void mmio_reset_data(struct trace tr->time_start =ftrace_now (tr->cpu);for_each_online_cpu (cpu) -tracing_reset (tr->data[cpu]); +tracing_reset (tr, cpu); }static void mmio_trace_init (struct trace_array *tr)
@@ -130,10 +130,14 @@ static unsigned long count_overruns(stru {int cpu;unsigned long cnt =0 ; +/* FIXME: */ +#if 0 for_each_online_cpu (cpu) { cnt += iter->overrun[cpu]; iter->overrun[cpu] =0 ; } +#endif + (void )cpu;return cnt; }
@@ -176,7 +180,7 @@ static int mmio_print_rw(struct trace_itstruct trace_entry *entry = iter->ent;struct mmiotrace_rw *rw = &entry->mmiorw;struct trace_seq *s = &iter->seq; -unsigned long long t =ns2usecs (entry->t); +unsigned long long t =ns2usecs (iter->ts);unsigned long usec_rem =do_div (t,1000000ULL );unsigned secs = (unsigned long )t;int ret =1 ;
@@ -218,7 +222,7 @@ static int mmio_print_map(struct trace_istruct trace_entry *entry = iter->ent;struct mmiotrace_map *m = &entry->mmiomap;struct trace_seq *s = &iter->seq; -unsigned long long t =ns2usecs (entry->t); +unsigned long long t =ns2usecs (iter->ts);unsigned long usec_rem =do_div (t,1000000ULL );unsigned secs = (unsigned long )t;int ret =1 ;
kernel/trace/trace_sched_switch.c +1 -1
@@ -133,7 +133,7 @@ static void sched_switch_reset(struct tr tr->time_start =ftrace_now (tr->cpu);for_each_online_cpu (cpu) -tracing_reset (tr->data[cpu]); +tracing_reset (tr, cpu); }static int tracing_sched_register (void )
kernel/trace/trace_sched_wakeup.c +1 -1
@@ -216,7 +216,7 @@ static void __wakeup_reset(struct trace_for_each_possible_cpu (cpu) { data = tr->data[cpu]; -tracing_reset (data); +tracing_reset (tr, cpu); } wakeup_cpu =-1 ;