• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _LINUX_RING_BUFFER_EXT_H
3 #define _LINUX_RING_BUFFER_EXT_H
4 #include <linux/mm.h>
5 #include <linux/types.h>
6 
7 struct rb_ext_stats {
8 	u64		entries;
9 	unsigned long	pages_touched;
10 	unsigned long	overrun;
11 };
12 
13 #define RB_PAGE_FT_HEAD		(1 << 0)
14 #define RB_PAGE_FT_READER	(1 << 1)
15 #define RB_PAGE_FT_COMMIT	(1 << 2)
16 
17 /*
18  * The pages where the events are stored are the only shared elements between
19  * the reader and the external writer. They are convenient to enable
20  * communication from the writer to the reader. The data will be used by the
21  * reader to update its view on the ring buffer.
22  */
23 struct rb_ext_page_footer {
24 	atomic_t		writer_status;
25 	atomic_t		reader_status;
26 	struct rb_ext_stats	stats;
27 };
28 
rb_ext_page_get_footer(void * page)29 static inline struct rb_ext_page_footer *rb_ext_page_get_footer(void *page)
30 {
31 	struct rb_ext_page_footer *footer;
32 	unsigned long page_va = (unsigned long)page;
33 
34 	page_va	= ALIGN_DOWN(page_va, PAGE_SIZE);
35 
36 	return (struct rb_ext_page_footer *)(page_va + PAGE_SIZE -
37 					     sizeof(*footer));
38 }
39 
40 #define BUF_EXT_PAGE_SIZE (BUF_PAGE_SIZE - sizeof(struct rb_ext_page_footer))
41 
42 /*
43  * An external writer can't rely on the internal struct ring_buffer_per_cpu.
44  * Instead, allow to pack the relevant information into struct
45  * ring_buffer_pack which can be sent to the writer. The latter can then create
46  * its own view on the ring buffer.
47  */
48 struct ring_buffer_pack {
49 	int		cpu;
50 	unsigned long	reader_page_va;
51 	unsigned long	nr_pages;
52 	unsigned long	page_va[];
53 };
54 
55 struct trace_buffer_pack {
56 	int			nr_cpus;
57 	unsigned long		total_pages;
58 	char			__data[];	/* contains ring_buffer_pack */
59 };
60 
61 static inline
__next_ring_buffer_pack(struct ring_buffer_pack * rb_pack)62 struct ring_buffer_pack *__next_ring_buffer_pack(struct ring_buffer_pack *rb_pack)
63 {
64 	size_t len;
65 
66 	len = offsetof(struct ring_buffer_pack, page_va) +
67 		       sizeof(unsigned long) * rb_pack->nr_pages;
68 
69 	return (struct ring_buffer_pack *)((void *)rb_pack + len);
70 }
71 
72 /*
73  * Accessor for ring_buffer_pack's within trace_buffer_pack
74  */
75 #define for_each_ring_buffer_pack(rb_pack, cpu, trace_pack)		\
76 	for (rb_pack = (struct ring_buffer_pack *)&trace_pack->__data[0], cpu = 0;	\
77 	     cpu < trace_pack->nr_cpus;					\
78 	     cpu++, rb_pack = __next_ring_buffer_pack(rb_pack))
79 #endif
80