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>
This commit is contained in:
Steven Rostedt 2008-10-01 11:14:54 -04:00 коммит произвёл Ingo Molnar
Родитель 7104f300c5
Коммит e4c2ce82ca
1 изменённых файлов: 32 добавлений и 22 удалений

Просмотреть файл

@ -115,16 +115,10 @@ void *ring_buffer_event_data(struct ring_buffer_event *event)
* Thanks to Peter Zijlstra for suggesting this idea. * Thanks to Peter Zijlstra for suggesting this idea.
*/ */
struct buffer_page { struct buffer_page {
union { u64 time_stamp; /* page time stamp */
struct { unsigned size; /* size of page data */
unsigned long flags; /* mandatory */ struct list_head list; /* list of free pages */
atomic_t _count; /* mandatory */ void *page; /* Actual data page */
u64 time_stamp; /* page time stamp */
unsigned size; /* size of page data */
struct list_head list; /* list of free pages */
};
struct page page;
};
}; };
/* /*
@ -133,9 +127,9 @@ struct buffer_page {
*/ */
static inline void free_buffer_page(struct buffer_page *bpage) static inline void free_buffer_page(struct buffer_page *bpage)
{ {
reset_page_mapcount(&bpage->page); if (bpage->page)
bpage->page.mapping = NULL; __free_page(bpage->page);
__free_page(&bpage->page); kfree(bpage);
} }
/* /*
@ -237,11 +231,16 @@ static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
unsigned i; unsigned i;
for (i = 0; i < nr_pages; 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); addr = __get_free_page(GFP_KERNEL);
if (!addr) if (!addr)
goto free_pages; goto free_pages;
page = (struct buffer_page *)virt_to_page(addr); page->page = (void *)addr;
list_add(&page->list, &pages);
} }
list_splice(&pages, head); list_splice(&pages, head);
@ -262,6 +261,7 @@ static struct ring_buffer_per_cpu *
rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu) rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu)
{ {
struct ring_buffer_per_cpu *cpu_buffer; struct ring_buffer_per_cpu *cpu_buffer;
struct buffer_page *page;
unsigned long addr; unsigned long addr;
int ret; int ret;
@ -275,10 +275,17 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu)
spin_lock_init(&cpu_buffer->lock); spin_lock_init(&cpu_buffer->lock);
INIT_LIST_HEAD(&cpu_buffer->pages); 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); addr = __get_free_page(GFP_KERNEL);
if (!addr) if (!addr)
goto fail_free_buffer; goto fail_free_reader;
cpu_buffer->reader_page = (struct buffer_page *)virt_to_page(addr); page->page = (void *)addr;
INIT_LIST_HEAD(&cpu_buffer->reader_page->list); INIT_LIST_HEAD(&cpu_buffer->reader_page->list);
cpu_buffer->reader_page->size = 0; cpu_buffer->reader_page->size = 0;
@ -523,11 +530,16 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size)
for_each_buffer_cpu(buffer, cpu) { for_each_buffer_cpu(buffer, cpu) {
for (i = 0; i < new_pages; i++) { 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); addr = __get_free_page(GFP_KERNEL);
if (!addr) if (!addr)
goto free_pages; goto free_pages;
page = (struct buffer_page *)virt_to_page(addr); page->page = (void *)addr;
list_add(&page->list, &pages);
} }
} }
@ -567,9 +579,7 @@ static inline int rb_null_event(struct ring_buffer_event *event)
static inline void *rb_page_index(struct buffer_page *page, unsigned index) static inline void *rb_page_index(struct buffer_page *page, unsigned index)
{ {
void *addr = page_address(&page->page); return page->page + index;
return addr + index;
} }
static inline struct ring_buffer_event * static inline struct ring_buffer_event *