Import lib ring buffer into LTTng modules
[lttng-modules.git] / lib / ringbuffer / ring_buffer_mmap.c
CommitLineData
f3bc08c5
MD
1/*
2 * ring_buffer_mmap.c
3 *
4 * Copyright (C) 2002-2005 - Tom Zanussi <zanussi@us.ibm.com>, IBM Corp
5 * Copyright (C) 1999-2005 - Karim Yaghmour <karim@opersys.com>
6 * Copyright (C) 2008-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * Re-using content from kernel/relay.c.
9 *
10 * This file is released under the GPL v2.
11 */
12
13#include <linux/module.h>
14#include <linux/mm.h>
15
16#include "../../wrapper/ringbuffer/backend.h"
17#include "../../wrapper/ringbuffer/frontend.h"
18#include "../../wrapper/ringbuffer/vfs.h"
19
20/*
21 * fault() vm_op implementation for ring buffer file mapping.
22 */
23static int lib_ring_buffer_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
24{
25 struct lib_ring_buffer *buf = vma->vm_private_data;
26 struct channel *chan = buf->backend.chan;
27 const struct lib_ring_buffer_config *config = chan->backend.config;
28 pgoff_t pgoff = vmf->pgoff;
29 struct page **page;
30 void **virt;
31 unsigned long offset, sb_bindex;
32
33 if (!buf)
34 return VM_FAULT_OOM;
35
36 /*
37 * Verify that faults are only done on the range of pages owned by the
38 * reader.
39 */
40 offset = pgoff << PAGE_SHIFT;
41 sb_bindex = subbuffer_id_get_index(config, buf->backend.buf_rsb.id);
42 if (!(offset >= buf->backend.array[sb_bindex]->mmap_offset
43 && offset < buf->backend.array[sb_bindex]->mmap_offset +
44 buf->backend.chan->backend.subbuf_size))
45 return VM_FAULT_SIGBUS;
46 /*
47 * ring_buffer_read_get_page() gets the page in the current reader's
48 * pages.
49 */
50 page = lib_ring_buffer_read_get_page(&buf->backend, offset, &virt);
51 if (!*page)
52 return VM_FAULT_SIGBUS;
53 get_page(*page);
54 vmf->page = *page;
55
56 return 0;
57}
58
59/*
60 * vm_ops for ring buffer file mappings.
61 */
62static const struct vm_operations_struct lib_ring_buffer_mmap_ops = {
63 .fault = lib_ring_buffer_fault,
64};
65
66/**
67 * lib_ring_buffer_mmap_buf: - mmap channel buffer to process address space
68 * @buf: ring buffer to map
69 * @vma: vm_area_struct describing memory to be mapped
70 *
71 * Returns 0 if ok, negative on error
72 *
73 * Caller should already have grabbed mmap_sem.
74 */
75static int lib_ring_buffer_mmap_buf(struct lib_ring_buffer *buf,
76 struct vm_area_struct *vma)
77{
78 unsigned long length = vma->vm_end - vma->vm_start;
79 struct channel *chan = buf->backend.chan;
80 const struct lib_ring_buffer_config *config = chan->backend.config;
81 unsigned long mmap_buf_len;
82
83 if (config->output != RING_BUFFER_MMAP)
84 return -EINVAL;
85
86 if (!buf)
87 return -EBADF;
88
89 mmap_buf_len = chan->backend.buf_size;
90 if (chan->backend.extra_reader_sb)
91 mmap_buf_len += chan->backend.subbuf_size;
92
93 if (length != mmap_buf_len)
94 return -EINVAL;
95
96 vma->vm_ops = &lib_ring_buffer_mmap_ops;
97 vma->vm_flags |= VM_DONTEXPAND;
98 vma->vm_private_data = buf;
99
100 return 0;
101}
102
103/**
104 * lib_ring_buffer_mmap - mmap file op
105 * @filp: the file
106 * @vma: the vma describing what to map
107 *
108 * Calls upon lib_ring_buffer_mmap_buf() to map the file into user space.
109 */
110int lib_ring_buffer_mmap(struct file *filp, struct vm_area_struct *vma)
111{
112 struct lib_ring_buffer *buf = filp->private_data;
113 return lib_ring_buffer_mmap_buf(buf, vma);
114}
115EXPORT_SYMBOL_GPL(lib_ring_buffer_mmap);
This page took 0.026799 seconds and 4 git commands to generate.