diff options
Diffstat (limited to 'kernel/trace/ring_buffer.c')
-rw-r--r-- | kernel/trace/ring_buffer.c | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index ca47a4fa2986..4ae268e687fe 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -438,6 +438,7 @@ struct ring_buffer_per_cpu { | |||
438 | raw_spinlock_t reader_lock; /* serialize readers */ | 438 | raw_spinlock_t reader_lock; /* serialize readers */ |
439 | arch_spinlock_t lock; | 439 | arch_spinlock_t lock; |
440 | struct lock_class_key lock_key; | 440 | struct lock_class_key lock_key; |
441 | struct buffer_data_page *free_page; | ||
441 | unsigned long nr_pages; | 442 | unsigned long nr_pages; |
442 | unsigned int current_context; | 443 | unsigned int current_context; |
443 | struct list_head *pages; | 444 | struct list_head *pages; |
@@ -4389,9 +4390,25 @@ EXPORT_SYMBOL_GPL(ring_buffer_swap_cpu); | |||
4389 | */ | 4390 | */ |
4390 | void *ring_buffer_alloc_read_page(struct ring_buffer *buffer, int cpu) | 4391 | void *ring_buffer_alloc_read_page(struct ring_buffer *buffer, int cpu) |
4391 | { | 4392 | { |
4392 | struct buffer_data_page *bpage; | 4393 | struct ring_buffer_per_cpu *cpu_buffer = buffer->buffers[cpu]; |
4394 | struct buffer_data_page *bpage = NULL; | ||
4395 | unsigned long flags; | ||
4393 | struct page *page; | 4396 | struct page *page; |
4394 | 4397 | ||
4398 | local_irq_save(flags); | ||
4399 | arch_spin_lock(&cpu_buffer->lock); | ||
4400 | |||
4401 | if (cpu_buffer->free_page) { | ||
4402 | bpage = cpu_buffer->free_page; | ||
4403 | cpu_buffer->free_page = NULL; | ||
4404 | } | ||
4405 | |||
4406 | arch_spin_unlock(&cpu_buffer->lock); | ||
4407 | local_irq_restore(flags); | ||
4408 | |||
4409 | if (bpage) | ||
4410 | goto out; | ||
4411 | |||
4395 | page = alloc_pages_node(cpu_to_node(cpu), | 4412 | page = alloc_pages_node(cpu_to_node(cpu), |
4396 | GFP_KERNEL | __GFP_NORETRY, 0); | 4413 | GFP_KERNEL | __GFP_NORETRY, 0); |
4397 | if (!page) | 4414 | if (!page) |
@@ -4399,6 +4416,7 @@ void *ring_buffer_alloc_read_page(struct ring_buffer *buffer, int cpu) | |||
4399 | 4416 | ||
4400 | bpage = page_address(page); | 4417 | bpage = page_address(page); |
4401 | 4418 | ||
4419 | out: | ||
4402 | rb_init_page(bpage); | 4420 | rb_init_page(bpage); |
4403 | 4421 | ||
4404 | return bpage; | 4422 | return bpage; |
@@ -4408,13 +4426,29 @@ EXPORT_SYMBOL_GPL(ring_buffer_alloc_read_page); | |||
4408 | /** | 4426 | /** |
4409 | * ring_buffer_free_read_page - free an allocated read page | 4427 | * ring_buffer_free_read_page - free an allocated read page |
4410 | * @buffer: the buffer the page was allocate for | 4428 | * @buffer: the buffer the page was allocate for |
4429 | * @cpu: the cpu buffer the page came from | ||
4411 | * @data: the page to free | 4430 | * @data: the page to free |
4412 | * | 4431 | * |
4413 | * Free a page allocated from ring_buffer_alloc_read_page. | 4432 | * Free a page allocated from ring_buffer_alloc_read_page. |
4414 | */ | 4433 | */ |
4415 | void ring_buffer_free_read_page(struct ring_buffer *buffer, void *data) | 4434 | void ring_buffer_free_read_page(struct ring_buffer *buffer, int cpu, void *data) |
4416 | { | 4435 | { |
4417 | free_page((unsigned long)data); | 4436 | struct ring_buffer_per_cpu *cpu_buffer = buffer->buffers[cpu]; |
4437 | struct buffer_data_page *bpage = data; | ||
4438 | unsigned long flags; | ||
4439 | |||
4440 | local_irq_save(flags); | ||
4441 | arch_spin_lock(&cpu_buffer->lock); | ||
4442 | |||
4443 | if (!cpu_buffer->free_page) { | ||
4444 | cpu_buffer->free_page = bpage; | ||
4445 | bpage = NULL; | ||
4446 | } | ||
4447 | |||
4448 | arch_spin_unlock(&cpu_buffer->lock); | ||
4449 | local_irq_restore(flags); | ||
4450 | |||
4451 | free_page((unsigned long)bpage); | ||
4418 | } | 4452 | } |
4419 | EXPORT_SYMBOL_GPL(ring_buffer_free_read_page); | 4453 | EXPORT_SYMBOL_GPL(ring_buffer_free_read_page); |
4420 | 4454 | ||