X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=lib%2Fringbuffer%2Fring_buffer_vfs.c;h=af753b9bc21a15d807d9eb882d39173406582717;hb=b7cdc18250880cc44edeef4a4b42c8ac7a135a6d;hp=6a9fb469ca4f73ccc4940b755a3607ec4bf3784d;hpb=f3bc08c50e1b302bceea699027d889fd6d9af525;p=lttng-modules.git diff --git a/lib/ringbuffer/ring_buffer_vfs.c b/lib/ringbuffer/ring_buffer_vfs.c index 6a9fb469..af753b9b 100644 --- a/lib/ringbuffer/ring_buffer_vfs.c +++ b/lib/ringbuffer/ring_buffer_vfs.c @@ -1,21 +1,21 @@ -/* - * ring_buffer_vfs.c +/* SPDX-License-Identifier: (GPL-2.0-only OR LGPL-2.1-only) * - * Copyright (C) 2009-2010 - Mathieu Desnoyers + * ring_buffer_vfs.c * * Ring Buffer VFS file operations. * - * Dual LGPL v2.1/GPL v2 license. + * Copyright (C) 2010-2012 Mathieu Desnoyers */ #include #include #include -#include "../../wrapper/ringbuffer/backend.h" -#include "../../wrapper/ringbuffer/frontend.h" -#include "../../wrapper/ringbuffer/vfs.h" -#include "../../wrapper/poll.h" +#include +#include +#include +#include +#include static int put_ulong(unsigned long val, unsigned long arg) { @@ -29,24 +29,22 @@ static int compat_put_ulong(compat_ulong_t val, unsigned long arg) } #endif -/** - * lib_ring_buffer_open - ring buffer open file operation - * @inode: opened inode - * @file: opened file - * - * Open implementation. Makes sure only one open instance of a buffer is - * done at a given moment. +/* + * This is not used by anonymous file descriptors. This code is left + * there if we ever want to implement an inode with open() operation. */ -int lib_ring_buffer_open(struct inode *inode, struct file *file) +int lib_ring_buffer_open(struct inode *inode, struct file *file, + struct lib_ring_buffer *buf) { - struct lib_ring_buffer *buf = inode->i_private; int ret; + if (!buf) + return -EINVAL; + ret = lib_ring_buffer_open_read(buf); if (ret) return ret; - file->private_data = buf; ret = nonseekable_open(inode, file); if (ret) goto release_read; @@ -56,49 +54,73 @@ release_read: lib_ring_buffer_release_read(buf); return ret; } +EXPORT_SYMBOL_GPL(lib_ring_buffer_open); /** - * lib_ring_buffer_release - ring buffer release file operation + * vfs_lib_ring_buffer_open - ring buffer open file operation * @inode: opened inode * @file: opened file * - * Release implementation. + * Open implementation. Makes sure only one open instance of a buffer is + * done at a given moment. */ -int lib_ring_buffer_release(struct inode *inode, struct file *file) +static +int vfs_lib_ring_buffer_open(struct inode *inode, struct file *file) { - struct lib_ring_buffer *buf = file->private_data; + struct lib_ring_buffer *buf = inode->i_private; + + file->private_data = buf; + return lib_ring_buffer_open(inode, file, buf); +} +int lib_ring_buffer_release(struct inode *inode, struct file *file, + struct lib_ring_buffer *buf) +{ lib_ring_buffer_release_read(buf); return 0; } +EXPORT_SYMBOL_GPL(lib_ring_buffer_release); /** - * lib_ring_buffer_poll - ring buffer poll file operation - * @filp: the file - * @wait: poll table + * vfs_lib_ring_buffer_release - ring buffer release file operation + * @inode: opened inode + * @file: opened file * - * Poll implementation. + * Release implementation. */ -unsigned int lib_ring_buffer_poll(struct file *filp, poll_table *wait) +static +int vfs_lib_ring_buffer_release(struct inode *inode, struct file *file) +{ + struct lib_ring_buffer *buf = file->private_data; + + return lib_ring_buffer_release(inode, file, buf); +} + +unsigned int lib_ring_buffer_poll(struct file *filp, poll_table *wait, + struct lib_ring_buffer *buf) { unsigned int mask = 0; - struct lib_ring_buffer *buf = filp->private_data; struct channel *chan = buf->backend.chan; - const struct lib_ring_buffer_config *config = chan->backend.config; - int finalized; + const struct lib_ring_buffer_config *config = &chan->backend.config; + int finalized, disabled; if (filp->f_mode & FMODE_READ) { poll_wait_set_exclusive(wait); poll_wait(filp, &buf->read_wait, wait); finalized = lib_ring_buffer_is_finalized(config, buf); + disabled = lib_ring_buffer_channel_is_disabled(chan); + /* * lib_ring_buffer_is_finalized() contains a smp_rmb() ordering * finalized load before offsets loads. */ WARN_ON(atomic_long_read(&buf->active_readers) != 1); retry: + if (disabled) + return POLLERR; + if (subbuf_trunc(lib_ring_buffer_get_offset(config, buf), chan) - subbuf_trunc(lib_ring_buffer_get_consumed(config, buf), chan) == 0) { @@ -128,41 +150,39 @@ retry: } return mask; } +EXPORT_SYMBOL_GPL(lib_ring_buffer_poll); /** - * lib_ring_buffer_ioctl - control ring buffer reader synchronization - * + * vfs_lib_ring_buffer_poll - ring buffer poll file operation * @filp: the file - * @cmd: the command - * @arg: command arg + * @wait: poll table * - * This ioctl implements commands necessary for producer/consumer - * and flight recorder reader interaction : - * RING_BUFFER_GET_NEXT_SUBBUF - * Get the next sub-buffer that can be read. It never blocks. - * RING_BUFFER_PUT_NEXT_SUBBUF - * Release the currently read sub-buffer. - * RING_BUFFER_GET_SUBBUF_SIZE - * returns the size of the current sub-buffer. - * RING_BUFFER_GET_MAX_SUBBUF_SIZE - * returns the maximum size for sub-buffers. - * RING_BUFFER_GET_NUM_SUBBUF - * returns the number of reader-visible sub-buffers in the per cpu - * channel (for mmap). - * RING_BUFFER_GET_MMAP_READ_OFFSET - * returns the offset of the subbuffer belonging to the reader. - * Should only be used for mmap clients. + * Poll implementation. */ -long lib_ring_buffer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +static +unsigned int vfs_lib_ring_buffer_poll(struct file *filp, poll_table *wait) { struct lib_ring_buffer *buf = filp->private_data; + + return lib_ring_buffer_poll(filp, wait, buf); +} + +long lib_ring_buffer_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg, struct lib_ring_buffer *buf) +{ struct channel *chan = buf->backend.chan; - const struct lib_ring_buffer_config *config = chan->backend.config; + const struct lib_ring_buffer_config *config = &chan->backend.config; + + if (lib_ring_buffer_channel_is_disabled(chan)) + return -EIO; switch (cmd) { case RING_BUFFER_SNAPSHOT: return lib_ring_buffer_snapshot(buf, &buf->cons_snapshot, &buf->prod_snapshot); + case RING_BUFFER_SNAPSHOT_SAMPLE_POSITIONS: + return lib_ring_buffer_snapshot_sample_positions(buf, + &buf->cons_snapshot, &buf->prod_snapshot); case RING_BUFFER_SNAPSHOT_GET_CONSUMED: return put_ulong(buf->cons_snapshot, arg); case RING_BUFFER_SNAPSHOT_GET_PRODUCED: @@ -237,28 +257,75 @@ long lib_ring_buffer_ioctl(struct file *filp, unsigned int cmd, unsigned long ar return put_ulong(buf->backend.array[sb_bindex]->mmap_offset, arg); } + case RING_BUFFER_FLUSH: + lib_ring_buffer_switch_remote(buf); + return 0; + case RING_BUFFER_FLUSH_EMPTY: + lib_ring_buffer_switch_remote_empty(buf); + return 0; + case RING_BUFFER_CLEAR: + lib_ring_buffer_clear(buf); + return 0; default: return -ENOIOCTLCMD; } } +EXPORT_SYMBOL_GPL(lib_ring_buffer_ioctl); + +/** + * vfs_lib_ring_buffer_ioctl - control ring buffer reader synchronization + * + * @filp: the file + * @cmd: the command + * @arg: command arg + * + * This ioctl implements commands necessary for producer/consumer + * and flight recorder reader interaction : + * RING_BUFFER_GET_NEXT_SUBBUF + * Get the next sub-buffer that can be read. It never blocks. + * RING_BUFFER_PUT_NEXT_SUBBUF + * Release the currently read sub-buffer. + * RING_BUFFER_GET_SUBBUF_SIZE + * returns the size of the current sub-buffer. + * RING_BUFFER_GET_MAX_SUBBUF_SIZE + * returns the maximum size for sub-buffers. + * RING_BUFFER_GET_NUM_SUBBUF + * returns the number of reader-visible sub-buffers in the per cpu + * channel (for mmap). + * RING_BUFFER_GET_MMAP_READ_OFFSET + * returns the offset of the subbuffer belonging to the reader. + * Should only be used for mmap clients. + */ +static +long vfs_lib_ring_buffer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct lib_ring_buffer *buf = filp->private_data; + + return lib_ring_buffer_ioctl(filp, cmd, arg, buf); +} #ifdef CONFIG_COMPAT long lib_ring_buffer_compat_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) + unsigned long arg, struct lib_ring_buffer *buf) { - struct lib_ring_buffer *buf = filp->private_data; struct channel *chan = buf->backend.chan; - const struct lib_ring_buffer_config *config = chan->backend.config; + const struct lib_ring_buffer_config *config = &chan->backend.config; + + if (lib_ring_buffer_channel_is_disabled(chan)) + return -EIO; switch (cmd) { - case RING_BUFFER_SNAPSHOT: + case RING_BUFFER_COMPAT_SNAPSHOT: return lib_ring_buffer_snapshot(buf, &buf->cons_snapshot, &buf->prod_snapshot); - case RING_BUFFER_SNAPSHOT_GET_CONSUMED: + case RING_BUFFER_COMPAT_SNAPSHOT_SAMPLE_POSITIONS: + return lib_ring_buffer_snapshot_sample_positions(buf, + &buf->cons_snapshot, &buf->prod_snapshot); + case RING_BUFFER_COMPAT_SNAPSHOT_GET_CONSUMED: return compat_put_ulong(buf->cons_snapshot, arg); - case RING_BUFFER_SNAPSHOT_GET_PRODUCED: + case RING_BUFFER_COMPAT_SNAPSHOT_GET_PRODUCED: return compat_put_ulong(buf->prod_snapshot, arg); - case RING_BUFFER_GET_SUBBUF: + case RING_BUFFER_COMPAT_GET_SUBBUF: { __u32 uconsume; unsigned long consume; @@ -277,11 +344,11 @@ long lib_ring_buffer_compat_ioctl(struct file *filp, unsigned int cmd, } return ret; } - case RING_BUFFER_PUT_SUBBUF: + case RING_BUFFER_COMPAT_PUT_SUBBUF: lib_ring_buffer_put_subbuf(buf); return 0; - case RING_BUFFER_GET_NEXT_SUBBUF: + case RING_BUFFER_COMPAT_GET_NEXT_SUBBUF: { long ret; @@ -292,19 +359,19 @@ long lib_ring_buffer_compat_ioctl(struct file *filp, unsigned int cmd, } return ret; } - case RING_BUFFER_PUT_NEXT_SUBBUF: + case RING_BUFFER_COMPAT_PUT_NEXT_SUBBUF: lib_ring_buffer_put_next_subbuf(buf); return 0; - case RING_BUFFER_GET_SUBBUF_SIZE: + case RING_BUFFER_COMPAT_GET_SUBBUF_SIZE: { unsigned long data_size; data_size = lib_ring_buffer_get_read_data_size(config, buf); if (data_size > UINT_MAX) return -EFBIG; - return put_ulong(data_size, arg); + return compat_put_ulong(data_size, arg); } - case RING_BUFFER_GET_PADDED_SUBBUF_SIZE: + case RING_BUFFER_COMPAT_GET_PADDED_SUBBUF_SIZE: { unsigned long size; @@ -312,13 +379,13 @@ long lib_ring_buffer_compat_ioctl(struct file *filp, unsigned int cmd, size = PAGE_ALIGN(size); if (size > UINT_MAX) return -EFBIG; - return put_ulong(size, arg); + return compat_put_ulong(size, arg); } - case RING_BUFFER_GET_MAX_SUBBUF_SIZE: + case RING_BUFFER_COMPAT_GET_MAX_SUBBUF_SIZE: if (chan->backend.subbuf_size > UINT_MAX) return -EFBIG; - return put_ulong(chan->backend.subbuf_size, arg); - case RING_BUFFER_GET_MMAP_LEN: + return compat_put_ulong(chan->backend.subbuf_size, arg); + case RING_BUFFER_COMPAT_GET_MMAP_LEN: { unsigned long mmap_buf_len; @@ -329,9 +396,9 @@ long lib_ring_buffer_compat_ioctl(struct file *filp, unsigned int cmd, mmap_buf_len += chan->backend.subbuf_size; if (mmap_buf_len > UINT_MAX) return -EFBIG; - return put_ulong(mmap_buf_len, arg); + return compat_put_ulong(mmap_buf_len, arg); } - case RING_BUFFER_GET_MMAP_READ_OFFSET: + case RING_BUFFER_COMPAT_GET_MMAP_READ_OFFSET: { unsigned long sb_bindex, read_offset; @@ -342,28 +409,52 @@ long lib_ring_buffer_compat_ioctl(struct file *filp, unsigned int cmd, read_offset = buf->backend.array[sb_bindex]->mmap_offset; if (read_offset > UINT_MAX) return -EINVAL; - return put_ulong(read_offset, arg); + return compat_put_ulong(read_offset, arg); } + case RING_BUFFER_COMPAT_FLUSH: + lib_ring_buffer_switch_remote(buf); + return 0; + case RING_BUFFER_COMPAT_FLUSH_EMPTY: + lib_ring_buffer_switch_remote_empty(buf); + return 0; + case RING_BUFFER_COMPAT_CLEAR: + lib_ring_buffer_clear(buf); + return 0; default: return -ENOIOCTLCMD; } } +EXPORT_SYMBOL_GPL(lib_ring_buffer_compat_ioctl); + +static +long vfs_lib_ring_buffer_compat_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + struct lib_ring_buffer *buf = filp->private_data; + + return lib_ring_buffer_compat_ioctl(filp, cmd, arg, buf); +} #endif const struct file_operations lib_ring_buffer_file_operations = { - .open = lib_ring_buffer_open, - .release = lib_ring_buffer_release, - .poll = lib_ring_buffer_poll, - .splice_read = lib_ring_buffer_splice_read, - .mmap = lib_ring_buffer_mmap, - .unlocked_ioctl = lib_ring_buffer_ioctl, - .llseek = lib_ring_buffer_no_llseek, + .owner = THIS_MODULE, + .open = vfs_lib_ring_buffer_open, + .release = vfs_lib_ring_buffer_release, + .poll = vfs_lib_ring_buffer_poll, + .splice_read = vfs_lib_ring_buffer_splice_read, + .mmap = vfs_lib_ring_buffer_mmap, + .unlocked_ioctl = vfs_lib_ring_buffer_ioctl, + .llseek = vfs_lib_ring_buffer_no_llseek, #ifdef CONFIG_COMPAT - .compat_ioctl = lib_ring_buffer_compat_ioctl, + .compat_ioctl = vfs_lib_ring_buffer_compat_ioctl, #endif }; EXPORT_SYMBOL_GPL(lib_ring_buffer_file_operations); MODULE_LICENSE("GPL and additional rights"); -MODULE_AUTHOR("Mathieu Desnoyers"); -MODULE_DESCRIPTION("Ring Buffer Library VFS"); +MODULE_AUTHOR("Mathieu Desnoyers "); +MODULE_DESCRIPTION("LTTng ring buffer library"); +MODULE_VERSION(__stringify(LTTNG_MODULES_MAJOR_VERSION) "." + __stringify(LTTNG_MODULES_MINOR_VERSION) "." + __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION) + LTTNG_MODULES_EXTRAVERSION);