These new calls export the data required for the consumer to generate
the index while tracing :
- timestamp begin
- timestamp end
- events discarded
- context size
- packet size
- stream id

Signed-off-by: Julien Desfossez <[email protected]>
---
 lttng-abi.c                         |  174 +++++++++++++++++++++++++++++++++--
 lttng-abi.h                         |   35 +++++++
 lttng-events.c                      |    2 +-
 lttng-events.h                      |   19 ++++
 lttng-ring-buffer-client.h          |   84 +++++++++++++++++
 lttng-ring-buffer-metadata-client.h |   48 ++++++++++
 6 files changed, 355 insertions(+), 7 deletions(-)

diff --git a/lttng-abi.c b/lttng-abi.c
index 9a25490..28b9a04 100644
--- a/lttng-abi.c
+++ b/lttng-abi.c
@@ -52,6 +52,7 @@
 #include "lttng-abi-old.h"
 #include "lttng-events.h"
 #include "lttng-tracer.h"
+#include "lib/ringbuffer/frontend_types.h"
 
 /*
  * This is LTTng's own personal way to create a system call as an external
@@ -1294,25 +1295,186 @@ static const struct file_operations lttng_event_fops = 
{
 #endif
 };
 
+static int put_u64(uint64_t val, unsigned long arg)
+{
+       return put_user(val, (uint64_t __user *) arg);
+}
+
 static long lttng_stream_ring_buffer_ioctl(struct file *filp,
                unsigned int cmd, unsigned long 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 lttng_channel *lttng_chan = channel_get_private(chan);
+       int ret;
+
+       if (atomic_read(&chan->record_disabled))
+               return -EIO;
+
        switch (cmd) {
-               default:
-                       return 
lib_ring_buffer_file_operations.unlocked_ioctl(filp,
-                                       cmd, arg);
+       case LTTNG_RING_BUFFER_GET_TIMESTAMP_BEGIN:
+       {
+               uint64_t ts;
+
+               if (!lttng_chan->ops)
+                       goto error;
+               ret = lttng_chan->ops->timestamp_begin(config, buf, &ts);
+               if (ret < 0)
+                       goto error;
+               return put_u64(ts, arg);
+       }
+       case LTTNG_RING_BUFFER_GET_TIMESTAMP_END:
+       {
+               uint64_t ts;
+
+               if (!lttng_chan->ops)
+                       goto error;
+               ret = lttng_chan->ops->timestamp_end(config, buf, &ts);
+               if (ret < 0)
+                       goto error;
+               return put_u64(ts, arg);
+       }
+       case LTTNG_RING_BUFFER_GET_EVENTS_DISCARDED:
+       {
+               uint64_t ed;
+
+               if (!lttng_chan->ops)
+                       goto error;
+               ret = lttng_chan->ops->events_discarded(config, buf, &ed);
+               if (ret < 0)
+                       goto error;
+               return put_u64(ed, arg);
+       }
+       case LTTNG_RING_BUFFER_GET_CONTENT_SIZE:
+       {
+               uint64_t cs;
+
+               if (!lttng_chan->ops)
+                       goto error;
+               ret = lttng_chan->ops->content_size(config, buf, &cs);
+               if (ret < 0)
+                       goto error;
+               return put_u64(cs, arg);
+       }
+       case LTTNG_RING_BUFFER_GET_PACKET_SIZE:
+       {
+               uint64_t ps;
+
+               if (!lttng_chan->ops)
+                       goto error;
+               ret = lttng_chan->ops->packet_size(config, buf, &ps);
+               if (ret < 0)
+                       goto error;
+               return put_u64(ps, arg);
+       }
+       case LTTNG_RING_BUFFER_GET_STREAM_ID:
+       {
+               uint64_t si;
+
+               if (!lttng_chan->ops)
+                       goto error;
+               ret = lttng_chan->ops->stream_id(config, buf, &si);
+               if (ret < 0)
+                       goto error;
+               return put_u64(si, arg);
        }
+       default:
+               return lib_ring_buffer_file_operations.unlocked_ioctl(filp,
+                               cmd, arg);
+       }
+
+error:
+       return -ENOSYS;
 }
 
 #ifdef CONFIG_COMPAT
 static long lttng_stream_ring_buffer_compat_ioctl(struct file *filp,
                unsigned int cmd, unsigned long 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 lttng_channel *lttng_chan = channel_get_private(chan);
+       int ret;
+
+       if (atomic_read(&chan->record_disabled))
+               return -EIO;
+
        switch (cmd) {
-               default:
-                       return 
lib_ring_buffer_file_operations.compat_ioctl(filp,
-                                       cmd, arg);
+       case LTTNG_RING_BUFFER_COMPAT_GET_TIMESTAMP_BEGIN:
+       {
+               uint64_t ts;
+
+               if (!lttng_chan->ops)
+                       goto error;
+               ret = lttng_chan->ops->timestamp_begin(config, buf, &ts);
+               if (ret < 0)
+                       goto error;
+               return put_u64(ts, arg);
+       }
+       case LTTNG_RING_BUFFER_COMPAT_GET_TIMESTAMP_END:
+       {
+               uint64_t ts;
+
+               if (!lttng_chan->ops)
+                       goto error;
+               ret = lttng_chan->ops->timestamp_end(config, buf, &ts);
+               if (ret < 0)
+                       goto error;
+               return put_u64(ts, arg);
+       }
+       case LTTNG_RING_BUFFER_COMPAT_GET_EVENTS_DISCARDED:
+       {
+               uint64_t ed;
+
+               if (!lttng_chan->ops)
+                       goto error;
+               ret = lttng_chan->ops->events_discarded(config, buf, &ed);
+               if (ret < 0)
+                       goto error;
+               return put_u64(ed, arg);
        }
+       case LTTNG_RING_BUFFER_COMPAT_GET_CONTENT_SIZE:
+       {
+               uint64_t cs;
+
+               if (!lttng_chan->ops)
+                       goto error;
+               ret = lttng_chan->ops->content_size(config, buf, &cs);
+               if (ret < 0)
+                       goto error;
+               return put_u64(cs, arg);
+       }
+       case LTTNG_RING_BUFFER_COMPAT_GET_PACKET_SIZE:
+       {
+               uint64_t ps;
+
+               if (!lttng_chan->ops)
+                       goto error;
+               ret = lttng_chan->ops->packet_size(config, buf, &ps);
+               if (ret < 0)
+                       goto error;
+               return put_u64(ps, arg);
+       }
+       case LTTNG_RING_BUFFER_COMPAT_GET_STREAM_ID:
+       {
+               uint64_t si;
+
+               if (!lttng_chan->ops)
+                       goto error;
+               ret = lttng_chan->ops->stream_id(config, buf, &si);
+               if (ret < 0)
+                       goto error;
+               return put_u64(si, arg);
+       }
+       default:
+               return lib_ring_buffer_file_operations.compat_ioctl(filp,
+                               cmd, arg);
+       }
+
+error:
+       return -ENOSYS;
 }
 #endif /* CONFIG_COMPAT */
 
diff --git a/lttng-abi.h b/lttng-abi.h
index 8d3ecdd..b028f1e 100644
--- a/lttng-abi.h
+++ b/lttng-abi.h
@@ -174,4 +174,39 @@ struct lttng_kernel_context {
 #define LTTNG_KERNEL_ENABLE                    _IO(0xF6, 0x82)
 #define LTTNG_KERNEL_DISABLE                   _IO(0xF6, 0x83)
 
+/* LTTng-specific ioctls for the lib ringbuffer */
+/* returns the timestamp begin of the current sub-buffer */
+#define LTTNG_RING_BUFFER_GET_TIMESTAMP_BEGIN  _IOR(0xF6, 0x20, uint64_t)
+/* returns the timestamp end of the current sub-buffer */
+#define LTTNG_RING_BUFFER_GET_TIMESTAMP_END    _IOR(0xF6, 0x21, uint64_t)
+/* returns the number of events discarded */
+#define LTTNG_RING_BUFFER_GET_EVENTS_DISCARDED _IOR(0xF6, 0x22, uint64_t)
+/* returns the packet payload size */
+#define LTTNG_RING_BUFFER_GET_CONTENT_SIZE     _IOR(0xF6, 0x23, uint64_t)
+/* returns the actual packet size */
+#define LTTNG_RING_BUFFER_GET_PACKET_SIZE      _IOR(0xF6, 0x24, uint64_t)
+/* returns the stream id */
+#define LTTNG_RING_BUFFER_GET_STREAM_ID                _IOR(0xF6, 0x25, 
uint64_t)
+
+#ifdef CONFIG_COMPAT
+/* returns the timestamp begin of the current sub-buffer */
+#define LTTNG_RING_BUFFER_COMPAT_GET_TIMESTAMP_BEGIN \
+       LTTNG_RING_BUFFER_GET_TIMESTAMP_BEGIN
+/* returns the timestamp end of the current sub-buffer */
+#define LTTNG_RING_BUFFER_COMPAT_GET_TIMESTAMP_END \
+       LTTNG_RING_BUFFER_GET_TIMESTAMP_END
+/* returns the number of events discarded */
+#define LTTNG_RING_BUFFER_COMPAT_GET_EVENTS_DISCARDED \
+       LTTNG_RING_BUFFER_GET_EVENTS_DISCARDED
+/* returns the packet payload size */
+#define LTTNG_RING_BUFFER_COMPAT_GET_CONTENT_SIZE \
+       LTTNG_RING_BUFFER_GET_CONTENT_SIZE
+/* returns the actual packet size */
+#define LTTNG_RING_BUFFER_COMPAT_GET_PACKET_SIZE \
+       LTTNG_RING_BUFFER_GET_PACKET_SIZE
+/* returns the stream id */
+#define LTTNG_RING_BUFFER_COMPAT_GET_STREAM_ID \
+       LTTNG_RING_BUFFER_GET_STREAM_ID
+#endif /* CONFIG_COMPAT */
+
 #endif /* _LTTNG_ABI_H */
diff --git a/lttng-events.c b/lttng-events.c
index 567df65..7cb1b93 100644
--- a/lttng-events.c
+++ b/lttng-events.c
@@ -285,6 +285,7 @@ struct lttng_channel *lttng_channel_create(struct 
lttng_session *session,
                goto nomem;
        chan->session = session;
        chan->id = session->free_chan_id++;
+       chan->ops = &transport->ops;
        /*
         * Note: the channel creation op already writes into the packet
         * headers. Therefore the "chan" information used as input
@@ -296,7 +297,6 @@ struct lttng_channel *lttng_channel_create(struct 
lttng_session *session,
        if (!chan->chan)
                goto create_error;
        chan->enabled = 1;
-       chan->ops = &transport->ops;
        chan->transport = transport;
        chan->channel_type = channel_type;
        list_add(&chan->list, &session->chan);
diff --git a/lttng-events.h b/lttng-events.h
index 4c1f322..08d0a5a 100644
--- a/lttng-events.h
+++ b/lttng-events.h
@@ -39,6 +39,7 @@ struct lttng_metadata_cache;
 struct lib_ring_buffer_ctx;
 struct perf_event;
 struct perf_event_attr;
+struct lib_ring_buffer_config;
 
 /* Type description */
 
@@ -244,6 +245,24 @@ struct lttng_channel_ops {
        wait_queue_head_t *(*get_hp_wait_queue)(struct channel *chan);
        int (*is_finalized)(struct channel *chan);
        int (*is_disabled)(struct channel *chan);
+       int (*timestamp_begin) (const struct lib_ring_buffer_config *config,
+                       struct lib_ring_buffer *bufb,
+                       uint64_t *timestamp_begin);
+       int (*timestamp_end) (const struct lib_ring_buffer_config *config,
+                       struct lib_ring_buffer *bufb,
+                       uint64_t *timestamp_end);
+       int (*events_discarded) (const struct lib_ring_buffer_config *config,
+                       struct lib_ring_buffer *bufb,
+                       uint64_t *events_discarded);
+       int (*content_size) (const struct lib_ring_buffer_config *config,
+                       struct lib_ring_buffer *bufb,
+                       uint64_t *content_size);
+       int (*packet_size) (const struct lib_ring_buffer_config *config,
+                       struct lib_ring_buffer *bufb,
+                       uint64_t *packet_size);
+       int (*stream_id) (const struct lib_ring_buffer_config *config,
+                       struct lib_ring_buffer *bufb,
+                       uint64_t *stream_id);
 };
 
 struct lttng_transport {
diff --git a/lttng-ring-buffer-client.h b/lttng-ring-buffer-client.h
index 0b05561..167000a 100644
--- a/lttng-ring-buffer-client.h
+++ b/lttng-ring-buffer-client.h
@@ -390,6 +390,83 @@ static void client_buffer_finalize(struct lib_ring_buffer 
*buf, void *priv, int
 {
 }
 
+static struct packet_header *client_packet_header(
+               const struct lib_ring_buffer_config *config,
+               struct lib_ring_buffer *buf)
+{
+       struct lib_ring_buffer_backend *bufb;
+       unsigned long sb_bindex;
+       struct packet_header *header;
+
+       bufb = &buf->backend;
+       sb_bindex = subbuffer_id_get_index(config, bufb->buf_rsb.id);
+       header = (struct packet_header *)
+               lib_ring_buffer_offset_address(bufb,
+                               sb_bindex * bufb->chan->backend.subbuf_size);
+
+       return header;
+}
+
+static int client_timestamp_begin(const struct lib_ring_buffer_config *config,
+               struct lib_ring_buffer *buf,
+               uint64_t *timestamp_begin)
+{
+       struct packet_header *header = client_packet_header(config, buf);
+       *timestamp_begin = header->ctx.timestamp_begin;
+
+       return 0;
+}
+
+static int client_timestamp_end(const struct lib_ring_buffer_config *config,
+                       struct lib_ring_buffer *buf,
+                       uint64_t *timestamp_end)
+{
+       struct packet_header *header = client_packet_header(config, buf);
+       *timestamp_end = header->ctx.timestamp_end;
+
+       return 0;
+}
+
+static int client_events_discarded(const struct lib_ring_buffer_config *config,
+                       struct lib_ring_buffer *buf,
+                       uint64_t *events_discarded)
+{
+       struct packet_header *header = client_packet_header(config, buf);
+       *events_discarded = header->ctx.events_discarded;
+
+       return 0;
+}
+
+static int client_content_size(const struct lib_ring_buffer_config *config,
+                       struct lib_ring_buffer *buf,
+                       uint64_t *content_size)
+{
+       struct packet_header *header = client_packet_header(config, buf);
+       *content_size = header->ctx.content_size;
+
+       return 0;
+}
+
+static int client_packet_size(const struct lib_ring_buffer_config *config,
+                       struct lib_ring_buffer *buf,
+                       uint64_t *packet_size)
+{
+       struct packet_header *header = client_packet_header(config, buf);
+       *packet_size = header->ctx.packet_size;
+
+       return 0;
+}
+
+static int client_stream_id(const struct lib_ring_buffer_config *config,
+                       struct lib_ring_buffer *buf,
+                       uint64_t *stream_id)
+{
+       struct packet_header *header = client_packet_header(config, buf);
+       *stream_id = header->stream_id;
+
+       return 0;
+}
+
 static const struct lib_ring_buffer_config client_config = {
        .cb.ring_buffer_clock_read = client_ring_buffer_clock_read,
        .cb.record_header_size = client_record_header_size,
@@ -417,6 +494,13 @@ struct channel *_channel_create(const char *name,
                                unsigned int switch_timer_interval,
                                unsigned int read_timer_interval)
 {
+       lttng_chan->ops->timestamp_begin = client_timestamp_begin;
+       lttng_chan->ops->timestamp_end = client_timestamp_end;
+       lttng_chan->ops->events_discarded = client_events_discarded;
+       lttng_chan->ops->content_size = client_content_size;
+       lttng_chan->ops->packet_size = client_packet_size;
+       lttng_chan->ops->stream_id = client_stream_id;
+
        return channel_create(&client_config, name, lttng_chan, buf_addr,
                              subbuf_size, num_subbuf, switch_timer_interval,
                              read_timer_interval);
diff --git a/lttng-ring-buffer-metadata-client.h 
b/lttng-ring-buffer-metadata-client.h
index 1c77f99..6130715 100644
--- a/lttng-ring-buffer-metadata-client.h
+++ b/lttng-ring-buffer-metadata-client.h
@@ -148,6 +148,47 @@ static void client_buffer_finalize(struct lib_ring_buffer 
*buf, void *priv, int
 {
 }
 
+static int client_timestamp_begin(const struct lib_ring_buffer_config *config,
+               struct lib_ring_buffer *buf, uint64_t *timestamp_begin)
+{
+       return -ENOSYS;
+}
+
+static int client_timestamp_end(const struct lib_ring_buffer_config *config,
+                       struct lib_ring_buffer *bufb,
+                       uint64_t *timestamp_end)
+{
+       return -ENOSYS;
+}
+
+static int client_events_discarded(const struct lib_ring_buffer_config *config,
+                       struct lib_ring_buffer *bufb,
+                       uint64_t *events_discarded)
+{
+       return -ENOSYS;
+}
+
+static int client_content_size(const struct lib_ring_buffer_config *config,
+                       struct lib_ring_buffer *bufb,
+                       uint64_t *content_size)
+{
+       return -ENOSYS;
+}
+
+static int client_packet_size(const struct lib_ring_buffer_config *config,
+                       struct lib_ring_buffer *bufb,
+                       uint64_t *packet_size)
+{
+       return -ENOSYS;
+}
+
+static int client_stream_id(const struct lib_ring_buffer_config *config,
+                       struct lib_ring_buffer *bufb,
+                       uint64_t *stream_id)
+{
+       return -ENOSYS;
+}
+
 static const struct lib_ring_buffer_config client_config = {
        .cb.ring_buffer_clock_read = client_ring_buffer_clock_read,
        .cb.record_header_size = client_record_header_size,
@@ -175,6 +216,13 @@ struct channel *_channel_create(const char *name,
                                unsigned int switch_timer_interval,
                                unsigned int read_timer_interval)
 {
+       lttng_chan->ops->timestamp_begin = client_timestamp_begin;
+       lttng_chan->ops->timestamp_end = client_timestamp_end;
+       lttng_chan->ops->events_discarded = client_events_discarded;
+       lttng_chan->ops->content_size = client_content_size;
+       lttng_chan->ops->packet_size = client_packet_size;
+       lttng_chan->ops->stream_id = client_stream_id;
+
        return channel_create(&client_config, name, lttng_chan, buf_addr,
                              subbuf_size, num_subbuf, switch_timer_interval,
                              read_timer_interval);
-- 
1.7.10.4


_______________________________________________
lttng-dev mailing list
[email protected]
http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev

Reply via email to