summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
461277e)
Don't use ring buffer client's struct lttng_channel from ioctl which
applies to ring buffer streams, because lttng_channel is freed while lib
ring buffer stream and channel are still in use. Their lifetime persists
until the consumer daemon releases its handles on the related stream
file descriptors.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
unsigned long num_subbuf; /* Number of sub-buffers for writer */
u64 start_tsc; /* Channel creation TSC value */
void *priv; /* Client-specific information */
unsigned long num_subbuf; /* Number of sub-buffers for writer */
u64 start_tsc; /* Channel creation TSC value */
void *priv; /* Client-specific information */
+ void *priv_ops; /* Client-specific ops pointer */
+ void (*release_priv_ops)(void *priv_ops);
struct notifier_block cpu_hp_notifier; /* CPU hotplug notifier */
/*
* We need to copy config because the module containing the
struct notifier_block cpu_hp_notifier; /* CPU hotplug notifier */
/*
* We need to copy config because the module containing the
static void channel_free(struct channel *chan)
{
static void channel_free(struct channel *chan)
{
+ if (chan->backend.release_priv_ops) {
+ chan->backend.release_priv_ops(chan->backend.priv_ops);
+ }
channel_iterator_free(chan);
channel_backend_free(&chan->backend);
kfree(chan);
channel_iterator_free(chan);
channel_backend_free(&chan->backend);
kfree(chan);
struct lib_ring_buffer *buf = filp->private_data;
struct channel *chan = buf->backend.chan;
const struct lib_ring_buffer_config *config = &chan->backend.config;
struct lib_ring_buffer *buf = filp->private_data;
struct channel *chan = buf->backend.chan;
const struct lib_ring_buffer_config *config = &chan->backend.config;
- struct lttng_channel *lttng_chan = channel_get_private(chan);
+ const struct lttng_channel_ops *ops = chan->backend.priv_ops;
int ret;
if (atomic_read(&chan->record_disabled))
int ret;
if (atomic_read(&chan->record_disabled))
- if (!lttng_chan->ops)
- goto error;
- ret = lttng_chan->ops->timestamp_begin(config, buf, &ts);
+ ret = ops->timestamp_begin(config, buf, &ts);
if (ret < 0)
goto error;
return put_u64(ts, arg);
if (ret < 0)
goto error;
return put_u64(ts, arg);
- if (!lttng_chan->ops)
- goto error;
- ret = lttng_chan->ops->timestamp_end(config, buf, &ts);
+ ret = ops->timestamp_end(config, buf, &ts);
if (ret < 0)
goto error;
return put_u64(ts, arg);
if (ret < 0)
goto error;
return put_u64(ts, arg);
- if (!lttng_chan->ops)
- goto error;
- ret = lttng_chan->ops->events_discarded(config, buf, &ed);
+ ret = ops->events_discarded(config, buf, &ed);
if (ret < 0)
goto error;
return put_u64(ed, arg);
if (ret < 0)
goto error;
return put_u64(ed, arg);
- if (!lttng_chan->ops)
- goto error;
- ret = lttng_chan->ops->content_size(config, buf, &cs);
+ ret = ops->content_size(config, buf, &cs);
if (ret < 0)
goto error;
return put_u64(cs, arg);
if (ret < 0)
goto error;
return put_u64(cs, arg);
- if (!lttng_chan->ops)
- goto error;
- ret = lttng_chan->ops->packet_size(config, buf, &ps);
+ ret = ops->packet_size(config, buf, &ps);
if (ret < 0)
goto error;
return put_u64(ps, arg);
if (ret < 0)
goto error;
return put_u64(ps, arg);
- if (!lttng_chan->ops)
- goto error;
- ret = lttng_chan->ops->stream_id(config, buf, &si);
+ ret = ops->stream_id(config, buf, &si);
if (ret < 0)
goto error;
return put_u64(si, arg);
if (ret < 0)
goto error;
return put_u64(si, arg);
- if (!lttng_chan->ops)
- goto error;
- ret = lttng_chan->ops->current_timestamp(config, buf, &ts);
+ ret = ops->current_timestamp(config, buf, &ts);
if (ret < 0)
goto error;
return put_u64(ts, arg);
if (ret < 0)
goto error;
return put_u64(ts, arg);
struct lib_ring_buffer *buf = filp->private_data;
struct channel *chan = buf->backend.chan;
const struct lib_ring_buffer_config *config = &chan->backend.config;
struct lib_ring_buffer *buf = filp->private_data;
struct channel *chan = buf->backend.chan;
const struct lib_ring_buffer_config *config = &chan->backend.config;
- struct lttng_channel *lttng_chan = channel_get_private(chan);
+ const struct lttng_channel_ops *ops = chan->backend.priv_ops;
int ret;
if (atomic_read(&chan->record_disabled))
int ret;
if (atomic_read(&chan->record_disabled))
- if (!lttng_chan->ops)
- goto error;
- ret = lttng_chan->ops->timestamp_begin(config, buf, &ts);
+ ret = ops->timestamp_begin(config, buf, &ts);
if (ret < 0)
goto error;
return put_u64(ts, arg);
if (ret < 0)
goto error;
return put_u64(ts, arg);
- if (!lttng_chan->ops)
- goto error;
- ret = lttng_chan->ops->timestamp_end(config, buf, &ts);
+ ret = ops->timestamp_end(config, buf, &ts);
if (ret < 0)
goto error;
return put_u64(ts, arg);
if (ret < 0)
goto error;
return put_u64(ts, arg);
- if (!lttng_chan->ops)
- goto error;
- ret = lttng_chan->ops->events_discarded(config, buf, &ed);
+ ret = ops->events_discarded(config, buf, &ed);
if (ret < 0)
goto error;
return put_u64(ed, arg);
if (ret < 0)
goto error;
return put_u64(ed, arg);
- if (!lttng_chan->ops)
- goto error;
- ret = lttng_chan->ops->content_size(config, buf, &cs);
+ ret = ops->content_size(config, buf, &cs);
if (ret < 0)
goto error;
return put_u64(cs, arg);
if (ret < 0)
goto error;
return put_u64(cs, arg);
- if (!lttng_chan->ops)
- goto error;
- ret = lttng_chan->ops->packet_size(config, buf, &ps);
+ ret = ops->packet_size(config, buf, &ps);
if (ret < 0)
goto error;
return put_u64(ps, arg);
if (ret < 0)
goto error;
return put_u64(ps, arg);
- if (!lttng_chan->ops)
- goto error;
- ret = lttng_chan->ops->stream_id(config, buf, &si);
+ ret = ops->stream_id(config, buf, &si);
if (ret < 0)
goto error;
return put_u64(si, arg);
if (ret < 0)
goto error;
return put_u64(si, arg);
- if (!lttng_chan->ops)
- goto error;
- ret = lttng_chan->ops->current_timestamp(config, buf, &ts);
+ ret = ops->current_timestamp(config, buf, &ts);
if (ret < 0)
goto error;
return put_u64(ts, arg);
if (ret < 0)
goto error;
return put_u64(ts, arg);
#define LTTNG_COMPACT_EVENT_BITS 5
#define LTTNG_COMPACT_TSC_BITS 27
#define LTTNG_COMPACT_EVENT_BITS 5
#define LTTNG_COMPACT_TSC_BITS 27
+static struct lttng_transport lttng_relay_transport;
+
/*
* Keep the natural field alignment for _each field_ within this structure if
* you ever add/remove a field from this header. Packed attribute is not used
/*
* Keep the natural field alignment for _each field_ within this structure if
* you ever add/remove a field from this header. Packed attribute is not used
.wakeup = RING_BUFFER_WAKEUP_BY_TIMER,
};
.wakeup = RING_BUFFER_WAKEUP_BY_TIMER,
};
+static
+void release_priv_ops(void *priv_ops)
+{
+ module_put(THIS_MODULE);
+}
+
+static
+void lttng_channel_destroy(struct channel *chan)
+{
+ channel_destroy(chan);
+}
+
static
struct channel *_channel_create(const char *name,
struct lttng_channel *lttng_chan, void *buf_addr,
static
struct channel *_channel_create(const char *name,
struct lttng_channel *lttng_chan, void *buf_addr,
unsigned int switch_timer_interval,
unsigned int read_timer_interval)
{
unsigned int switch_timer_interval,
unsigned int read_timer_interval)
{
- return channel_create(&client_config, name, lttng_chan, buf_addr,
+ struct channel *chan;
+
+ chan = channel_create(&client_config, name, lttng_chan, buf_addr,
subbuf_size, num_subbuf, switch_timer_interval,
read_timer_interval);
subbuf_size, num_subbuf, switch_timer_interval,
read_timer_interval);
+ if (chan) {
+ /*
+ * Ensure this module is not unloaded before we finish
+ * using lttng_relay_transport.ops.
+ */
+ if (!try_module_get(THIS_MODULE)) {
+ printk(KERN_WARNING "LTT : Can't lock transport module.\n");
+ goto error;
+ }
+ chan->backend.priv_ops = <tng_relay_transport.ops;
+ chan->backend.release_priv_ops = release_priv_ops;
+ }
+ return chan;
-static
-void lttng_channel_destroy(struct channel *chan)
-{
- channel_destroy(chan);
+error:
+ lttng_channel_destroy(chan);
+ return NULL;
#include "lttng-events.h"
#include "lttng-tracer.h"
#include "lttng-events.h"
#include "lttng-tracer.h"
+static struct lttng_transport lttng_relay_transport;
+
struct metadata_packet_header {
uint32_t magic; /* 0x75D11D57 */
uint8_t uuid[16]; /* Unique Universal Identifier */
struct metadata_packet_header {
uint32_t magic; /* 0x75D11D57 */
uint8_t uuid[16]; /* Unique Universal Identifier */
.wakeup = RING_BUFFER_WAKEUP_BY_TIMER,
};
.wakeup = RING_BUFFER_WAKEUP_BY_TIMER,
};
+static
+void release_priv_ops(void *priv_ops)
+{
+ module_put(THIS_MODULE);
+}
+
+static
+void lttng_channel_destroy(struct channel *chan)
+{
+ channel_destroy(chan);
+}
+
static
struct channel *_channel_create(const char *name,
struct lttng_channel *lttng_chan, void *buf_addr,
static
struct channel *_channel_create(const char *name,
struct lttng_channel *lttng_chan, void *buf_addr,
unsigned int switch_timer_interval,
unsigned int read_timer_interval)
{
unsigned int switch_timer_interval,
unsigned int read_timer_interval)
{
- return channel_create(&client_config, name, lttng_chan, buf_addr,
+ struct channel *chan;
+
+ chan = channel_create(&client_config, name, lttng_chan, buf_addr,
subbuf_size, num_subbuf, switch_timer_interval,
read_timer_interval);
subbuf_size, num_subbuf, switch_timer_interval,
read_timer_interval);
+ if (chan) {
+ /*
+ * Ensure this module is not unloaded before we finish
+ * using lttng_relay_transport.ops.
+ */
+ if (!try_module_get(THIS_MODULE)) {
+ printk(KERN_WARNING "LTT : Can't lock transport module.\n");
+ goto error;
+ }
+ chan->backend.priv_ops = <tng_relay_transport.ops;
+ chan->backend.release_priv_ops = release_priv_ops;
+ }
+ return chan;
-static
-void lttng_channel_destroy(struct channel *chan)
-{
- channel_destroy(chan);
+error:
+ lttng_channel_destroy(chan);
+ return NULL;