[lttng-dev] [MODULES PATCH 2/4] LTTng ringbuffer ABI calls for index generation

Julien Desfossez jdesfossez at efficios.com
Mon Sep 16 11:18:31 EDT 2013


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 <jdesfossez at efficios.com>
Acked-by: Mathieu Desnoyers <mathieu.desnoyers at efficios.com>
---
 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 7cc4b52..c2560e0 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
@@ -1323,25 +1324,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 4b891cd..879097b 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 bc5cd9f..bce6507 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.8.3.2




More information about the lttng-dev mailing list