}
const struct file_operations channel_payload_file_operations = {
+ .owner = THIS_MODULE,
.open = channel_file_open,
.release = channel_file_release,
.read = channel_file_read,
EXPORT_SYMBOL_GPL(channel_payload_file_operations);
const struct file_operations lib_ring_buffer_payload_file_operations = {
+ .owner = THIS_MODULE,
.open = lib_ring_buffer_file_open,
.release = lib_ring_buffer_file_release,
.read = lib_ring_buffer_file_read,
#endif
const struct file_operations lib_ring_buffer_file_operations = {
+ .owner = THIS_MODULE,
.open = lib_ring_buffer_open,
.release = lib_ring_buffer_release,
.poll = lib_ring_buffer_poll,
static const struct file_operations lttng_metadata_fops;
static const struct file_operations lttng_event_fops;
+/*
+ * Teardown management: opened file descriptors keep a refcount on the module,
+ * so it can only exit when all file descriptors are closed.
+ */
+
enum channel_type {
PER_CPU_CHANNEL,
METADATA_CHANNEL,
}
static const struct file_operations lttng_fops = {
+ .owner = THIS_MODULE,
.unlocked_ioctl = lttng_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = lttng_ioctl,
}
static const struct file_operations lttng_session_fops = {
+ .owner = THIS_MODULE,
.release = lttng_session_release,
.unlocked_ioctl = lttng_session_ioctl,
#ifdef CONFIG_COMPAT
}
static const struct file_operations lttng_channel_fops = {
+ .owner = THIS_MODULE,
.release = lttng_channel_release,
.poll = lttng_channel_poll,
.unlocked_ioctl = lttng_channel_ioctl,
};
static const struct file_operations lttng_metadata_fops = {
+ .owner = THIS_MODULE,
.release = lttng_channel_release,
.unlocked_ioctl = lttng_metadata_ioctl,
#ifdef CONFIG_COMPAT
/* TODO: filter control ioctl */
static const struct file_operations lttng_event_fops = {
+ .owner = THIS_MODULE,
.release = lttng_event_release,
.unlocked_ioctl = lttng_event_ioctl,
#ifdef CONFIG_COMPAT
unsigned int read_timer_interval)
{
struct ltt_channel *chan;
- struct ltt_transport *transport;
+ struct ltt_transport *transport = NULL;
mutex_lock(&sessions_mutex);
if (session->been_active)
transport_name);
goto notransport;
}
+ if (!try_module_get(transport->owner)) {
+ printk(KERN_WARNING "LTT : Can't lock transport module.\n");
+ goto notransport;
+ }
chan = kzalloc(sizeof(struct ltt_channel), GFP_KERNEL);
if (!chan)
goto nomem;
goto create_error;
chan->enabled = 1;
chan->ops = &transport->ops;
+ chan->transport = transport;
list_add(&chan->list, &session->chan);
mutex_unlock(&sessions_mutex);
return chan;
create_error:
kfree(chan);
nomem:
+ if (transport)
+ module_put(transport->owner);
notransport:
active:
mutex_unlock(&sessions_mutex);
void _ltt_channel_destroy(struct ltt_channel *chan)
{
chan->ops->channel_destroy(chan->chan);
+ module_put(chan->transport->owner);
list_del(&chan->list);
lttng_destroy_context(chan->ctx);
kfree(chan);
int (*is_disabled)(struct channel *chan);
};
+struct ltt_transport {
+ char *name;
+ struct module *owner;
+ struct list_head node;
+ struct ltt_channel_ops ops;
+};
+
struct ltt_channel {
unsigned int id;
struct channel *chan; /* Channel buffers */
unsigned int free_event_id; /* Next event ID to allocate */
struct list_head list; /* Channel list */
struct ltt_channel_ops *ops;
+ struct ltt_transport *transport;
int header_type; /* 0: unset, 1: compact, 2: large */
int metadata_dumped:1;
};
int metadata_dumped:1;
};
-struct ltt_transport {
- char *name;
- struct module *owner;
- struct list_head node;
- struct ltt_channel_ops ops;
-};
-
struct ltt_session *ltt_session_create(void);
int ltt_session_enable(struct ltt_session *session);
int ltt_session_disable(struct ltt_session *session);