1.. SPDX-License-Identifier: GPL-2.0 2 3================================== 4Tracefs ring-buffer memory mapping 5================================== 6 7:Author: Vincent Donnefort <vdonnefort@google.com> 8 9Overview 10======== 11Tracefs ring-buffer memory map provides an efficient method to stream data 12as no memory copy is necessary. The application mapping the ring-buffer becomes 13then a consumer for that ring-buffer, in a similar fashion to trace_pipe. 14 15Memory mapping setup 16==================== 17The mapping works with a mmap() of the trace_pipe_raw interface. 18 19The first system page of the mapping contains ring-buffer statistics and 20description. It is referred to as the meta-page. One of the most important 21fields of the meta-page is the reader. It contains the sub-buffer ID which can 22be safely read by the mapper (see ring-buffer-design.rst). 23 24The meta-page is followed by all the sub-buffers, ordered by ascending ID. It is 25therefore effortless to know where the reader starts in the mapping: 26 27.. code-block:: c 28 29 reader_id = meta->reader->id; 30 reader_offset = meta->meta_page_size + reader_id * meta->subbuf_size; 31 32When the application is done with the current reader, it can get a new one using 33the trace_pipe_raw ioctl() TRACE_MMAP_IOCTL_GET_READER. This ioctl also updates 34the meta-page fields. 35 36Limitations 37=========== 38When a mapping is in place on a Tracefs ring-buffer, it is not possible to 39either resize it (either by increasing the entire size of the ring-buffer or 40each subbuf). It is also not possible to use snapshot and causes splice to copy 41the ring buffer data instead of using the copyless swap from the ring buffer. 42 43Concurrent readers (either another application mapping that ring-buffer or the 44kernel with trace_pipe) are allowed but not recommended. They will compete for 45the ring-buffer and the output is unpredictable, just like concurrent readers on 46trace_pipe would be. 47 48Example 49======= 50 51.. code-block:: c 52 53 #include <fcntl.h> 54 #include <stdio.h> 55 #include <stdlib.h> 56 #include <unistd.h> 57 58 #include <linux/trace_mmap.h> 59 60 #include <sys/mman.h> 61 #include <sys/ioctl.h> 62 63 #define TRACE_PIPE_RAW "/sys/kernel/tracing/per_cpu/cpu0/trace_pipe_raw" 64 65 int main(void) 66 { 67 int page_size = getpagesize(), fd, reader_id; 68 unsigned long meta_len, data_len; 69 struct trace_buffer_meta *meta; 70 void *map, *reader, *data; 71 72 fd = open(TRACE_PIPE_RAW, O_RDONLY | O_NONBLOCK); 73 if (fd < 0) 74 exit(EXIT_FAILURE); 75 76 map = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); 77 if (map == MAP_FAILED) 78 exit(EXIT_FAILURE); 79 80 meta = (struct trace_buffer_meta *)map; 81 meta_len = meta->meta_page_size; 82 83 printf("entries: %llu\n", meta->entries); 84 printf("overrun: %llu\n", meta->overrun); 85 printf("read: %llu\n", meta->read); 86 printf("nr_subbufs: %u\n", meta->nr_subbufs); 87 88 data_len = meta->subbuf_size * meta->nr_subbufs; 89 data = mmap(NULL, data_len, PROT_READ, MAP_SHARED, fd, meta_len); 90 if (data == MAP_FAILED) 91 exit(EXIT_FAILURE); 92 93 if (ioctl(fd, TRACE_MMAP_IOCTL_GET_READER) < 0) 94 exit(EXIT_FAILURE); 95 96 reader_id = meta->reader.id; 97 reader = data + meta->subbuf_size * reader_id; 98 99 printf("Current reader address: %p\n", reader); 100 101 munmap(data, data_len); 102 munmap(meta, meta_len); 103 close (fd); 104 105 return 0; 106 } 107