diff options
| author | Steven Rostedt <rostedt@goodmis.org> | 2008-10-01 11:14:54 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-10-14 04:39:08 -0400 |
| commit | e4c2ce82ca2710e17cb4df8eb2b249fa2eb5af30 (patch) | |
| tree | 186a96aa4cace7fe51ede64c8b4f426a5007f007 /kernel | |
| parent | 7104f300c5a69b46dda00d898034dd05c9f21739 (diff) | |
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.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/trace/ring_buffer.c | 54 |
1 files changed, 32 insertions, 22 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 9631abf2ae29..98145718988d 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
| @@ -115,16 +115,10 @@ void *ring_buffer_event_data(struct ring_buffer_event *event) | |||
| 115 | * Thanks to Peter Zijlstra for suggesting this idea. | 115 | * Thanks to Peter Zijlstra for suggesting this idea. |
| 116 | */ | 116 | */ |
| 117 | struct buffer_page { | 117 | struct buffer_page { |
| 118 | union { | 118 | u64 time_stamp; /* page time stamp */ |
| 119 | struct { | 119 | unsigned size; /* size of page data */ |
| 120 | unsigned long flags; /* mandatory */ | 120 | struct list_head list; /* list of free pages */ |
| 121 | atomic_t _count; /* mandatory */ | 121 | void *page; /* Actual data page */ |
| 122 | u64 time_stamp; /* page time stamp */ | ||
| 123 | unsigned size; /* size of page data */ | ||
| 124 | struct list_head list; /* list of free pages */ | ||
| 125 | }; | ||
| 126 | struct page page; | ||
| 127 | }; | ||
| 128 | }; | 122 | }; |
| 129 | 123 | ||
| 130 | /* | 124 | /* |
| @@ -133,9 +127,9 @@ struct buffer_page { | |||
| 133 | */ | 127 | */ |
| 134 | static inline void free_buffer_page(struct buffer_page *bpage) | 128 | static inline void free_buffer_page(struct buffer_page *bpage) |
| 135 | { | 129 | { |
| 136 | reset_page_mapcount(&bpage->page); | 130 | if (bpage->page) |
| 137 | bpage->page.mapping = NULL; | 131 | __free_page(bpage->page); |
| 138 | __free_page(&bpage->page); | 132 | kfree(bpage); |
| 139 | } | 133 | } |
| 140 | 134 | ||
| 141 | /* | 135 | /* |
| @@ -237,11 +231,16 @@ static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer, | |||
| 237 | unsigned i; | 231 | unsigned i; |
| 238 | 232 | ||
| 239 | for (i = 0; i < nr_pages; i++) { | 233 | for (i = 0; i < nr_pages; i++) { |
| 234 | page = kzalloc_node(ALIGN(sizeof(*page), cache_line_size()), | ||
| 235 | GFP_KERNEL, cpu_to_node(cpu)); | ||
| 236 | if (!page) | ||
| 237 | goto free_pages; | ||
| 238 | list_add(&page->list, &pages); | ||
| 239 | |||
| 240 | addr = __get_free_page(GFP_KERNEL); | 240 | addr = __get_free_page(GFP_KERNEL); |
| 241 | if (!addr) | 241 | if (!addr) |
| 242 | goto free_pages; | 242 | goto free_pages; |
| 243 | page = (struct buffer_page *)virt_to_page(addr); | 243 | page->page = (void *)addr; |
| 244 | list_add(&page->list, &pages); | ||
| 245 | } | 244 | } |
| 246 | 245 | ||
| 247 | list_splice(&pages, head); | 246 | list_splice(&pages, head); |
| @@ -262,6 +261,7 @@ static struct ring_buffer_per_cpu * | |||
| 262 | rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu) | 261 | rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu) |
| 263 | { | 262 | { |
| 264 | struct ring_buffer_per_cpu *cpu_buffer; | 263 | struct ring_buffer_per_cpu *cpu_buffer; |
| 264 | struct buffer_page *page; | ||
| 265 | unsigned long addr; | 265 | unsigned long addr; |
| 266 | int ret; | 266 | int ret; |
| 267 | 267 | ||
| @@ -275,10 +275,17 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu) | |||
| 275 | spin_lock_init(&cpu_buffer->lock); | 275 | spin_lock_init(&cpu_buffer->lock); |
| 276 | INIT_LIST_HEAD(&cpu_buffer->pages); | 276 | INIT_LIST_HEAD(&cpu_buffer->pages); |
| 277 | 277 | ||
| 278 | page = kzalloc_node(ALIGN(sizeof(*page), cache_line_size()), | ||
| 279 | GFP_KERNEL, cpu_to_node(cpu)); | ||
| 280 | if (!page) | ||
| 281 | goto fail_free_buffer; | ||
| 282 | |||
| 283 | cpu_buffer->reader_page = page; | ||
| 278 | addr = __get_free_page(GFP_KERNEL); | 284 | addr = __get_free_page(GFP_KERNEL); |
| 279 | if (!addr) | 285 | if (!addr) |
| 280 | goto fail_free_buffer; | 286 | goto fail_free_reader; |
| 281 | cpu_buffer->reader_page = (struct buffer_page *)virt_to_page(addr); | 287 | page->page = (void *)addr; |
| 288 | |||
| 282 | INIT_LIST_HEAD(&cpu_buffer->reader_page->list); | 289 | INIT_LIST_HEAD(&cpu_buffer->reader_page->list); |
| 283 | cpu_buffer->reader_page->size = 0; | 290 | cpu_buffer->reader_page->size = 0; |
| 284 | 291 | ||
| @@ -523,11 +530,16 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size) | |||
| 523 | 530 | ||
| 524 | for_each_buffer_cpu(buffer, cpu) { | 531 | for_each_buffer_cpu(buffer, cpu) { |
| 525 | for (i = 0; i < new_pages; i++) { | 532 | for (i = 0; i < new_pages; i++) { |
| 533 | page = kzalloc_node(ALIGN(sizeof(*page), | ||
| 534 | cache_line_size()), | ||
| 535 | GFP_KERNEL, cpu_to_node(cpu)); | ||
| 536 | if (!page) | ||
| 537 | goto free_pages; | ||
| 538 | list_add(&page->list, &pages); | ||
| 526 | addr = __get_free_page(GFP_KERNEL); | 539 | addr = __get_free_page(GFP_KERNEL); |
| 527 | if (!addr) | 540 | if (!addr) |
| 528 | goto free_pages; | 541 | goto free_pages; |
| 529 | page = (struct buffer_page *)virt_to_page(addr); | 542 | page->page = (void *)addr; |
| 530 | list_add(&page->list, &pages); | ||
| 531 | } | 543 | } |
| 532 | } | 544 | } |
| 533 | 545 | ||
| @@ -567,9 +579,7 @@ static inline int rb_null_event(struct ring_buffer_event *event) | |||
| 567 | 579 | ||
| 568 | static inline void *rb_page_index(struct buffer_page *page, unsigned index) | 580 | static inline void *rb_page_index(struct buffer_page *page, unsigned index) |
| 569 | { | 581 | { |
| 570 | void *addr = page_address(&page->page); | 582 | return page->page + index; |
| 571 | |||
| 572 | return addr + index; | ||
| 573 | } | 583 | } |
| 574 | 584 | ||
| 575 | static inline struct ring_buffer_event * | 585 | static inline struct ring_buffer_event * |
