Cleanup: Move lib/ringbuffer/ headers to include/ringbuffer/
[lttng-modules.git] / lib / ringbuffer / ring_buffer_vfs.c
1 /* SPDX-License-Identifier: (GPL-2.0-only OR LGPL-2.1-only)
2 *
3 * ring_buffer_vfs.c
4 *
5 * Ring Buffer VFS file operations.
6 *
7 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 */
9
10 #include <linux/module.h>
11 #include <linux/fs.h>
12 #include <linux/compat.h>
13
14 #include <ringbuffer/backend.h>
15 #include <ringbuffer/frontend.h>
16 #include <ringbuffer/vfs.h>
17 #include <wrapper/poll.h>
18 #include <lttng-tracer.h>
19
20 static int put_ulong(unsigned long val, unsigned long arg)
21 {
22 return put_user(val, (unsigned long __user *)arg);
23 }
24
25 #ifdef CONFIG_COMPAT
26 static int compat_put_ulong(compat_ulong_t val, unsigned long arg)
27 {
28 return put_user(val, (compat_ulong_t __user *)compat_ptr(arg));
29 }
30 #endif
31
32 /*
33 * This is not used by anonymous file descriptors. This code is left
34 * there if we ever want to implement an inode with open() operation.
35 */
36 int lib_ring_buffer_open(struct inode *inode, struct file *file,
37 struct lib_ring_buffer *buf)
38 {
39 int ret;
40
41 if (!buf)
42 return -EINVAL;
43
44 ret = lib_ring_buffer_open_read(buf);
45 if (ret)
46 return ret;
47
48 ret = nonseekable_open(inode, file);
49 if (ret)
50 goto release_read;
51 return 0;
52
53 release_read:
54 lib_ring_buffer_release_read(buf);
55 return ret;
56 }
57 EXPORT_SYMBOL_GPL(lib_ring_buffer_open);
58
59 /**
60 * vfs_lib_ring_buffer_open - ring buffer open file operation
61 * @inode: opened inode
62 * @file: opened file
63 *
64 * Open implementation. Makes sure only one open instance of a buffer is
65 * done at a given moment.
66 */
67 static
68 int vfs_lib_ring_buffer_open(struct inode *inode, struct file *file)
69 {
70 struct lib_ring_buffer *buf = inode->i_private;
71
72 file->private_data = buf;
73 return lib_ring_buffer_open(inode, file, buf);
74 }
75
76 int lib_ring_buffer_release(struct inode *inode, struct file *file,
77 struct lib_ring_buffer *buf)
78 {
79 lib_ring_buffer_release_read(buf);
80
81 return 0;
82 }
83 EXPORT_SYMBOL_GPL(lib_ring_buffer_release);
84
85 /**
86 * vfs_lib_ring_buffer_release - ring buffer release file operation
87 * @inode: opened inode
88 * @file: opened file
89 *
90 * Release implementation.
91 */
92 static
93 int vfs_lib_ring_buffer_release(struct inode *inode, struct file *file)
94 {
95 struct lib_ring_buffer *buf = file->private_data;
96
97 return lib_ring_buffer_release(inode, file, buf);
98 }
99
100 unsigned int lib_ring_buffer_poll(struct file *filp, poll_table *wait,
101 struct lib_ring_buffer *buf)
102 {
103 unsigned int mask = 0;
104 struct channel *chan = buf->backend.chan;
105 const struct lib_ring_buffer_config *config = &chan->backend.config;
106 int finalized, disabled;
107
108 if (filp->f_mode & FMODE_READ) {
109 poll_wait_set_exclusive(wait);
110 poll_wait(filp, &buf->read_wait, wait);
111
112 finalized = lib_ring_buffer_is_finalized(config, buf);
113 disabled = lib_ring_buffer_channel_is_disabled(chan);
114
115 /*
116 * lib_ring_buffer_is_finalized() contains a smp_rmb() ordering
117 * finalized load before offsets loads.
118 */
119 WARN_ON(atomic_long_read(&buf->active_readers) != 1);
120 retry:
121 if (disabled)
122 return POLLERR;
123
124 if (subbuf_trunc(lib_ring_buffer_get_offset(config, buf), chan)
125 - subbuf_trunc(lib_ring_buffer_get_consumed(config, buf), chan)
126 == 0) {
127 if (finalized)
128 return POLLHUP;
129 else {
130 /*
131 * The memory barriers
132 * __wait_event()/wake_up_interruptible() take
133 * care of "raw_spin_is_locked" memory ordering.
134 */
135 if (raw_spin_is_locked(&buf->raw_tick_nohz_spinlock))
136 goto retry;
137 else
138 return 0;
139 }
140 } else {
141 if (subbuf_trunc(lib_ring_buffer_get_offset(config, buf),
142 chan)
143 - subbuf_trunc(lib_ring_buffer_get_consumed(config, buf),
144 chan)
145 >= chan->backend.buf_size)
146 return POLLPRI | POLLRDBAND;
147 else
148 return POLLIN | POLLRDNORM;
149 }
150 }
151 return mask;
152 }
153 EXPORT_SYMBOL_GPL(lib_ring_buffer_poll);
154
155 /**
156 * vfs_lib_ring_buffer_poll - ring buffer poll file operation
157 * @filp: the file
158 * @wait: poll table
159 *
160 * Poll implementation.
161 */
162 static
163 unsigned int vfs_lib_ring_buffer_poll(struct file *filp, poll_table *wait)
164 {
165 struct lib_ring_buffer *buf = filp->private_data;
166
167 return lib_ring_buffer_poll(filp, wait, buf);
168 }
169
170 long lib_ring_buffer_ioctl(struct file *filp, unsigned int cmd,
171 unsigned long arg, struct lib_ring_buffer *buf)
172 {
173 struct channel *chan = buf->backend.chan;
174 const struct lib_ring_buffer_config *config = &chan->backend.config;
175
176 if (lib_ring_buffer_channel_is_disabled(chan))
177 return -EIO;
178
179 switch (cmd) {
180 case RING_BUFFER_SNAPSHOT:
181 return lib_ring_buffer_snapshot(buf, &buf->cons_snapshot,
182 &buf->prod_snapshot);
183 case RING_BUFFER_SNAPSHOT_SAMPLE_POSITIONS:
184 return lib_ring_buffer_snapshot_sample_positions(buf,
185 &buf->cons_snapshot, &buf->prod_snapshot);
186 case RING_BUFFER_SNAPSHOT_GET_CONSUMED:
187 return put_ulong(buf->cons_snapshot, arg);
188 case RING_BUFFER_SNAPSHOT_GET_PRODUCED:
189 return put_ulong(buf->prod_snapshot, arg);
190 case RING_BUFFER_GET_SUBBUF:
191 {
192 unsigned long uconsume;
193 long ret;
194
195 ret = get_user(uconsume, (unsigned long __user *) arg);
196 if (ret)
197 return ret; /* will return -EFAULT */
198 ret = lib_ring_buffer_get_subbuf(buf, uconsume);
199 if (!ret) {
200 /* Set file position to zero at each successful "get" */
201 filp->f_pos = 0;
202 }
203 return ret;
204 }
205 case RING_BUFFER_PUT_SUBBUF:
206 lib_ring_buffer_put_subbuf(buf);
207 return 0;
208
209 case RING_BUFFER_GET_NEXT_SUBBUF:
210 {
211 long ret;
212
213 ret = lib_ring_buffer_get_next_subbuf(buf);
214 if (!ret) {
215 /* Set file position to zero at each successful "get" */
216 filp->f_pos = 0;
217 }
218 return ret;
219 }
220 case RING_BUFFER_PUT_NEXT_SUBBUF:
221 lib_ring_buffer_put_next_subbuf(buf);
222 return 0;
223 case RING_BUFFER_GET_SUBBUF_SIZE:
224 return put_ulong(lib_ring_buffer_get_read_data_size(config, buf),
225 arg);
226 case RING_BUFFER_GET_PADDED_SUBBUF_SIZE:
227 {
228 unsigned long size;
229
230 size = lib_ring_buffer_get_read_data_size(config, buf);
231 size = PAGE_ALIGN(size);
232 return put_ulong(size, arg);
233 }
234 case RING_BUFFER_GET_MAX_SUBBUF_SIZE:
235 return put_ulong(chan->backend.subbuf_size, arg);
236 case RING_BUFFER_GET_MMAP_LEN:
237 {
238 unsigned long mmap_buf_len;
239
240 if (config->output != RING_BUFFER_MMAP)
241 return -EINVAL;
242 mmap_buf_len = chan->backend.buf_size;
243 if (chan->backend.extra_reader_sb)
244 mmap_buf_len += chan->backend.subbuf_size;
245 if (mmap_buf_len > INT_MAX)
246 return -EFBIG;
247 return put_ulong(mmap_buf_len, arg);
248 }
249 case RING_BUFFER_GET_MMAP_READ_OFFSET:
250 {
251 unsigned long sb_bindex;
252
253 if (config->output != RING_BUFFER_MMAP)
254 return -EINVAL;
255 sb_bindex = subbuffer_id_get_index(config,
256 buf->backend.buf_rsb.id);
257 return put_ulong(buf->backend.array[sb_bindex]->mmap_offset,
258 arg);
259 }
260 case RING_BUFFER_FLUSH:
261 lib_ring_buffer_switch_remote(buf);
262 return 0;
263 case RING_BUFFER_FLUSH_EMPTY:
264 lib_ring_buffer_switch_remote_empty(buf);
265 return 0;
266 case RING_BUFFER_CLEAR:
267 lib_ring_buffer_clear(buf);
268 return 0;
269 default:
270 return -ENOIOCTLCMD;
271 }
272 }
273 EXPORT_SYMBOL_GPL(lib_ring_buffer_ioctl);
274
275 /**
276 * vfs_lib_ring_buffer_ioctl - control ring buffer reader synchronization
277 *
278 * @filp: the file
279 * @cmd: the command
280 * @arg: command arg
281 *
282 * This ioctl implements commands necessary for producer/consumer
283 * and flight recorder reader interaction :
284 * RING_BUFFER_GET_NEXT_SUBBUF
285 * Get the next sub-buffer that can be read. It never blocks.
286 * RING_BUFFER_PUT_NEXT_SUBBUF
287 * Release the currently read sub-buffer.
288 * RING_BUFFER_GET_SUBBUF_SIZE
289 * returns the size of the current sub-buffer.
290 * RING_BUFFER_GET_MAX_SUBBUF_SIZE
291 * returns the maximum size for sub-buffers.
292 * RING_BUFFER_GET_NUM_SUBBUF
293 * returns the number of reader-visible sub-buffers in the per cpu
294 * channel (for mmap).
295 * RING_BUFFER_GET_MMAP_READ_OFFSET
296 * returns the offset of the subbuffer belonging to the reader.
297 * Should only be used for mmap clients.
298 */
299 static
300 long vfs_lib_ring_buffer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
301 {
302 struct lib_ring_buffer *buf = filp->private_data;
303
304 return lib_ring_buffer_ioctl(filp, cmd, arg, buf);
305 }
306
307 #ifdef CONFIG_COMPAT
308 long lib_ring_buffer_compat_ioctl(struct file *filp, unsigned int cmd,
309 unsigned long arg, struct lib_ring_buffer *buf)
310 {
311 struct channel *chan = buf->backend.chan;
312 const struct lib_ring_buffer_config *config = &chan->backend.config;
313
314 if (lib_ring_buffer_channel_is_disabled(chan))
315 return -EIO;
316
317 switch (cmd) {
318 case RING_BUFFER_COMPAT_SNAPSHOT:
319 return lib_ring_buffer_snapshot(buf, &buf->cons_snapshot,
320 &buf->prod_snapshot);
321 case RING_BUFFER_COMPAT_SNAPSHOT_SAMPLE_POSITIONS:
322 return lib_ring_buffer_snapshot_sample_positions(buf,
323 &buf->cons_snapshot, &buf->prod_snapshot);
324 case RING_BUFFER_COMPAT_SNAPSHOT_GET_CONSUMED:
325 return compat_put_ulong(buf->cons_snapshot, arg);
326 case RING_BUFFER_COMPAT_SNAPSHOT_GET_PRODUCED:
327 return compat_put_ulong(buf->prod_snapshot, arg);
328 case RING_BUFFER_COMPAT_GET_SUBBUF:
329 {
330 __u32 uconsume;
331 unsigned long consume;
332 long ret;
333
334 ret = get_user(uconsume, (__u32 __user *) arg);
335 if (ret)
336 return ret; /* will return -EFAULT */
337 consume = buf->cons_snapshot;
338 consume &= ~0xFFFFFFFFL;
339 consume |= uconsume;
340 ret = lib_ring_buffer_get_subbuf(buf, consume);
341 if (!ret) {
342 /* Set file position to zero at each successful "get" */
343 filp->f_pos = 0;
344 }
345 return ret;
346 }
347 case RING_BUFFER_COMPAT_PUT_SUBBUF:
348 lib_ring_buffer_put_subbuf(buf);
349 return 0;
350
351 case RING_BUFFER_COMPAT_GET_NEXT_SUBBUF:
352 {
353 long ret;
354
355 ret = lib_ring_buffer_get_next_subbuf(buf);
356 if (!ret) {
357 /* Set file position to zero at each successful "get" */
358 filp->f_pos = 0;
359 }
360 return ret;
361 }
362 case RING_BUFFER_COMPAT_PUT_NEXT_SUBBUF:
363 lib_ring_buffer_put_next_subbuf(buf);
364 return 0;
365 case RING_BUFFER_COMPAT_GET_SUBBUF_SIZE:
366 {
367 unsigned long data_size;
368
369 data_size = lib_ring_buffer_get_read_data_size(config, buf);
370 if (data_size > UINT_MAX)
371 return -EFBIG;
372 return compat_put_ulong(data_size, arg);
373 }
374 case RING_BUFFER_COMPAT_GET_PADDED_SUBBUF_SIZE:
375 {
376 unsigned long size;
377
378 size = lib_ring_buffer_get_read_data_size(config, buf);
379 size = PAGE_ALIGN(size);
380 if (size > UINT_MAX)
381 return -EFBIG;
382 return compat_put_ulong(size, arg);
383 }
384 case RING_BUFFER_COMPAT_GET_MAX_SUBBUF_SIZE:
385 if (chan->backend.subbuf_size > UINT_MAX)
386 return -EFBIG;
387 return compat_put_ulong(chan->backend.subbuf_size, arg);
388 case RING_BUFFER_COMPAT_GET_MMAP_LEN:
389 {
390 unsigned long mmap_buf_len;
391
392 if (config->output != RING_BUFFER_MMAP)
393 return -EINVAL;
394 mmap_buf_len = chan->backend.buf_size;
395 if (chan->backend.extra_reader_sb)
396 mmap_buf_len += chan->backend.subbuf_size;
397 if (mmap_buf_len > UINT_MAX)
398 return -EFBIG;
399 return compat_put_ulong(mmap_buf_len, arg);
400 }
401 case RING_BUFFER_COMPAT_GET_MMAP_READ_OFFSET:
402 {
403 unsigned long sb_bindex, read_offset;
404
405 if (config->output != RING_BUFFER_MMAP)
406 return -EINVAL;
407 sb_bindex = subbuffer_id_get_index(config,
408 buf->backend.buf_rsb.id);
409 read_offset = buf->backend.array[sb_bindex]->mmap_offset;
410 if (read_offset > UINT_MAX)
411 return -EINVAL;
412 return compat_put_ulong(read_offset, arg);
413 }
414 case RING_BUFFER_COMPAT_FLUSH:
415 lib_ring_buffer_switch_remote(buf);
416 return 0;
417 case RING_BUFFER_COMPAT_FLUSH_EMPTY:
418 lib_ring_buffer_switch_remote_empty(buf);
419 return 0;
420 case RING_BUFFER_COMPAT_CLEAR:
421 lib_ring_buffer_clear(buf);
422 return 0;
423 default:
424 return -ENOIOCTLCMD;
425 }
426 }
427 EXPORT_SYMBOL_GPL(lib_ring_buffer_compat_ioctl);
428
429 static
430 long vfs_lib_ring_buffer_compat_ioctl(struct file *filp, unsigned int cmd,
431 unsigned long arg)
432 {
433 struct lib_ring_buffer *buf = filp->private_data;
434
435 return lib_ring_buffer_compat_ioctl(filp, cmd, arg, buf);
436 }
437 #endif
438
439 const struct file_operations lib_ring_buffer_file_operations = {
440 .owner = THIS_MODULE,
441 .open = vfs_lib_ring_buffer_open,
442 .release = vfs_lib_ring_buffer_release,
443 .poll = vfs_lib_ring_buffer_poll,
444 .splice_read = vfs_lib_ring_buffer_splice_read,
445 .mmap = vfs_lib_ring_buffer_mmap,
446 .unlocked_ioctl = vfs_lib_ring_buffer_ioctl,
447 .llseek = vfs_lib_ring_buffer_no_llseek,
448 #ifdef CONFIG_COMPAT
449 .compat_ioctl = vfs_lib_ring_buffer_compat_ioctl,
450 #endif
451 };
452 EXPORT_SYMBOL_GPL(lib_ring_buffer_file_operations);
453
454 MODULE_LICENSE("GPL and additional rights");
455 MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@efficios.com>");
456 MODULE_DESCRIPTION("LTTng ring buffer library");
457 MODULE_VERSION(__stringify(LTTNG_MODULES_MAJOR_VERSION) "."
458 __stringify(LTTNG_MODULES_MINOR_VERSION) "."
459 __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION)
460 LTTNG_MODULES_EXTRAVERSION);
This page took 0.038527 seconds and 4 git commands to generate.