Skip to content

Commit 8789a9e

Browse files
Steven RostedtIngo Molnar
authored andcommitted
ring-buffer: read page interface
Impact: new API to ring buffer This patch adds a new interface into the ring buffer that allows a page to be read from the ring buffer on a given CPU. For every page read, one must also be given to allow for a "swap" of the pages. rpage = ring_buffer_alloc_read_page(buffer); if (!rpage) goto err; ret = ring_buffer_read_page(buffer, &rpage, cpu, full); if (!ret) goto empty; process_page(rpage); ring_buffer_free_read_page(rpage); The caller of these functions must handle any waits that are needed to wait for new data. The ring_buffer_read_page will simply return 0 if there is no data, or if "full" is set and the writer is still on the current page. Signed-off-by: Steven Rostedt <[email protected]> Signed-off-by: Ingo Molnar <[email protected]>
1 parent abc9b56 commit 8789a9e

File tree

2 files changed

+171
-0
lines changed

2 files changed

+171
-0
lines changed

include/linux/ring_buffer.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ void tracing_on(void);
124124
void tracing_off(void);
125125
void tracing_off_permanent(void);
126126

127+
void *ring_buffer_alloc_read_page(struct ring_buffer *buffer);
128+
void ring_buffer_free_read_page(struct ring_buffer *buffer, void *data);
129+
int ring_buffer_read_page(struct ring_buffer *buffer,
130+
void **data_page, int cpu, int full);
131+
127132
enum ring_buffer_flags {
128133
RB_FL_OVERWRITE = 1 << 0,
129134
};

kernel/trace/ring_buffer.c

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,12 @@ static inline int rb_null_event(struct ring_buffer_event *event)
687687
return event->type == RINGBUF_TYPE_PADDING;
688688
}
689689

690+
static inline void *
691+
__rb_data_page_index(struct buffer_data_page *page, unsigned index)
692+
{
693+
return page->data + index;
694+
}
695+
690696
static inline void *__rb_page_index(struct buffer_page *page, unsigned index)
691697
{
692698
return page->page->data + index;
@@ -2232,6 +2238,166 @@ int ring_buffer_swap_cpu(struct ring_buffer *buffer_a,
22322238
return 0;
22332239
}
22342240

2241+
static void rb_remove_entries(struct ring_buffer_per_cpu *cpu_buffer,
2242+
struct buffer_data_page *page)
2243+
{
2244+
struct ring_buffer_event *event;
2245+
unsigned long head;
2246+
2247+
__raw_spin_lock(&cpu_buffer->lock);
2248+
for (head = 0; head < local_read(&page->commit);
2249+
head += rb_event_length(event)) {
2250+
2251+
event = __rb_data_page_index(page, head);
2252+
if (RB_WARN_ON(cpu_buffer, rb_null_event(event)))
2253+
return;
2254+
/* Only count data entries */
2255+
if (event->type != RINGBUF_TYPE_DATA)
2256+
continue;
2257+
cpu_buffer->entries--;
2258+
}
2259+
__raw_spin_unlock(&cpu_buffer->lock);
2260+
}
2261+
2262+
/**
2263+
* ring_buffer_alloc_read_page - allocate a page to read from buffer
2264+
* @buffer: the buffer to allocate for.
2265+
*
2266+
* This function is used in conjunction with ring_buffer_read_page.
2267+
* When reading a full page from the ring buffer, these functions
2268+
* can be used to speed up the process. The calling function should
2269+
* allocate a few pages first with this function. Then when it
2270+
* needs to get pages from the ring buffer, it passes the result
2271+
* of this function into ring_buffer_read_page, which will swap
2272+
* the page that was allocated, with the read page of the buffer.
2273+
*
2274+
* Returns:
2275+
* The page allocated, or NULL on error.
2276+
*/
2277+
void *ring_buffer_alloc_read_page(struct ring_buffer *buffer)
2278+
{
2279+
unsigned long addr;
2280+
struct buffer_data_page *page;
2281+
2282+
addr = __get_free_page(GFP_KERNEL);
2283+
if (!addr)
2284+
return NULL;
2285+
2286+
page = (void *)addr;
2287+
2288+
return page;
2289+
}
2290+
2291+
/**
2292+
* ring_buffer_free_read_page - free an allocated read page
2293+
* @buffer: the buffer the page was allocate for
2294+
* @data: the page to free
2295+
*
2296+
* Free a page allocated from ring_buffer_alloc_read_page.
2297+
*/
2298+
void ring_buffer_free_read_page(struct ring_buffer *buffer, void *data)
2299+
{
2300+
free_page((unsigned long)data);
2301+
}
2302+
2303+
/**
2304+
* ring_buffer_read_page - extract a page from the ring buffer
2305+
* @buffer: buffer to extract from
2306+
* @data_page: the page to use allocated from ring_buffer_alloc_read_page
2307+
* @cpu: the cpu of the buffer to extract
2308+
* @full: should the extraction only happen when the page is full.
2309+
*
2310+
* This function will pull out a page from the ring buffer and consume it.
2311+
* @data_page must be the address of the variable that was returned
2312+
* from ring_buffer_alloc_read_page. This is because the page might be used
2313+
* to swap with a page in the ring buffer.
2314+
*
2315+
* for example:
2316+
* rpage = ring_buffer_alloc_page(buffer);
2317+
* if (!rpage)
2318+
* return error;
2319+
* ret = ring_buffer_read_page(buffer, &rpage, cpu, 0);
2320+
* if (ret)
2321+
* process_page(rpage);
2322+
*
2323+
* When @full is set, the function will not return true unless
2324+
* the writer is off the reader page.
2325+
*
2326+
* Note: it is up to the calling functions to handle sleeps and wakeups.
2327+
* The ring buffer can be used anywhere in the kernel and can not
2328+
* blindly call wake_up. The layer that uses the ring buffer must be
2329+
* responsible for that.
2330+
*
2331+
* Returns:
2332+
* 1 if data has been transferred
2333+
* 0 if no data has been transferred.
2334+
*/
2335+
int ring_buffer_read_page(struct ring_buffer *buffer,
2336+
void **data_page, int cpu, int full)
2337+
{
2338+
struct ring_buffer_per_cpu *cpu_buffer = buffer->buffers[cpu];
2339+
struct ring_buffer_event *event;
2340+
struct buffer_data_page *page;
2341+
unsigned long flags;
2342+
int ret = 0;
2343+
2344+
if (!data_page)
2345+
return 0;
2346+
2347+
page = *data_page;
2348+
if (!page)
2349+
return 0;
2350+
2351+
spin_lock_irqsave(&cpu_buffer->reader_lock, flags);
2352+
2353+
/*
2354+
* rb_buffer_peek will get the next ring buffer if
2355+
* the current reader page is empty.
2356+
*/
2357+
event = rb_buffer_peek(buffer, cpu, NULL);
2358+
if (!event)
2359+
goto out;
2360+
2361+
/* check for data */
2362+
if (!local_read(&cpu_buffer->reader_page->page->commit))
2363+
goto out;
2364+
/*
2365+
* If the writer is already off of the read page, then simply
2366+
* switch the read page with the given page. Otherwise
2367+
* we need to copy the data from the reader to the writer.
2368+
*/
2369+
if (cpu_buffer->reader_page == cpu_buffer->commit_page) {
2370+
unsigned int read = cpu_buffer->reader_page->read;
2371+
2372+
if (full)
2373+
goto out;
2374+
/* The writer is still on the reader page, we must copy */
2375+
page = cpu_buffer->reader_page->page;
2376+
memcpy(page->data,
2377+
cpu_buffer->reader_page->page->data + read,
2378+
local_read(&page->commit) - read);
2379+
2380+
/* consume what was read */
2381+
cpu_buffer->reader_page += read;
2382+
2383+
} else {
2384+
/* swap the pages */
2385+
rb_init_page(page);
2386+
page = cpu_buffer->reader_page->page;
2387+
cpu_buffer->reader_page->page = *data_page;
2388+
cpu_buffer->reader_page->read = 0;
2389+
*data_page = page;
2390+
}
2391+
ret = 1;
2392+
2393+
/* update the entry counter */
2394+
rb_remove_entries(cpu_buffer, page);
2395+
out:
2396+
spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
2397+
2398+
return ret;
2399+
}
2400+
22352401
static ssize_t
22362402
rb_simple_read(struct file *filp, char __user *ubuf,
22372403
size_t cnt, loff_t *ppos)

0 commit comments

Comments
 (0)