X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=lttng-abi.c;h=1be6802a0f3c511677048e578476b71785e113d4;hb=b3b8072b02b4f1917a0254577c48301e8f44c210;hp=bde20864d526b40220d42db1b79fff8f3f1df35a;hpb=d83004aa718065e5221d8ef4b99e4302b70b3df9;p=lttng-modules.git diff --git a/lttng-abi.c b/lttng-abi.c index bde20864..1be6802a 100644 --- a/lttng-abi.c +++ b/lttng-abi.c @@ -539,7 +539,7 @@ unsigned int lttng_metadata_ring_buffer_poll(struct file *filp, mask |= POLLHUP; if (stream->metadata_cache->metadata_written > - stream->metadata_cache_read) + stream->metadata_out) mask |= POLLIN; } @@ -547,16 +547,15 @@ unsigned int lttng_metadata_ring_buffer_poll(struct file *filp, } static -int lttng_metadata_ring_buffer_ioctl_get_subbuf(struct file *filp, +int lttng_metadata_ring_buffer_ioctl_get_next_subbuf(struct file *filp, unsigned int cmd, unsigned long arg) { struct lttng_metadata_stream *stream = filp->private_data; struct lib_ring_buffer *buf = stream->priv; struct channel *chan = buf->backend.chan; - struct lttng_channel *lttng_chan = channel_get_private(chan); int ret; - ret = lttng_metadata_output_channel(lttng_chan, stream); + ret = lttng_metadata_output_channel(stream, chan); if (ret > 0) { lib_ring_buffer_switch_slow(buf, SWITCH_ACTIVE); ret = 0; @@ -564,6 +563,15 @@ int lttng_metadata_ring_buffer_ioctl_get_subbuf(struct file *filp, return ret; } +static +void lttng_metadata_ring_buffer_ioctl_put_next_subbuf(struct file *filp, + unsigned int cmd, unsigned long arg) +{ + struct lttng_metadata_stream *stream = filp->private_data; + + stream->metadata_out = stream->metadata_in; +} + static long lttng_metadata_ring_buffer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) @@ -573,25 +581,46 @@ long lttng_metadata_ring_buffer_ioctl(struct file *filp, struct lib_ring_buffer *buf = stream->priv; switch (cmd) { - case RING_BUFFER_GET_SUBBUF: case RING_BUFFER_GET_NEXT_SUBBUF: { - ret = lttng_metadata_ring_buffer_ioctl_get_subbuf(filp, + ret = lttng_metadata_ring_buffer_ioctl_get_next_subbuf(filp, cmd, arg); if (ret < 0) goto err; break; } + case RING_BUFFER_GET_SUBBUF: + { + /* + * Random access is not allowed for metadata channel. + */ + return -ENOSYS; + } default: break; } + /* PUT_SUBBUF is the one from lib ring buffer, unmodified. */ + /* Performing lib ring buffer ioctl after our own. */ - return lib_ring_buffer_ioctl(filp, cmd, arg, buf); + ret = lib_ring_buffer_ioctl(filp, cmd, arg, buf); + if (ret < 0) + goto err; + switch (cmd) { + case RING_BUFFER_PUT_NEXT_SUBBUF: + { + lttng_metadata_ring_buffer_ioctl_put_next_subbuf(filp, + cmd, arg); + break; + } + default: + break; + } err: return ret; } +#ifdef CONFIG_COMPAT static long lttng_metadata_ring_buffer_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) @@ -601,25 +630,50 @@ long lttng_metadata_ring_buffer_compat_ioctl(struct file *filp, struct lib_ring_buffer *buf = stream->priv; switch (cmd) { - case RING_BUFFER_GET_SUBBUF: case RING_BUFFER_GET_NEXT_SUBBUF: { - ret = lttng_metadata_ring_buffer_ioctl_get_subbuf(filp, + ret = lttng_metadata_ring_buffer_ioctl_get_next_subbuf(filp, cmd, arg); if (ret < 0) goto err; break; } + case RING_BUFFER_GET_SUBBUF: + { + /* + * Random access is not allowed for metadata channel. + */ + return -ENOSYS; + } default: break; } + /* PUT_SUBBUF is the one from lib ring buffer, unmodified. */ + /* Performing lib ring buffer ioctl after our own. */ - return lib_ring_buffer_compat_ioctl(filp, cmd, arg, buf); + ret = lib_ring_buffer_compat_ioctl(filp, cmd, arg, buf); + if (ret < 0) + goto err; + switch (cmd) { + case RING_BUFFER_PUT_NEXT_SUBBUF: + { + lttng_metadata_ring_buffer_ioctl_put_next_subbuf(filp, + cmd, arg); + break; + } + default: + break; + } err: return ret; } +#endif +/* + * This is not used by anonymous file descriptors. This code is left + * there if we ever want to implement an inode with open() operation. + */ static int lttng_metadata_ring_buffer_open(struct inode *inode, struct file *file) { @@ -627,6 +681,14 @@ int lttng_metadata_ring_buffer_open(struct inode *inode, struct file *file) struct lib_ring_buffer *buf = stream->priv; file->private_data = buf; + /* + * Since life-time of metadata cache differs from that of + * session, we need to keep our own reference on the transport. + */ + if (!try_module_get(stream->transport->owner)) { + printk(KERN_WARNING "LTT : Can't lock transport module.\n"); + return -EBUSY; + } return lib_ring_buffer_open(inode, file, buf); } @@ -637,7 +699,7 @@ int lttng_metadata_ring_buffer_release(struct inode *inode, struct file *file) struct lib_ring_buffer *buf = stream->priv; kref_put(&stream->metadata_cache->refcount, metadata_cache_destroy); - + module_put(stream->transport->owner); return lib_ring_buffer_release(inode, file, buf); } @@ -757,12 +819,26 @@ int lttng_abi_open_metadata_stream(struct file *channel_file) metadata_stream = kzalloc(sizeof(struct lttng_metadata_stream), GFP_KERNEL); - if (!metadata_stream) - return -ENOMEM; + if (!metadata_stream) { + ret = -ENOMEM; + goto nomem; + } metadata_stream->metadata_cache = session->metadata_cache; init_waitqueue_head(&metadata_stream->read_wait); metadata_stream->priv = buf; stream_priv = metadata_stream; + metadata_stream->transport = channel->transport; + + /* + * Since life-time of metadata cache differs from that of + * session, we need to keep our own reference on the transport. + */ + if (!try_module_get(metadata_stream->transport->owner)) { + printk(KERN_WARNING "LTT : Can't lock transport module.\n"); + ret = -EINVAL; + goto notransport; + } + ret = lttng_abi_create_stream_fd(channel_file, stream_priv, <tng_metadata_ring_buffer_file_operations); if (ret < 0) @@ -774,6 +850,10 @@ int lttng_abi_open_metadata_stream(struct file *channel_file) return ret; fd_error: + module_put(metadata_stream->transport->owner); +notransport: + kfree(metadata_stream); +nomem: channel->ops->buffer_read_close(buf); return ret; }