From 381c0f1ef474e0ae8a96b3753470ca4bda45c764 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 22 Sep 2011 10:51:55 -0400 Subject: [PATCH] libust ABI: export streams Signed-off-by: Mathieu Desnoyers --- include/lttng-ust-comm.h | 4 + include/ust/lttng-events.h | 4 +- include/ust/lttng-ust-abi.h | 10 +++ libringbuffer/frontend.h | 4 +- libringbuffer/ring_buffer_backend.c | 1 - libringbuffer/ring_buffer_frontend.c | 17 ++++- libringbuffer/shm.h | 18 +++++ libust/ltt-ring-buffer-client.h | 8 +- libust/ltt-ring-buffer-metadata-client.h | 7 +- libust/lttng-ust-abi.c | 96 ++++++++++++++++++++---- libust/lttng-ust-comm.c | 25 ++++++ 11 files changed, 169 insertions(+), 25 deletions(-) diff --git a/include/lttng-ust-comm.h b/include/lttng-ust-comm.h index a5220a4..d792074 100644 --- a/include/lttng-ust-comm.h +++ b/include/lttng-ust-comm.h @@ -126,6 +126,7 @@ struct lttcomm_ust_msg { union { struct lttng_ust_tracer_version version; struct lttng_ust_channel channel; + struct lttng_ust_stream stream; struct lttng_ust_event event; struct lttng_ust_context context; } u; @@ -141,6 +142,9 @@ struct lttcomm_ust_reply { uint32_t ret_code; /* enum enum lttcomm_return_code */ uint32_t ret_val; /* return value */ union { + struct { + uint64_t memory_map_size; + } stream; } u; }; diff --git a/include/ust/lttng-events.h b/include/ust/lttng-events.h index 303d0da..db475cd 100644 --- a/include/ust/lttng-events.h +++ b/include/ust/lttng-events.h @@ -209,7 +209,9 @@ struct ltt_channel_ops { unsigned int read_timer_interval); void (*channel_destroy)(struct ltt_channel *ltt_chan); struct lib_ring_buffer *(*buffer_read_open)(struct channel *chan, - struct shm_handle *handle); + struct shm_handle *handle, + int *shm_fd, int *wait_fd, + uint64_t *memory_map_size); void (*buffer_read_close)(struct lib_ring_buffer *buf, struct shm_handle *handle); int (*event_reserve)(struct lib_ring_buffer_ctx *ctx, diff --git a/include/ust/lttng-ust-abi.h b/include/ust/lttng-ust-abi.h index 56fa8b9..73eb61f 100644 --- a/include/ust/lttng-ust-abi.h +++ b/include/ust/lttng-ust-abi.h @@ -43,6 +43,16 @@ struct lttng_ust_channel { enum lttng_ust_output output; /* output mode */ }; +/* + * This structure is only used internally within UST. It is not per-se + * part of the communication between sessiond and UST. + */ +struct lttng_ust_stream { + int shm_fd; + int wait_fd; + uint64_t memory_map_size; +}; + struct lttng_ust_event { char name[LTTNG_UST_SYM_NAME_LEN]; /* event name */ enum lttng_ust_instrumentation instrumentation; diff --git a/libringbuffer/frontend.h b/libringbuffer/frontend.h index 2385d39..c1d8dd4 100644 --- a/libringbuffer/frontend.h +++ b/libringbuffer/frontend.h @@ -67,7 +67,9 @@ void *channel_destroy(struct channel *chan, struct shm_handle *handle); extern struct lib_ring_buffer *channel_get_ring_buffer( const struct lib_ring_buffer_config *config, struct channel *chan, int cpu, - struct shm_handle *handle); + struct shm_handle *handle, + int *shm_fd, int *wait_fd, + uint64_t *memory_map_size); extern int lib_ring_buffer_open_read(struct lib_ring_buffer *buf, struct shm_handle *handle); extern void lib_ring_buffer_release_read(struct lib_ring_buffer *buf, diff --git a/libringbuffer/ring_buffer_backend.c b/libringbuffer/ring_buffer_backend.c index 3e20297..72ddacf 100644 --- a/libringbuffer/ring_buffer_backend.c +++ b/libringbuffer/ring_buffer_backend.c @@ -482,7 +482,6 @@ void *lib_ring_buffer_offset_address(struct lib_ring_buffer_backend *bufb, struct channel_backend *chanb = &shmp(handle, bufb->chan)->backend; const struct lib_ring_buffer_config *config = chanb->config; unsigned long sb_bindex, id; - void *ret; offset &= chanb->buf_size - 1; sbidx = offset >> chanb->subbuf_size_order; diff --git a/libringbuffer/ring_buffer_frontend.c b/libringbuffer/ring_buffer_frontend.c index bd774df..7dab159 100644 --- a/libringbuffer/ring_buffer_frontend.c +++ b/libringbuffer/ring_buffer_frontend.c @@ -577,12 +577,23 @@ void *channel_destroy(struct channel *chan, struct shm_handle *handle) struct lib_ring_buffer *channel_get_ring_buffer( const struct lib_ring_buffer_config *config, struct channel *chan, int cpu, - struct shm_handle *handle) + struct shm_handle *handle, + int *shm_fd, int *wait_fd, + uint64_t *memory_map_size) { - if (config->alloc == RING_BUFFER_ALLOC_GLOBAL) + struct shm_ref *ref; + + if (config->alloc == RING_BUFFER_ALLOC_GLOBAL) { + ref = &chan->backend.buf[0].shmp._ref; + shm_get_object_data(handle, ref, shm_fd, wait_fd, + memory_map_size); return shmp(handle, chan->backend.buf[0].shmp); - else + } else { + ref = &chan->backend.buf[cpu].shmp._ref; + shm_get_object_data(handle, ref, shm_fd, wait_fd, + memory_map_size); return shmp(handle, chan->backend.buf[cpu].shmp); + } } int lib_ring_buffer_open_read(struct lib_ring_buffer *buf, diff --git a/libringbuffer/shm.h b/libringbuffer/shm.h index 22c9afd..5785b71 100644 --- a/libringbuffer/shm.h +++ b/libringbuffer/shm.h @@ -103,4 +103,22 @@ int shm_get_wait_fd(struct shm_handle *handle, struct shm_ref *ref) return obj->wait_fd[0]; } +static inline +int shm_get_object_data(struct shm_handle *handle, struct shm_ref *ref, + int *shm_fd, int *wait_fd, uint64_t *memory_map_size) +{ + struct shm_object_table *table = handle->table; + struct shm_object *obj; + size_t index; + + index = (size_t) ref->index; + if (unlikely(index >= table->allocated_len)) + return -EPERM; + obj = &table->objects[index]; + *shm_fd = obj->shm_fd; + *wait_fd = obj->wait_fd[0]; + *memory_map_size = obj->memory_map_size; + return 0; +} + #endif /* _LIBRINGBUFFER_SHM_H */ diff --git a/libust/ltt-ring-buffer-client.h b/libust/ltt-ring-buffer-client.h index 2fe854a..605a282 100644 --- a/libust/ltt-ring-buffer-client.h +++ b/libust/ltt-ring-buffer-client.h @@ -399,13 +399,17 @@ void ltt_channel_destroy(struct ltt_channel *ltt_chan) static struct lib_ring_buffer *ltt_buffer_read_open(struct channel *chan, - struct shm_handle *handle) + struct shm_handle *handle, + int *shm_fd, int *wait_fd, + uint64_t *memory_map_size) { struct lib_ring_buffer *buf; int cpu; for_each_channel_cpu(cpu, chan) { - buf = channel_get_ring_buffer(&client_config, chan, cpu, handle); + buf = channel_get_ring_buffer(&client_config, chan, + cpu, handle, shm_fd, wait_fd, + memory_map_size); if (!lib_ring_buffer_open_read(buf, handle)) return buf; } diff --git a/libust/ltt-ring-buffer-metadata-client.h b/libust/ltt-ring-buffer-metadata-client.h index 3e16890..dd16846 100644 --- a/libust/ltt-ring-buffer-metadata-client.h +++ b/libust/ltt-ring-buffer-metadata-client.h @@ -179,11 +179,14 @@ void ltt_channel_destroy(struct ltt_channel *ltt_chan) static struct lib_ring_buffer *ltt_buffer_read_open(struct channel *chan, - struct shm_handle *handle) + struct shm_handle *handle, + int *shm_fd, int *wait_fd, + uint64_t *memory_map_size) { struct lib_ring_buffer *buf; - buf = channel_get_ring_buffer(&client_config, chan, 0, handle); + buf = channel_get_ring_buffer(&client_config, chan, + 0, handle, shm_fd, wait_fd, memory_map_size); if (!lib_ring_buffer_open_read(buf, handle)) return buf; return NULL; diff --git a/libust/lttng-ust-abi.c b/libust/lttng-ust-abi.c index ccaa17f..0c0d6bb 100644 --- a/libust/lttng-ust-abi.c +++ b/libust/lttng-ust-abi.c @@ -204,6 +204,7 @@ static const struct objd_ops lttng_session_ops; static const struct objd_ops lttng_channel_ops; static const struct objd_ops lttng_metadata_ops; static const struct objd_ops lttng_event_ops; +static const struct objd_ops lib_ring_buffer_objd_ops; enum channel_type { PER_CPU_CHANNEL, @@ -505,35 +506,46 @@ static const struct objd_ops lttng_session_ops = { .cmd = lttng_session_cmd, }; -#if 0 +struct stream_priv_data { + struct lib_ring_buffer *buf; + struct ltt_channel *ltt_chan; +}; + static -int lttng_abi_open_stream(int channel_objd) +int lttng_abi_open_stream(int channel_objd, struct lttng_ust_stream *info) { struct ltt_channel *channel = objd_private(channel_objd); struct lib_ring_buffer *buf; + struct stream_priv_data *priv; int stream_objd, ret; - buf = channel->ops->buffer_read_open(channel->chan); + buf = channel->ops->buffer_read_open(channel->chan, channel->handle, + &info->shm_fd, &info->wait_fd, &info->memory_map_size); if (!buf) return -ENOENT; - stream_objd = objd_alloc(buf, &lib_ring_buffer_objd_ops); + priv = zmalloc(sizeof(*priv)); + if (!priv) { + ret = -ENOMEM; + goto alloc_error; + } + priv->buf = buf; + priv->ltt_chan = channel; + stream_objd = objd_alloc(priv, &lib_ring_buffer_objd_ops); if (stream_objd < 0) { ret = stream_objd; goto objd_error; } - /* - * The stream holds a reference to the channel within the generic ring - * buffer library, so no need to hold a refcount on the channel and - * session files here. - */ + /* Hold a reference on the channel object descriptor */ + objd_ref(channel_objd); return stream_objd; objd_error: - channel->ops->buffer_read_close(buf); + free(priv); +alloc_error: + channel->ops->buffer_read_close(buf, channel->handle); return ret; } -#endif //0 static int lttng_abi_create_event(int channel_objd, @@ -603,8 +615,13 @@ long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg) switch (cmd) { case LTTNG_UST_STREAM: - return -ENOSYS; //TODO - //return lttng_abi_open_stream(objd); + { + struct lttng_ust_stream *stream; + + stream = (struct lttng_ust_stream *) arg; + /* stream used as output */ + return lttng_abi_open_stream(objd, stream); + } case LTTNG_UST_EVENT: return lttng_abi_create_event(objd, (struct lttng_ust_event *) arg); case LTTNG_UST_CONTEXT: @@ -638,8 +655,13 @@ long lttng_metadata_cmd(int objd, unsigned int cmd, unsigned long arg) { switch (cmd) { case LTTNG_UST_STREAM: - return -ENOSYS; //TODO - //return lttng_abi_open_stream(objd); + { + struct lttng_ust_stream *stream; + + stream = (struct lttng_ust_stream *) arg; + /* stream used as output */ + return lttng_abi_open_stream(objd, stream); + } default: return -EINVAL; } @@ -696,6 +718,50 @@ static const struct objd_ops lttng_metadata_ops = { .cmd = lttng_metadata_cmd, }; +/** + * lttng_rb_cmd - lttng ring buffer control through object descriptors + * + * @objd: the object descriptor + * @cmd: the command + * @arg: command arg + * + * This object descriptor implements lttng commands: + * (None for now. Access is done directly though shm.) + * TODO: Add buffer flush. + */ +static +long lttng_rb_cmd(int objd, unsigned int cmd, unsigned long arg) +{ + struct stream_priv_data *priv = objd_private(objd); + + switch (cmd) { + default: + return -EINVAL; + } +} + +static +int lttng_rb_release(int objd) +{ + struct stream_priv_data *priv = objd_private(objd); + struct lib_ring_buffer *buf; + struct ltt_channel *channel; + + if (priv) { + buf = priv->buf; + channel = priv->ltt_chan; + free(priv); + + return objd_unref(channel->objd); + } + return 0; +} + +static const struct objd_ops lib_ring_buffer_objd_ops = { + .release = lttng_rb_release, + .cmd = lttng_rb_cmd, +}; + /** * lttng_event_cmd - lttng control through object descriptors * diff --git a/libust/lttng-ust-comm.c b/libust/lttng-ust-comm.c index c5a3064..d88c4af 100644 --- a/libust/lttng-ust-comm.c +++ b/libust/lttng-ust-comm.c @@ -282,8 +282,33 @@ end: } else { lur.ret_code = LTTCOMM_SESSION_FAIL; } + if (lum->cmd == LTTNG_UST_STREAM) { + /* + * Special-case reply to send stream info. + * Use lum.u output. + */ + lur.u.stream.memory_map_size = lum->u.stream.memory_map_size; + } ret = send_reply(sock, &lur); + if (lum->cmd == LTTNG_UST_STREAM && ret >= 0) { + /* we also need to send the file descriptors. */ + ret = lttcomm_send_fds_unix_sock(sock, + &lum->u.stream.shm_fd, &lum->u.stream.shm_fd, + 1, sizeof(int)); + if (ret < 0) { + perror("send shm_fd"); + goto error; + } + ret = lttcomm_send_fds_unix_sock(sock, + &lum->u.stream.wait_fd, &lum->u.stream.wait_fd, + 1, sizeof(int)); + if (ret < 0) { + perror("send wait_fd"); + goto error; + } + } +error: ust_unlock(); return ret; } -- 2.34.1