Merge tag 'v3.14.25' into backport/v3.14.24-ltsi-rc1+v3.14.25/snapshot-merge.wip
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / staging / lttng / lib / ringbuffer / ring_buffer_vfs.c
1 /*
2  * ring_buffer_vfs.c
3  *
4  * Ring Buffer VFS file operations.
5  *
6  * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; only
11  * version 2.1 of the License.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 #include <linux/module.h>
24 #include <linux/fs.h>
25 #include <linux/compat.h>
26
27 #include "../../wrapper/ringbuffer/backend.h"
28 #include "../../wrapper/ringbuffer/frontend.h"
29 #include "../../wrapper/ringbuffer/vfs.h"
30 #include "../../wrapper/poll.h"
31
32 static int put_ulong(unsigned long val, unsigned long arg)
33 {
34         return put_user(val, (unsigned long __user *)arg);
35 }
36
37 #ifdef CONFIG_COMPAT
38 static int compat_put_ulong(compat_ulong_t val, unsigned long arg)
39 {
40         return put_user(val, (compat_ulong_t __user *)compat_ptr(arg));
41 }
42 #endif
43
44 /*
45  * This is not used by anonymous file descriptors. This code is left
46  * there if we ever want to implement an inode with open() operation.
47  */
48 int lib_ring_buffer_open(struct inode *inode, struct file *file,
49                 struct lib_ring_buffer *buf)
50 {
51         int ret;
52
53         if (!buf)
54                 return -EINVAL;
55
56         ret = lib_ring_buffer_open_read(buf);
57         if (ret)
58                 return ret;
59
60         ret = nonseekable_open(inode, file);
61         if (ret)
62                 goto release_read;
63         return 0;
64
65 release_read:
66         lib_ring_buffer_release_read(buf);
67         return ret;
68 }
69 EXPORT_SYMBOL_GPL(lib_ring_buffer_open);
70
71 /**
72  *      vfs_lib_ring_buffer_open - ring buffer open file operation
73  *      @inode: opened inode
74  *      @file: opened file
75  *
76  *      Open implementation. Makes sure only one open instance of a buffer is
77  *      done at a given moment.
78  */
79 static
80 int vfs_lib_ring_buffer_open(struct inode *inode, struct file *file)
81 {
82         struct lib_ring_buffer *buf = inode->i_private;
83
84         file->private_data = buf;
85         return lib_ring_buffer_open(inode, file, buf);
86 }
87
88 int lib_ring_buffer_release(struct inode *inode, struct file *file,
89                 struct lib_ring_buffer *buf)
90 {
91         lib_ring_buffer_release_read(buf);
92
93         return 0;
94 }
95 EXPORT_SYMBOL_GPL(lib_ring_buffer_release);
96
97 /**
98  *      vfs_lib_ring_buffer_release - ring buffer release file operation
99  *      @inode: opened inode
100  *      @file: opened file
101  *
102  *      Release implementation.
103  */
104 static
105 int vfs_lib_ring_buffer_release(struct inode *inode, struct file *file)
106 {
107         struct lib_ring_buffer *buf = file->private_data;
108
109         return lib_ring_buffer_release(inode, file, buf);
110 }
111
112 unsigned int lib_ring_buffer_poll(struct file *filp, poll_table *wait,
113                 struct lib_ring_buffer *buf)
114 {
115         unsigned int mask = 0;
116         struct channel *chan = buf->backend.chan;
117         const struct lib_ring_buffer_config *config = &chan->backend.config;
118         int finalized, disabled;
119
120         if (filp->f_mode & FMODE_READ) {
121                 poll_wait_set_exclusive(wait);
122                 poll_wait(filp, &buf->read_wait, wait);
123
124                 finalized = lib_ring_buffer_is_finalized(config, buf);
125                 disabled = lib_ring_buffer_channel_is_disabled(chan);
126
127                 /*
128                  * lib_ring_buffer_is_finalized() contains a smp_rmb() ordering
129                  * finalized load before offsets loads.
130                  */
131                 WARN_ON(atomic_long_read(&buf->active_readers) != 1);
132 retry:
133                 if (disabled)
134                         return POLLERR;
135
136                 if (subbuf_trunc(lib_ring_buffer_get_offset(config, buf), chan)
137                   - subbuf_trunc(lib_ring_buffer_get_consumed(config, buf), chan)
138                   == 0) {
139                         if (finalized)
140                                 return POLLHUP;
141                         else {
142                                 /*
143                                  * The memory barriers
144                                  * __wait_event()/wake_up_interruptible() take
145                                  * care of "raw_spin_is_locked" memory ordering.
146                                  */
147                                 if (raw_spin_is_locked(&buf->raw_tick_nohz_spinlock))
148                                         goto retry;
149                                 else
150                                         return 0;
151                         }
152                 } else {
153                         if (subbuf_trunc(lib_ring_buffer_get_offset(config, buf),
154                                          chan)
155                           - subbuf_trunc(lib_ring_buffer_get_consumed(config, buf),
156                                          chan)
157                           >= chan->backend.buf_size)
158                                 return POLLPRI | POLLRDBAND;
159                         else
160                                 return POLLIN | POLLRDNORM;
161                 }
162         }
163         return mask;
164 }
165 EXPORT_SYMBOL_GPL(lib_ring_buffer_poll);
166
167 /**
168  *      vfs_lib_ring_buffer_poll - ring buffer poll file operation
169  *      @filp: the file
170  *      @wait: poll table
171  *
172  *      Poll implementation.
173  */
174 static
175 unsigned int vfs_lib_ring_buffer_poll(struct file *filp, poll_table *wait)
176 {
177         struct lib_ring_buffer *buf = filp->private_data;
178
179         return lib_ring_buffer_poll(filp, wait, buf);
180 }
181
182 long lib_ring_buffer_ioctl(struct file *filp, unsigned int cmd,
183                 unsigned long arg, struct lib_ring_buffer *buf)
184 {
185         struct channel *chan = buf->backend.chan;
186         const struct lib_ring_buffer_config *config = &chan->backend.config;
187
188         if (lib_ring_buffer_channel_is_disabled(chan))
189                 return -EIO;
190
191         switch (cmd) {
192         case RING_BUFFER_SNAPSHOT:
193                 return lib_ring_buffer_snapshot(buf, &buf->cons_snapshot,
194                                             &buf->prod_snapshot);
195         case RING_BUFFER_SNAPSHOT_GET_CONSUMED:
196                 return put_ulong(buf->cons_snapshot, arg);
197         case RING_BUFFER_SNAPSHOT_GET_PRODUCED:
198                 return put_ulong(buf->prod_snapshot, arg);
199         case RING_BUFFER_GET_SUBBUF:
200         {
201                 unsigned long uconsume;
202                 long ret;
203
204                 ret = get_user(uconsume, (unsigned long __user *) arg);
205                 if (ret)
206                         return ret; /* will return -EFAULT */
207                 ret = lib_ring_buffer_get_subbuf(buf, uconsume);
208                 if (!ret) {
209                         /* Set file position to zero at each successful "get" */
210                         filp->f_pos = 0;
211                 }
212                 return ret;
213         }
214         case RING_BUFFER_PUT_SUBBUF:
215                 lib_ring_buffer_put_subbuf(buf);
216                 return 0;
217
218         case RING_BUFFER_GET_NEXT_SUBBUF:
219         {
220                 long ret;
221
222                 ret = lib_ring_buffer_get_next_subbuf(buf);
223                 if (!ret) {
224                         /* Set file position to zero at each successful "get" */
225                         filp->f_pos = 0;
226                 }
227                 return ret;
228         }
229         case RING_BUFFER_PUT_NEXT_SUBBUF:
230                 lib_ring_buffer_put_next_subbuf(buf);
231                 return 0;
232         case RING_BUFFER_GET_SUBBUF_SIZE:
233                 return put_ulong(lib_ring_buffer_get_read_data_size(config, buf),
234                                  arg);
235         case RING_BUFFER_GET_PADDED_SUBBUF_SIZE:
236         {
237                 unsigned long size;
238
239                 size = lib_ring_buffer_get_read_data_size(config, buf);
240                 size = PAGE_ALIGN(size);
241                 return put_ulong(size, arg);
242         }
243         case RING_BUFFER_GET_MAX_SUBBUF_SIZE:
244                 return put_ulong(chan->backend.subbuf_size, arg);
245         case RING_BUFFER_GET_MMAP_LEN:
246         {
247                 unsigned long mmap_buf_len;
248
249                 if (config->output != RING_BUFFER_MMAP)
250                         return -EINVAL;
251                 mmap_buf_len = chan->backend.buf_size;
252                 if (chan->backend.extra_reader_sb)
253                         mmap_buf_len += chan->backend.subbuf_size;
254                 if (mmap_buf_len > INT_MAX)
255                         return -EFBIG;
256                 return put_ulong(mmap_buf_len, arg);
257         }
258         case RING_BUFFER_GET_MMAP_READ_OFFSET:
259         {
260                 unsigned long sb_bindex;
261
262                 if (config->output != RING_BUFFER_MMAP)
263                         return -EINVAL;
264                 sb_bindex = subbuffer_id_get_index(config,
265                                                    buf->backend.buf_rsb.id);
266                 return put_ulong(buf->backend.array[sb_bindex]->mmap_offset,
267                                  arg);
268         }
269         case RING_BUFFER_FLUSH:
270                 lib_ring_buffer_switch_remote(buf);
271                 return 0;
272         default:
273                 return -ENOIOCTLCMD;
274         }
275 }
276 EXPORT_SYMBOL_GPL(lib_ring_buffer_ioctl);
277
278 /**
279  *      vfs_lib_ring_buffer_ioctl - control ring buffer reader synchronization
280  *
281  *      @filp: the file
282  *      @cmd: the command
283  *      @arg: command arg
284  *
285  *      This ioctl implements commands necessary for producer/consumer
286  *      and flight recorder reader interaction :
287  *      RING_BUFFER_GET_NEXT_SUBBUF
288  *              Get the next sub-buffer that can be read. It never blocks.
289  *      RING_BUFFER_PUT_NEXT_SUBBUF
290  *              Release the currently read sub-buffer.
291  *      RING_BUFFER_GET_SUBBUF_SIZE
292  *              returns the size of the current sub-buffer.
293  *      RING_BUFFER_GET_MAX_SUBBUF_SIZE
294  *              returns the maximum size for sub-buffers.
295  *      RING_BUFFER_GET_NUM_SUBBUF
296  *              returns the number of reader-visible sub-buffers in the per cpu
297  *              channel (for mmap).
298  *      RING_BUFFER_GET_MMAP_READ_OFFSET
299  *              returns the offset of the subbuffer belonging to the reader.
300  *              Should only be used for mmap clients.
301  */
302 static
303 long vfs_lib_ring_buffer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
304 {
305         struct lib_ring_buffer *buf = filp->private_data;
306
307         return lib_ring_buffer_ioctl(filp, cmd, arg, buf);
308 }
309
310 #ifdef CONFIG_COMPAT
311 long lib_ring_buffer_compat_ioctl(struct file *filp, unsigned int cmd,
312                 unsigned long arg, struct lib_ring_buffer *buf)
313 {
314         struct channel *chan = buf->backend.chan;
315         const struct lib_ring_buffer_config *config = &chan->backend.config;
316
317         if (lib_ring_buffer_channel_is_disabled(chan))
318                 return -EIO;
319
320         switch (cmd) {
321         case RING_BUFFER_COMPAT_SNAPSHOT:
322                 return lib_ring_buffer_snapshot(buf, &buf->cons_snapshot,
323                                                 &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         default:
418                 return -ENOIOCTLCMD;
419         }
420 }
421 EXPORT_SYMBOL_GPL(lib_ring_buffer_compat_ioctl);
422
423 static
424 long vfs_lib_ring_buffer_compat_ioctl(struct file *filp, unsigned int cmd,
425                                   unsigned long arg)
426 {
427         struct lib_ring_buffer *buf = filp->private_data;
428
429         return lib_ring_buffer_compat_ioctl(filp, cmd, arg, buf);
430 }
431 #endif
432
433 const struct file_operations lib_ring_buffer_file_operations = {
434         .owner = THIS_MODULE,
435         .open = vfs_lib_ring_buffer_open,
436         .release = vfs_lib_ring_buffer_release,
437         .poll = vfs_lib_ring_buffer_poll,
438         .splice_read = vfs_lib_ring_buffer_splice_read,
439         .mmap = vfs_lib_ring_buffer_mmap,
440         .unlocked_ioctl = vfs_lib_ring_buffer_ioctl,
441         .llseek = vfs_lib_ring_buffer_no_llseek,
442 #ifdef CONFIG_COMPAT
443         .compat_ioctl = vfs_lib_ring_buffer_compat_ioctl,
444 #endif
445 };
446 EXPORT_SYMBOL_GPL(lib_ring_buffer_file_operations);
447
448 MODULE_LICENSE("GPL and additional rights");
449 MODULE_AUTHOR("Mathieu Desnoyers");
450 MODULE_DESCRIPTION("Ring Buffer Library VFS");