Skip to content

Commit f9b94da

Browse files
tzstoyanovrostedt
authored andcommitted
ring-buffer: Set new size of the ring buffer sub page
There are two approaches when changing the size of the ring buffer sub page: 1. Destroying all pages and allocating new pages with the new size. 2. Allocating new pages, copying the content of the old pages before destroying them. The first approach is easier, it is selected in the proposed implementation. Changing the ring buffer sub page size is supposed to not happen frequently. Usually, that size should be set only once, when the buffer is not in use yet and is supposed to be empty. Link: https://lore.kernel.org/linux-trace-devel/[email protected] Link: https://lore.kernel.org/linux-trace-kernel/[email protected] Cc: Masami Hiramatsu <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Mathieu Desnoyers <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Vincent Donnefort <[email protected]> Cc: Kent Overstreet <[email protected]> Signed-off-by: Tzvetomir Stoyanov (VMware) <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent 2808e31 commit f9b94da

File tree

1 file changed

+73
-7
lines changed

1 file changed

+73
-7
lines changed

kernel/trace/ring_buffer.c

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ struct buffer_page {
332332
unsigned read; /* index for next read */
333333
local_t entries; /* entries on this page */
334334
unsigned long real_end; /* real end of data */
335+
unsigned order; /* order of the page */
335336
struct buffer_data_page *page; /* Actual data page */
336337
};
337338

@@ -362,7 +363,7 @@ static __always_inline unsigned int rb_page_commit(struct buffer_page *bpage)
362363

363364
static void free_buffer_page(struct buffer_page *bpage)
364365
{
365-
free_page((unsigned long)bpage->page);
366+
free_pages((unsigned long)bpage->page, bpage->order);
366367
kfree(bpage);
367368
}
368369

@@ -1460,10 +1461,12 @@ static int __rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
14601461

14611462
list_add(&bpage->list, pages);
14621463

1463-
page = alloc_pages_node(cpu_to_node(cpu_buffer->cpu), mflags, 0);
1464+
page = alloc_pages_node(cpu_to_node(cpu_buffer->cpu), mflags,
1465+
cpu_buffer->buffer->subbuf_order);
14641466
if (!page)
14651467
goto free_pages;
14661468
bpage->page = page_address(page);
1469+
bpage->order = cpu_buffer->buffer->subbuf_order;
14671470
rb_init_page(bpage->page);
14681471

14691472
if (user_thread && fatal_signal_pending(current))
@@ -1542,7 +1545,8 @@ rb_allocate_cpu_buffer(struct trace_buffer *buffer, long nr_pages, int cpu)
15421545
rb_check_bpage(cpu_buffer, bpage);
15431546

15441547
cpu_buffer->reader_page = bpage;
1545-
page = alloc_pages_node(cpu_to_node(cpu), GFP_KERNEL, 0);
1548+
1549+
page = alloc_pages_node(cpu_to_node(cpu), GFP_KERNEL, cpu_buffer->buffer->subbuf_order);
15461550
if (!page)
15471551
goto fail_free_reader;
15481552
bpage->page = page_address(page);
@@ -1626,6 +1630,7 @@ struct trace_buffer *__ring_buffer_alloc(unsigned long size, unsigned flags,
16261630
goto fail_free_buffer;
16271631

16281632
/* Default buffer page size - one system page */
1633+
buffer->subbuf_order = 0;
16291634
buffer->subbuf_size = PAGE_SIZE - BUF_PAGE_HDR_SIZE;
16301635

16311636
/* Max payload is buffer page size - header (8bytes) */
@@ -5503,8 +5508,8 @@ void *ring_buffer_alloc_read_page(struct trace_buffer *buffer, int cpu)
55035508
if (bpage)
55045509
goto out;
55055510

5506-
page = alloc_pages_node(cpu_to_node(cpu),
5507-
GFP_KERNEL | __GFP_NORETRY, 0);
5511+
page = alloc_pages_node(cpu_to_node(cpu), GFP_KERNEL | __GFP_NORETRY,
5512+
cpu_buffer->buffer->subbuf_order);
55085513
if (!page)
55095514
return ERR_PTR(-ENOMEM);
55105515

@@ -5553,7 +5558,7 @@ void ring_buffer_free_read_page(struct trace_buffer *buffer, int cpu, void *data
55535558
local_irq_restore(flags);
55545559

55555560
out:
5556-
free_page((unsigned long)bpage);
5561+
free_pages((unsigned long)bpage, buffer->subbuf_order);
55575562
}
55585563
EXPORT_SYMBOL_GPL(ring_buffer_free_read_page);
55595564

@@ -5813,7 +5818,13 @@ EXPORT_SYMBOL_GPL(ring_buffer_subbuf_order_get);
58135818
*/
58145819
int ring_buffer_subbuf_order_set(struct trace_buffer *buffer, int order)
58155820
{
5821+
struct ring_buffer_per_cpu **cpu_buffers;
5822+
int old_order, old_size;
5823+
int nr_pages;
58165824
int psize;
5825+
int bsize;
5826+
int err;
5827+
int cpu;
58175828

58185829
if (!buffer || order < 0)
58195830
return -EINVAL;
@@ -5825,12 +5836,67 @@ int ring_buffer_subbuf_order_set(struct trace_buffer *buffer, int order)
58255836
if (psize <= BUF_PAGE_HDR_SIZE)
58265837
return -EINVAL;
58275838

5839+
bsize = sizeof(void *) * buffer->cpus;
5840+
cpu_buffers = kzalloc(bsize, GFP_KERNEL);
5841+
if (!cpu_buffers)
5842+
return -ENOMEM;
5843+
5844+
old_order = buffer->subbuf_order;
5845+
old_size = buffer->subbuf_size;
5846+
5847+
/* prevent another thread from changing buffer sizes */
5848+
mutex_lock(&buffer->mutex);
5849+
atomic_inc(&buffer->record_disabled);
5850+
5851+
/* Make sure all commits have finished */
5852+
synchronize_rcu();
5853+
58285854
buffer->subbuf_order = order;
58295855
buffer->subbuf_size = psize - BUF_PAGE_HDR_SIZE;
58305856

5831-
/* Todo: reset the buffer with the new page size */
5857+
/* Make sure all new buffers are allocated, before deleting the old ones */
5858+
for_each_buffer_cpu(buffer, cpu) {
5859+
if (!cpumask_test_cpu(cpu, buffer->cpumask))
5860+
continue;
5861+
5862+
nr_pages = buffer->buffers[cpu]->nr_pages;
5863+
cpu_buffers[cpu] = rb_allocate_cpu_buffer(buffer, nr_pages, cpu);
5864+
if (!cpu_buffers[cpu]) {
5865+
err = -ENOMEM;
5866+
goto error;
5867+
}
5868+
}
5869+
5870+
for_each_buffer_cpu(buffer, cpu) {
5871+
if (!cpumask_test_cpu(cpu, buffer->cpumask))
5872+
continue;
5873+
5874+
rb_free_cpu_buffer(buffer->buffers[cpu]);
5875+
buffer->buffers[cpu] = cpu_buffers[cpu];
5876+
}
5877+
5878+
atomic_dec(&buffer->record_disabled);
5879+
mutex_unlock(&buffer->mutex);
5880+
5881+
kfree(cpu_buffers);
58325882

58335883
return 0;
5884+
5885+
error:
5886+
buffer->subbuf_order = old_order;
5887+
buffer->subbuf_size = old_size;
5888+
5889+
atomic_dec(&buffer->record_disabled);
5890+
mutex_unlock(&buffer->mutex);
5891+
5892+
for_each_buffer_cpu(buffer, cpu) {
5893+
if (!cpu_buffers[cpu])
5894+
continue;
5895+
kfree(cpu_buffers[cpu]);
5896+
}
5897+
kfree(cpu_buffers);
5898+
5899+
return err;
58345900
}
58355901
EXPORT_SYMBOL_GPL(ring_buffer_subbuf_order_set);
58365902

0 commit comments

Comments
 (0)