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;
}
#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)
{
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);
}
{
struct lttng_metadata_stream *stream = file->private_data;
struct lib_ring_buffer *buf = stream->priv;
- struct channel *chan = buf->backend.chan;
- struct lttng_channel *lttng_chan = channel_get_private(chan);
kref_put(&stream->metadata_cache->refcount, metadata_cache_destroy);
- fput(lttng_chan->file);
-
+ module_put(stream->transport->owner);
return lib_ring_buffer_release(inode, file, buf);
}
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)
goto fd_error;
- atomic_long_inc(&channel_file->f_count);
kref_get(&session->metadata_cache->refcount);
list_add(&metadata_stream->list,
&session->metadata_cache->metadata_stream);
return ret;
fd_error:
+ module_put(metadata_stream->transport->owner);
+notransport:
+ kfree(metadata_stream);
+nomem:
channel->ops->buffer_read_close(buf);
return ret;
}
* remaining space left in packet and write, since mutual exclusion
* protects us from concurrent writes.
*/
-int lttng_metadata_output_channel(struct lttng_channel *chan,
- struct lttng_metadata_stream *stream)
+int lttng_metadata_output_channel(struct lttng_metadata_stream *stream,
+ struct channel *chan)
{
struct lib_ring_buffer_ctx ctx;
int ret = 0;
if (!len)
return 0;
reserve_len = min_t(size_t,
- chan->ops->packet_avail_size(chan->chan),
+ stream->transport->ops.packet_avail_size(chan),
len);
- lib_ring_buffer_ctx_init(&ctx, chan->chan, NULL, reserve_len,
+ lib_ring_buffer_ctx_init(&ctx, chan, NULL, reserve_len,
sizeof(char), -1);
/*
* If reservation failed, return an error to the caller.
*/
- ret = chan->ops->event_reserve(&ctx, 0);
+ ret = stream->transport->ops.event_reserve(&ctx, 0);
if (ret != 0) {
printk(KERN_WARNING "LTTng: Metadata event reservation failed\n");
goto end;
}
- chan->ops->event_write(&ctx,
+ stream->transport->ops.event_write(&ctx,
stream->metadata_cache->data + stream->metadata_in,
reserve_len);
- chan->ops->event_commit(&ctx);
+ stream->transport->ops.event_commit(&ctx);
stream->metadata_in += reserve_len;
ret = reserve_len;
int finalized; /* Has channel been finalized */
wait_queue_head_t read_wait; /* Reader buffer-level wait queue */
struct list_head list; /* Stream list */
+ struct lttng_transport *transport;
};
struct lttng_session {
int lttng_probes_init(void);
void lttng_probes_exit(void);
-int lttng_metadata_output_channel(struct lttng_channel *chan,
- struct lttng_metadata_stream *stream);
+int lttng_metadata_output_channel(struct lttng_metadata_stream *stream,
+ struct channel *chan);
#if defined(CONFIG_HAVE_SYSCALL_TRACEPOINTS)
int lttng_syscalls_register(struct lttng_channel *chan, void *filter);