Skip to content

Commit 2808e31

Browse files
tzstoyanovrostedt
authored andcommitted
ring-buffer: Add interface for configuring trace sub buffer size
The trace ring buffer sub page size can be configured, per trace instance. A new ftrace file "buffer_subbuf_order" is added to get and set the size of the ring buffer sub page for current trace instance. The size must be an order of system page size, that's why the new interface works with system page order, instead of absolute page size: 0 means the ring buffer sub page is equal to 1 system page and so forth: 0 - 1 system page 1 - 2 system pages 2 - 4 system pages ... The ring buffer sub page size is limited between 1 and 128 system pages. The default value is 1 system page. New ring buffer APIs are introduced: ring_buffer_subbuf_order_set() ring_buffer_subbuf_order_get() ring_buffer_subbuf_size_get() 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 139f840 commit 2808e31

File tree

3 files changed

+125
-0
lines changed

3 files changed

+125
-0
lines changed

include/linux/ring_buffer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,10 @@ struct trace_seq;
202202
int ring_buffer_print_entry_header(struct trace_seq *s);
203203
int ring_buffer_print_page_header(struct trace_buffer *buffer, struct trace_seq *s);
204204

205+
int ring_buffer_subbuf_order_get(struct trace_buffer *buffer);
206+
int ring_buffer_subbuf_order_set(struct trace_buffer *buffer, int order);
207+
int ring_buffer_subbuf_size_get(struct trace_buffer *buffer);
208+
205209
enum ring_buffer_flags {
206210
RB_FL_OVERWRITE = 1 << 0,
207211
};

kernel/trace/ring_buffer.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ struct trace_buffer {
507507
bool time_stamp_abs;
508508

509509
unsigned int subbuf_size;
510+
unsigned int subbuf_order;
510511
unsigned int max_data_size;
511512
};
512513

@@ -5761,6 +5762,78 @@ int ring_buffer_read_page(struct trace_buffer *buffer,
57615762
}
57625763
EXPORT_SYMBOL_GPL(ring_buffer_read_page);
57635764

5765+
/**
5766+
* ring_buffer_subbuf_size_get - get size of the sub buffer.
5767+
* @buffer: the buffer to get the sub buffer size from
5768+
*
5769+
* Returns size of the sub buffer, in bytes.
5770+
*/
5771+
int ring_buffer_subbuf_size_get(struct trace_buffer *buffer)
5772+
{
5773+
return buffer->subbuf_size + BUF_PAGE_HDR_SIZE;
5774+
}
5775+
EXPORT_SYMBOL_GPL(ring_buffer_subbuf_size_get);
5776+
5777+
/**
5778+
* ring_buffer_subbuf_order_get - get order of system sub pages in one buffer page.
5779+
* @buffer: The ring_buffer to get the system sub page order from
5780+
*
5781+
* By default, one ring buffer sub page equals to one system page. This parameter
5782+
* is configurable, per ring buffer. The size of the ring buffer sub page can be
5783+
* extended, but must be an order of system page size.
5784+
*
5785+
* Returns the order of buffer sub page size, in system pages:
5786+
* 0 means the sub buffer size is 1 system page and so forth.
5787+
* In case of an error < 0 is returned.
5788+
*/
5789+
int ring_buffer_subbuf_order_get(struct trace_buffer *buffer)
5790+
{
5791+
if (!buffer)
5792+
return -EINVAL;
5793+
5794+
return buffer->subbuf_order;
5795+
}
5796+
EXPORT_SYMBOL_GPL(ring_buffer_subbuf_order_get);
5797+
5798+
/**
5799+
* ring_buffer_subbuf_order_set - set the size of ring buffer sub page.
5800+
* @buffer: The ring_buffer to set the new page size.
5801+
* @order: Order of the system pages in one sub buffer page
5802+
*
5803+
* By default, one ring buffer pages equals to one system page. This API can be
5804+
* used to set new size of the ring buffer page. The size must be order of
5805+
* system page size, that's why the input parameter @order is the order of
5806+
* system pages that are allocated for one ring buffer page:
5807+
* 0 - 1 system page
5808+
* 1 - 2 system pages
5809+
* 3 - 4 system pages
5810+
* ...
5811+
*
5812+
* Returns 0 on success or < 0 in case of an error.
5813+
*/
5814+
int ring_buffer_subbuf_order_set(struct trace_buffer *buffer, int order)
5815+
{
5816+
int psize;
5817+
5818+
if (!buffer || order < 0)
5819+
return -EINVAL;
5820+
5821+
if (buffer->subbuf_order == order)
5822+
return 0;
5823+
5824+
psize = (1 << order) * PAGE_SIZE;
5825+
if (psize <= BUF_PAGE_HDR_SIZE)
5826+
return -EINVAL;
5827+
5828+
buffer->subbuf_order = order;
5829+
buffer->subbuf_size = psize - BUF_PAGE_HDR_SIZE;
5830+
5831+
/* Todo: reset the buffer with the new page size */
5832+
5833+
return 0;
5834+
}
5835+
EXPORT_SYMBOL_GPL(ring_buffer_subbuf_order_set);
5836+
57645837
/*
57655838
* We only allocate new buffers, never free them if the CPU goes down.
57665839
* If we were to free the buffer, then the user would lose any trace that was in

kernel/trace/trace.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9358,6 +9358,51 @@ static const struct file_operations buffer_percent_fops = {
93589358
.llseek = default_llseek,
93599359
};
93609360

9361+
static ssize_t
9362+
buffer_order_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
9363+
{
9364+
struct trace_array *tr = filp->private_data;
9365+
char buf[64];
9366+
int r;
9367+
9368+
r = sprintf(buf, "%d\n", ring_buffer_subbuf_order_get(tr->array_buffer.buffer));
9369+
9370+
return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
9371+
}
9372+
9373+
static ssize_t
9374+
buffer_order_write(struct file *filp, const char __user *ubuf,
9375+
size_t cnt, loff_t *ppos)
9376+
{
9377+
struct trace_array *tr = filp->private_data;
9378+
unsigned long val;
9379+
int ret;
9380+
9381+
ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
9382+
if (ret)
9383+
return ret;
9384+
9385+
/* limit between 1 and 128 system pages */
9386+
if (val < 0 || val > 7)
9387+
return -EINVAL;
9388+
9389+
ret = ring_buffer_subbuf_order_set(tr->array_buffer.buffer, val);
9390+
if (ret)
9391+
return ret;
9392+
9393+
(*ppos)++;
9394+
9395+
return cnt;
9396+
}
9397+
9398+
static const struct file_operations buffer_order_fops = {
9399+
.open = tracing_open_generic_tr,
9400+
.read = buffer_order_read,
9401+
.write = buffer_order_write,
9402+
.release = tracing_release_generic_tr,
9403+
.llseek = default_llseek,
9404+
};
9405+
93619406
static struct dentry *trace_instance_dir;
93629407

93639408
static void
@@ -9824,6 +9869,9 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
98249869
trace_create_file("buffer_percent", TRACE_MODE_WRITE, d_tracer,
98259870
tr, &buffer_percent_fops);
98269871

9872+
trace_create_file("buffer_subbuf_order", TRACE_MODE_WRITE, d_tracer,
9873+
tr, &buffer_order_fops);
9874+
98279875
create_trace_options_dir(tr);
98289876

98299877
#ifdef CONFIG_TRACER_MAX_TRACE

0 commit comments

Comments
 (0)