From 48842b309b2000205367409c0f29ca40ec3e251c Mon Sep 17 00:00:00 2001 From: David Goulet Date: Wed, 2 Nov 2011 15:44:27 -0400 Subject: [PATCH] Preliminary work for full UST support Add hashtable support for all UST data structure. At this point, enable channel and event works with the global UST domain. The interaction with the ust consumer has problems for now thus not working at this stage. NOTICE: This commit does NOT work with the user space tracer yet. Please refer to next commit for working version. Signed-off-by: David Goulet --- ltt-sessiond/Makefile.am | 10 +- ltt-sessiond/channel.c | 86 +++--- ltt-sessiond/channel.h | 2 +- ltt-sessiond/context.c | 46 ++- ltt-sessiond/context.h | 3 +- ltt-sessiond/event.c | 68 ++--- ltt-sessiond/event.h | 2 +- ltt-sessiond/hashtable.c | 4 +- ltt-sessiond/main.c | 472 +++++------------------------ ltt-sessiond/session.h | 1 - ltt-sessiond/trace-ust.c | 33 +-- ltt-sessiond/trace-ust.h | 58 +--- ltt-sessiond/ust-app.c | 571 +++++++++++++++++++++++++++++++++++- ltt-sessiond/ust-app.h | 52 +++- ltt-sessiond/ust-consumer.c | 199 +++++++++++++ ltt-sessiond/ust-consumer.h | 25 ++ ltt-sessiond/ust-ctl.h | 40 ++- 17 files changed, 1067 insertions(+), 605 deletions(-) create mode 100644 ltt-sessiond/ust-consumer.c create mode 100644 ltt-sessiond/ust-consumer.h diff --git a/ltt-sessiond/Makefile.am b/ltt-sessiond/Makefile.am index f3723016e..4c23849cf 100644 --- a/ltt-sessiond/Makefile.am +++ b/ltt-sessiond/Makefile.am @@ -16,24 +16,24 @@ ltt_sessiond_SOURCES = utils.c utils.h \ compat/poll.h $(COMPAT) \ trace-kernel.c trace-kernel.h \ kernel-ctl.c kernel-ctl.h \ - ust-ctl.h ust-app.h trace-ust.h \ + ust-ctl.h ust-app.h trace-ust.h \ context.c context.h \ channel.c channel.h \ event.c event.h \ futex.c futex.h \ shm.c shm.h \ session.c session.h \ - ltt-sessiond.h main.c \ ../hashtable/rculfhash.c \ ../hashtable/rculfhash.h \ ../hashtable/hash.c ../hashtable/hash.h if LTTNG_TOOLS_HAVE_UST -ltt_sessiond_SOURCES += \ - trace-ust.c \ - ust-app.c +ltt_sessiond_SOURCES += trace-ust.c ust-app.c ust-consumer.c ust-consumer.h endif +# Add main.c at the end for compile order +ltt_sessiond_SOURCES += ltt-sessiond.h main.c + # link on liblttngctl for check if sessiond is already alive. ltt_sessiond_LDADD = -lrt -lurcu-cds -lurcu \ $(top_builddir)/liblttng-sessiond-comm/liblttng-sessiond-comm.la \ diff --git a/ltt-sessiond/channel.c b/ltt-sessiond/channel.c index 3870af4be..fda679c78 100644 --- a/ltt-sessiond/channel.c +++ b/ltt-sessiond/channel.c @@ -206,62 +206,60 @@ error: /* * Create UST channel and enable it on the tracer. */ -int channel_ust_create(struct ltt_ust_session *usession, - struct lttng_channel *chan, int sock) +int channel_ust_create(struct ltt_ust_session *usess, + struct lttng_channel *attr) { int ret; - struct lttng_channel *attr = chan; - struct ltt_ust_channel *suchan; - struct lttng_ust_channel_attr uattr; - struct object_data *obj; - - /* Creating channel attributes if needed */ - if (attr == NULL) { - /* FIXME: this appears to be a memory leak */ - /* TODO: get default for other UST domains */ - attr = channel_new_default_attr(LTTNG_DOMAIN_UST); - if (attr == NULL) { - ret = LTTCOMM_FATAL; + struct ltt_ust_channel *uchan; + //struct lttng_ust_channel_attr uattr; + //struct object_data *obj; + + uchan = trace_ust_find_channel_by_name(usess->domain_global.channels, + attr->name); + if (uchan == NULL) { + uchan = trace_ust_create_channel(attr, usess->pathname); + if (uchan == NULL) { + ret = LTTCOMM_UST_CHAN_FAIL; goto error; } - } - - suchan = trace_ust_create_channel(attr, usession->path); - if (suchan == NULL) { - ret = LTTCOMM_UST_CHAN_FAIL; + rcu_read_lock(); + hashtable_add_unique(usess->domain_global.channels, &uchan->node); + rcu_read_unlock(); + } else { + ret = LTTCOMM_UST_CHAN_EXIST; goto error; } - uattr.overwrite = attr->attr.overwrite; - uattr.subbuf_size = attr->attr.subbuf_size; - uattr.num_subbuf = attr->attr.num_subbuf; - uattr.switch_timer_interval = attr->attr.switch_timer_interval; - uattr.read_timer_interval = attr->attr.read_timer_interval; - uattr.output = attr->attr.output; - ret = ustctl_create_channel(sock, usession->handle, - &uattr, &obj); + /* TODO: NOTIFY ust application to update */ + /* + ret = ustctl_create_channel(sock, usession->handle, &uattr, &obj); if (ret < 0) { ret = LTTCOMM_UST_CHAN_FAIL; goto error; } + */ - suchan->attr.overwrite = uattr.overwrite; - suchan->attr.subbuf_size = uattr.subbuf_size; - suchan->attr.num_subbuf = uattr.num_subbuf; - suchan->attr.switch_timer_interval = uattr.switch_timer_interval; - suchan->attr.read_timer_interval = uattr.read_timer_interval; - suchan->attr.output = uattr.output; - suchan->handle = obj->handle; - suchan->attr.shm_fd = obj->shm_fd; - suchan->attr.wait_fd = obj->wait_fd; - suchan->attr.memory_map_size = obj->memory_map_size; - suchan->obj = obj; + /* + uchan->attr.overwrite = uattr.overwrite; + uchan->attr.subbuf_size = uattr.subbuf_size; + uchan->attr.num_subbuf = uattr.num_subbuf; + uchan->attr.switch_timer_interval = uattr.switch_timer_interval; + uchan->attr.read_timer_interval = uattr.read_timer_interval; + uchan->attr.output = uattr.output; + uchan->handle = obj->handle; + uchan->attr.shm_fd = obj->shm_fd; + uchan->attr.wait_fd = obj->wait_fd; + uchan->attr.memory_map_size = obj->memory_map_size; + uchan->obj = obj; + */ /* Add channel to session */ - cds_list_add(&suchan->list, &usession->channels.head); - usession->channels.count++; + //rcu_read_lock(); + //cds_list_add(&uchan->list, &usession->channels.head); + //usession->channels.count++; + //rcu_read_unlock(); - DBG2("Channel %s UST create successfully for sock:%d", suchan->name, sock); + //DBG2("Channel %s UST create successfully for sock:%d", uchan->name, sock); ret = LTTCOMM_OK; @@ -276,9 +274,9 @@ int channel_ust_enable(struct ltt_ust_session *usession, struct ltt_ust_channel *uchan, int sock) { int ret = LTTCOMM_OK; +#ifdef DISABLE struct object_data obj; - obj.handle = uchan->handle; obj.shm_fd = uchan->attr.shm_fd; obj.wait_fd = uchan->attr.wait_fd; obj.memory_map_size = uchan->attr.memory_map_size; @@ -289,6 +287,7 @@ int channel_ust_enable(struct ltt_ust_session *usession, } ret = LTTCOMM_OK; end: +#endif return ret; } @@ -299,9 +298,9 @@ int channel_ust_disable(struct ltt_ust_session *usession, struct ltt_ust_channel *uchan, int sock) { int ret = LTTCOMM_OK; +#ifdef DISABLE struct object_data obj; - obj.handle = uchan->handle; obj.shm_fd = uchan->attr.shm_fd; obj.wait_fd = uchan->attr.wait_fd; obj.memory_map_size = uchan->attr.memory_map_size; @@ -312,5 +311,6 @@ int channel_ust_disable(struct ltt_ust_session *usession, } ret = LTTCOMM_OK; end: +#endif return ret; } diff --git a/ltt-sessiond/channel.h b/ltt-sessiond/channel.h index dfde76994..37c1b8c0a 100644 --- a/ltt-sessiond/channel.h +++ b/ltt-sessiond/channel.h @@ -31,7 +31,7 @@ int channel_kernel_create(struct ltt_kernel_session *ksession, struct lttng_channel *chan, int kernel_pipe); int channel_ust_create(struct ltt_ust_session *usession, - struct lttng_channel *chan, int sock); + struct lttng_channel *chan); int channel_ust_copy(struct ltt_ust_channel *dst, struct ltt_ust_channel *src); int channel_ust_disable(struct ltt_ust_session *usession, diff --git a/ltt-sessiond/context.c b/ltt-sessiond/context.c index c7765c0e8..41e33ec27 100644 --- a/ltt-sessiond/context.c +++ b/ltt-sessiond/context.c @@ -34,6 +34,7 @@ #endif #include "context.h" +#include "hashtable.h" #include "kernel-ctl.h" /* @@ -207,6 +208,7 @@ error: /* * Add UST context to an event of a specific channel. */ +#ifdef DISABLE static int add_ustctx_to_event(struct ltt_ust_session *ustsession, struct lttng_ust_context *ustctx, struct ltt_ust_channel *ustchan, char *event_name) @@ -217,7 +219,7 @@ static int add_ustctx_to_event(struct ltt_ust_session *ustsession, DBG("Add UST context to event %s", event_name); - ustevent = trace_ust_get_event_by_name(event_name, ustchan); + ustevent = trace_ust_find_event_by_name(ustchan->events, event_name); if (ustevent != NULL) { ret = ustctl_add_context(ustsession->sock, ustctx, ustevent->obj, &context_data); @@ -232,6 +234,7 @@ static int add_ustctx_to_event(struct ltt_ust_session *ustsession, error: return ret; } +#endif /* * Add UST context to all channel. @@ -239,8 +242,10 @@ error: * If event_name is specified, add context to event instead. */ static int add_ustctx_all_channels(struct ltt_ust_session *ustsession, - struct lttng_ust_context *ustctx, char *event_name) + struct lttng_ust_context *ustctx, char *event_name, + struct cds_lfht *channels) { +#ifdef DISABLE int ret, no_event = 0, found = 0; struct ltt_ust_channel *ustchan; struct object_data *context_data; /* FIXME: currently a memleak */ @@ -251,11 +256,16 @@ static int add_ustctx_all_channels(struct ltt_ust_session *ustsession, DBG("Adding ust context to all channels (event: %s)", event_name); - /* Go over all channels */ - cds_list_for_each_entry(ustchan, &ustsession->channels.head, list) { + struct cds_lfht_node *node; + struct cds_lfht_iter iter; + + rcu_read_lock(); + hashtable_get_first(channels, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + ustchan = caa_container_of(node, struct ltt_ust_channel, node); if (no_event) { - ret = ustctl_add_context(ustsession->sock, - ustctx, ustchan->obj, &context_data); + //ret = ustctl_add_context(ustsession->sock, + // ustctx, ustchan->obj, &context_data); if (ret < 0) { ret = LTTCOMM_UST_CONTEXT_FAIL; goto error; @@ -271,7 +281,9 @@ static int add_ustctx_all_channels(struct ltt_ust_session *ustsession, break; } } + hashtable_get_next(channels, &iter); } + rcu_read_unlock(); if (!found && !no_event) { ret = LTTCOMM_NO_EVENT; @@ -282,6 +294,8 @@ static int add_ustctx_all_channels(struct ltt_ust_session *ustsession, error: return ret; +#endif + return 0; } /* @@ -293,6 +307,7 @@ static int add_ustctx_to_channel(struct ltt_ust_session *ustsession, struct lttng_ust_context *ustctx, struct ltt_ust_channel *ustchan, char *event_name) { +#ifdef DISABLE int ret, no_event = 0, found = 0; struct object_data *context_data; /* FIXME: currently a memleak */ @@ -304,8 +319,8 @@ static int add_ustctx_to_channel(struct ltt_ust_session *ustsession, ustchan->name, event_name); if (no_event) { - ret = ustctl_add_context(ustsession->sock, ustctx, - ustchan->obj, &context_data); + //ret = ustctl_add_context(ustsession->sock, ustctx, + // ustchan->obj, &context_data); if (ret < 0) { ret = LTTCOMM_UST_CONTEXT_FAIL; goto error; @@ -330,6 +345,8 @@ static int add_ustctx_to_channel(struct ltt_ust_session *ustsession, error: return ret; +#endif + return 0; } /* @@ -337,23 +354,30 @@ error: */ int context_ust_add(struct ltt_ust_session *ustsession, struct lttng_event_context *ctx, char *event_name, - char *channel_name) + char *channel_name, int domain) { int ret; + struct cds_lfht *chan_ht = NULL; struct ltt_ust_channel *ustchan; struct lttng_ust_context ustctx; /* Setup UST context structure */ ustctx.ctx = ctx->ctx; + switch (domain) { + case LTTNG_DOMAIN_UST: + chan_ht = ustsession->domain_global.channels; + break; + } + if (strlen(channel_name) == 0) { - ret = add_ustctx_all_channels(ustsession, &ustctx, event_name); + ret = add_ustctx_all_channels(ustsession, &ustctx, event_name, chan_ht); if (ret != LTTCOMM_OK) { goto error; } } else { /* Get UST channel */ - ustchan = trace_ust_get_channel_by_name(channel_name, ustsession); + ustchan = trace_ust_find_channel_by_name(chan_ht, channel_name); if (ustchan == NULL) { ret = LTTCOMM_UST_CHAN_NOT_FOUND; goto error; diff --git a/ltt-sessiond/context.h b/ltt-sessiond/context.h index 872e77e7b..e97e9489a 100644 --- a/ltt-sessiond/context.h +++ b/ltt-sessiond/context.h @@ -32,6 +32,7 @@ int context_kernel_add(struct ltt_kernel_session *ksession, struct lttng_event_context *ctx, char *event_name, char *channel_name); int context_ust_add(struct ltt_ust_session *ustsession, - struct lttng_event_context *ctx, char *event_name, char *channel_name); + struct lttng_event_context *ctx, char *event_name, + char *channel_name, int domain); #endif /* _LTT_CONTEXT_H */ diff --git a/ltt-sessiond/event.c b/ltt-sessiond/event.c index eef0039d6..1f90c1c73 100644 --- a/ltt-sessiond/event.c +++ b/ltt-sessiond/event.c @@ -31,6 +31,7 @@ #include "channel.h" #include "event.h" +#include "hashtable.h" #include "kernel-ctl.h" /* @@ -240,67 +241,49 @@ end: /* * Enable UST tracepoint event for a channel from a UST session. */ -int event_ust_enable_tracepoint(struct ltt_ust_session *ustsession, - struct ltt_ust_channel *ustchan, struct lttng_event *event) +#ifdef DISABLE +int event_ust_enable_tracepoint(struct ltt_ust_session *usess, + struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent) { int ret; - struct ltt_ust_event *ustevent; - struct lttng_ust_event lttngustevent; - struct object_data *object_event; + struct lttng_ust_event ltt_uevent; + struct object_data *obj_event; - ustevent = trace_ust_get_event_by_name(event->name, ustchan); - if (ustevent == NULL) { - ustevent = trace_ust_create_event(event); - if (ustevent == NULL) { - ret = -1; - goto end; - } - strncpy(lttngustevent.name, event->name, - LTTNG_UST_SYM_NAME_LEN); - lttngustevent.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; - /* TODO: adjust to other instrumentation types */ - lttngustevent.instrumentation = LTTNG_UST_TRACEPOINT; - ret = ustctl_create_event(ustsession->sock, <tngustevent, - ustchan->obj, &object_event); - if (ret < 0) { - if (ret == -EEXIST) { - ret = LTTCOMM_KERN_EVENT_EXIST; - } else { - ret = LTTCOMM_KERN_ENABLE_FAIL; - } - goto end; - } - ustevent->obj = object_event; - ustevent->handle = object_event->handle; - ustevent->enabled = 1; - /* Add event to event list */ - cds_list_add(&ustevent->list, &ustchan->events.head); - ustchan->events.count++; - } else if (ustevent->enabled == 0) { - ret = ustctl_enable(ustsession->sock, ustevent->obj); - if (ret < 0) { - ret = LTTCOMM_KERN_ENABLE_FAIL; - goto end; - } - ustevent->enabled = 1; + strncpy(ltt_uevent.name, uevent->attr.name, sizeof(ltt_uevent.name)); + ltt_uevent.name[sizeof(ltt_uevent.name) - 1] = '\0'; + /* TODO: adjust to other instrumentation types */ + ltt_uevent.instrumentation = LTTNG_UST_TRACEPOINT; + + ret = ustctl_create_event(app->key.sock, <t_uevent, + uchan->obj, &obj_event); + if (ret < 0) { + DBG("Error ustctl create event %s for app pid: %d, sock: %d ret %d", + uevent->attr.name, app->key.pid, app->key.sock, ret); + goto next; } + + uevent->obj = obj_event; + uevent->handle = obj_event->handle; + uevent->enabled = 1; ret = LTTCOMM_OK; end: return ret; } +#endif +#ifdef DISABLE int event_ust_disable_tracepoint(struct ltt_ust_session *ustsession, struct ltt_ust_channel *ustchan, char *event_name) { int ret; struct ltt_ust_event *ustevent; - ustevent = trace_ust_get_event_by_name(event_name, ustchan); + ustevent = trace_ust_find_event_by_name(ustchan->events, event_name); if (ustevent == NULL) { ret = LTTCOMM_NO_EVENT; goto end; } - ret = ustctl_disable(ustsession->sock, ustevent->obj); + //ret = ustctl_disable(ustsession->sock, ustevent->obj); if (ret < 0) { ret = LTTCOMM_UST_ENABLE_FAIL; goto end; @@ -310,3 +293,4 @@ int event_ust_disable_tracepoint(struct ltt_ust_session *ustsession, end: return ret; } +#endif diff --git a/ltt-sessiond/event.h b/ltt-sessiond/event.h index 879ae659c..2852b3535 100644 --- a/ltt-sessiond/event.h +++ b/ltt-sessiond/event.h @@ -41,7 +41,7 @@ int event_kernel_enable_all(struct ltt_kernel_session *ksession, struct ltt_kernel_channel *kchan, int kernel_tracer_fd); int event_ust_enable_tracepoint(struct ltt_ust_session *ustsession, - struct ltt_ust_channel *ustchan, struct lttng_event *event); + struct ltt_ust_channel *ustchan, struct ltt_ust_event *uevent); int event_ust_disable_tracepoint(struct ltt_ust_session *ustsession, struct ltt_ust_channel *ustchan, char *event_name); diff --git a/ltt-sessiond/hashtable.c b/ltt-sessiond/hashtable.c index 37dc01c9e..6bca1dac0 100644 --- a/ltt-sessiond/hashtable.c +++ b/ltt-sessiond/hashtable.c @@ -30,7 +30,7 @@ struct cds_lfht *hashtable_new(unsigned long size) } return cds_lfht_new(hash_key, hash_compare_key, 0x42UL, - CDS_LFHT_AUTO_RESIZE, size, NULL); + size, size, CDS_LFHT_AUTO_RESIZE, NULL); } struct cds_lfht *hashtable_new_str(unsigned long size) @@ -40,7 +40,7 @@ struct cds_lfht *hashtable_new_str(unsigned long size) } return cds_lfht_new(hash_key_str, hash_compare_key_str, 0x42UL, - CDS_LFHT_AUTO_RESIZE, size, NULL); + size, size, CDS_LFHT_AUTO_RESIZE, NULL); } struct cds_lfht_node *hashtable_iter_get_node(struct cds_lfht_iter *iter) diff --git a/ltt-sessiond/main.c b/ltt-sessiond/main.c index 081b0c855..334af53a4 100644 --- a/ltt-sessiond/main.c +++ b/ltt-sessiond/main.c @@ -42,13 +42,6 @@ #include #include -#ifdef CONFIG_LTTNG_TOOLS_HAVE_UST -#include -#else -#include "lttng-ust-ctl.h" -#endif - - #include #include "channel.h" @@ -63,7 +56,6 @@ #include "ust-app.h" #include "ust-ctl.h" #include "utils.h" -#include "ust-ctl.h" struct consumer_data { enum lttng_consumer_type type; @@ -490,80 +482,6 @@ error: return ret; } -/* - * Send all stream fds of UST channel to the consumer. - */ -static int send_ustconsumer_channel_streams(struct consumer_data *consumer_data, - int sock, struct ltt_ust_channel *channel) -{ - int ret, fds[2]; - struct ltt_ust_stream *stream; - struct lttcomm_consumer_msg lum; - - DBG("Sending streams of channel %s to UST consumer", - channel->name); - - /* Send channel */ - lum.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL; - /* - * We need to keep shm_fd open to make sure this key stays - * unique within the session daemon. - */ - lum.u.channel.channel_key = channel->obj->shm_fd; - lum.u.channel.max_sb_size = channel->attr.subbuf_size; - lum.u.channel.mmap_len = channel->obj->memory_map_size; - DBG("Sending channel %d to consumer", lum.u.channel.channel_key); - ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum)); - if (ret < 0) { - perror("send consumer channel"); - goto error; - } - fds[0] = channel->obj->shm_fd; - fds[1] = channel->obj->wait_fd; - ret = lttcomm_send_fds_unix_sock(sock, fds, 2); - if (ret < 0) { - perror("send consumer channel ancillary data"); - goto error; - } - - /* Send streams */ - cds_list_for_each_entry(stream, &channel->stream_list.head, list) { - int fds[2]; - - if (!stream->obj->shm_fd) { - continue; - } - lum.cmd_type = LTTNG_CONSUMER_ADD_STREAM; - lum.u.stream.channel_key = channel->obj->shm_fd; - lum.u.stream.stream_key = stream->obj->shm_fd; - lum.u.stream.state = LTTNG_CONSUMER_ACTIVE_STREAM; - lum.u.stream.output = channel->attr.output; - lum.u.stream.mmap_len = stream->obj->memory_map_size; - strncpy(lum.u.stream.path_name, stream->pathname, PATH_MAX - 1); - lum.u.stream.path_name[PATH_MAX - 1] = '\0'; - DBG("Sending stream %d to consumer", lum.u.stream.stream_key); - ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum)); - if (ret < 0) { - perror("send consumer stream"); - goto error; - } - fds[0] = stream->obj->shm_fd; - fds[1] = stream->obj->wait_fd; - ret = lttcomm_send_fds_unix_sock(sock, fds, 2); - if (ret < 0) { - perror("send consumer stream ancillary data"); - goto error; - } - } - - DBG("consumer channel streams sent"); - - return 0; - -error: - return ret; -} - /* * Send all stream fds of the kernel session to the consumer. */ @@ -632,85 +550,6 @@ error: return ret; } -/* - * Send all stream fds of the UST session to the consumer. - */ -static int send_ustconsumer_session_streams(struct consumer_data *consumer_data, - struct ltt_ust_session *session) -{ - int ret; - struct ltt_ust_channel *chan; - struct lttcomm_consumer_msg lum; - int sock = session->consumer_fd; - - DBG("Sending metadata stream fd"); - - /* Extra protection. It's NOT supposed to be set to 0 at this point */ - if (session->consumer_fd == 0) { - session->consumer_fd = consumer_data->cmd_sock; - } - - if (session->metadata->obj->shm_fd != 0) { - int fds[2]; - - /* Send metadata channel fd */ - lum.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL; - lum.u.channel.channel_key = session->metadata->obj->shm_fd; - lum.u.channel.max_sb_size = session->metadata->attr.subbuf_size; - lum.u.channel.mmap_len = 0; /* for kernel */ - DBG("Sending metadata channel %d to consumer", lum.u.stream.stream_key); - ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum)); - if (ret < 0) { - perror("send consumer channel"); - goto error; - } - fds[0] = session->metadata->obj->shm_fd; - fds[1] = session->metadata->obj->wait_fd; - ret = lttcomm_send_fds_unix_sock(sock, fds, 2); - if (ret < 0) { - perror("send consumer metadata channel"); - goto error; - } - - /* Send metadata stream fd */ - lum.cmd_type = LTTNG_CONSUMER_ADD_STREAM; - lum.u.stream.channel_key = session->metadata->obj->shm_fd; - lum.u.stream.stream_key = session->metadata->stream_obj->shm_fd; - lum.u.stream.state = LTTNG_CONSUMER_ACTIVE_STREAM; - lum.u.stream.output = DEFAULT_UST_CHANNEL_OUTPUT; - lum.u.stream.mmap_len = session->metadata->stream_obj->memory_map_size; - strncpy(lum.u.stream.path_name, session->metadata->pathname, PATH_MAX - 1); - lum.u.stream.path_name[PATH_MAX - 1] = '\0'; - DBG("Sending metadata stream %d to consumer", lum.u.stream.stream_key); - ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum)); - if (ret < 0) { - perror("send consumer metadata stream"); - goto error; - } - fds[0] = session->metadata->stream_obj->shm_fd; - fds[1] = session->metadata->stream_obj->wait_fd; - ret = lttcomm_send_fds_unix_sock(sock, fds, 2); - if (ret < 0) { - perror("send consumer stream"); - goto error; - } - } - - cds_list_for_each_entry(chan, &session->channels.head, list) { - ret = send_ustconsumer_channel_streams(consumer_data, sock, chan); - if (ret < 0) { - goto error; - } - } - - DBG("consumer fds (metadata and channel streams) sent"); - - return 0; - -error: - return ret; -} - /* * Notify UST applications using the shm mmap futex. */ @@ -1055,7 +894,7 @@ static void *thread_manage_consumer(void *data) lttcomm_connect_unix_sock(consumer_data->cmd_unix_sock_path); if (consumer_data->cmd_sock < 0) { sem_post(&consumer_data->sem); - perror("consumer connect"); + PERROR("consumer connect"); goto error; } /* Signal condition to tell that the kconsumerd is ready */ @@ -1623,7 +1462,7 @@ static int start_consumerd(struct consumer_data *consumer_data) /* Setting up the consumer_data pid */ consumer_data->pid = ret; - DBG2("consumer pid %d", consumer_data->pid); + DBG2("Consumer pid %d", consumer_data->pid); pthread_mutex_unlock(&consumer_data->pid_mutex); DBG2("Spawning consumer control thread"); @@ -1814,36 +1653,6 @@ error: return ret; } -/* - * Init tracing by creating trace directory and sending fds ust consumer. - */ -static int init_ust_tracing(struct ltt_ust_session *session) -{ - int ret = 0; - - if (session->consumer_fds_sent == 0) { - /* - * Assign default ust consumer socket if no consumer assigned to the - * ust session. At this point, it's NOT suppose to be 0 but this is - * an extra security check. - */ - if (session->consumer_fd == 0) { - session->consumer_fd = ustconsumer_data.cmd_sock; - } - - ret = send_ustconsumer_session_streams(&ustconsumer_data, session); - if (ret < 0) { - ret = LTTCOMM_UST_CONSUMER_FAIL; - goto error; - } - - session->consumer_fds_sent = 1; - } - -error: - return ret; -} - /* * Create an UST session and add it to the session ust list. */ @@ -1851,16 +1660,11 @@ static int create_ust_session(struct ltt_session *session, struct lttng_domain *domain) { int ret; + unsigned int uid; struct ltt_ust_session *lus = NULL; - struct ust_app *app; switch (domain->type) { - case LTTNG_DOMAIN_UST_PID: - app = ust_app_find_by_pid(domain->attr.pid); - if (app == NULL) { - ret = LTTCOMM_APP_NOT_FOUND; - goto error; - } + case LTTNG_DOMAIN_UST: break; default: ret = LTTCOMM_UNKNOWN_DOMAIN; @@ -1869,13 +1673,17 @@ static int create_ust_session(struct ltt_session *session, DBG("Creating UST session"); - lus = trace_ust_create_session(session->path, domain->attr.pid, domain); + session_lock_list(); + uid = session_list_ptr->count; + session_unlock_list(); + + lus = trace_ust_create_session(session->path, uid, domain); if (lus == NULL) { ret = LTTCOMM_UST_SESS_FAIL; goto error; } - ret = mkdir_recursive(lus->path, S_IRWXU | S_IRWXG, + ret = mkdir_recursive(lus->pathname, S_IRWXU | S_IRWXG, geteuid(), allowed_group()); if (ret < 0) { if (ret != -EEXIST) { @@ -1887,39 +1695,13 @@ static int create_ust_session(struct ltt_session *session, /* The domain type dictate different actions on session creation */ switch (domain->type) { - case LTTNG_DOMAIN_UST_PID: - app = ust_app_find_by_pid(domain->attr.pid); - if (app == NULL) { - ret = LTTCOMM_APP_NOT_FOUND; - goto error; - } - /* Create session on the UST tracer */ - ret = ustctl_create_session(app->key.sock, lus); - if (ret < 0) { - ret = LTTCOMM_UST_SESS_FAIL; - goto error; - } - - lus->handle = ret; - break; - case LTTNG_DOMAIN_UST: - /* Create session on the UST tracer */ - ret = ustctl_create_session(app->key.sock, lus); - if (ret < 0) { - ret = LTTCOMM_UST_SESS_FAIL; - goto error; - } - break; - case LTTNG_DOMAIN_UST_EXEC_NAME: - break; - default: - goto error; + case LTTNG_DOMAIN_UST: + /* No ustctl for the global UST domain */ + break; + default: + goto error; } - lus->handle = ret; - lus->sock = app->sock; - session->ust_session = lus; - printf("%p\n", session->ust_session); return LTTCOMM_OK; @@ -2161,12 +1943,13 @@ static int cmd_enable_channel(struct ltt_session *session, { struct ltt_ust_channel *uchan; - DBG2("Enabling channel for LTTNG_DOMAIN_UST domain"); + DBG2("Enabling channel for LTTNG_DOMAIN_UST"); + /* Get channel in global UST domain HT */ uchan = trace_ust_find_channel_by_name(usess->domain_global.channels, attr->name); if (uchan == NULL) { - uchan = trace_ust_create_channel(attr, usess->path); + uchan = trace_ust_create_channel(attr, usess->pathname); if (uchan == NULL) { ret = LTTCOMM_UST_CHAN_FAIL; goto error; @@ -2174,12 +1957,16 @@ static int cmd_enable_channel(struct ltt_session *session, rcu_read_lock(); hashtable_add_unique(usess->domain_global.channels, &uchan->node); rcu_read_unlock(); + DBG2("UST channel %s added to global domain HT", attr->name); } else { ret = LTTCOMM_UST_CHAN_EXIST; goto error; } - /* TODO: Iterate over trace apps to enable that channel */ + ret = ust_app_add_channel(usess, uchan); + if (ret != LTTCOMM_OK) { + goto error; + } break; } @@ -2267,27 +2054,6 @@ static int cmd_disable_event(struct ltt_session *session, int domain, break; } case LTTNG_DOMAIN_UST: - { - struct ltt_ust_session *ustsession; - - cds_list_for_each_entry(ustsession, &session->ust_session_list.head, list) { - struct ltt_ust_channel *ustchan; - - ustchan = trace_ust_get_channel_by_name(channel_name, - ustsession); - if (ustchan == NULL) { - ret = LTTCOMM_KERN_CHAN_NOT_FOUND; - goto error; - } - ret = event_ust_disable_tracepoint(ustsession, ustchan, event_name); - if (ret != LTTCOMM_OK) { - goto error; - } - - ustctl_wait_quiescent(ustsession->sock); - } - break; - } case LTTNG_DOMAIN_UST_EXEC_NAME: case LTTNG_DOMAIN_UST_PID: case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: @@ -2359,17 +2125,18 @@ static int cmd_add_context(struct ltt_session *session, int domain, break; case LTTNG_DOMAIN_UST: { - struct ltt_ust_session *ustsession; + /* + struct ltt_ust_session *usess; - cds_list_for_each_entry(ustsession, &session->ust_session_list.head, list) { - /* Add UST context to UST tracer */ - ret = context_ust_add(ustsession, ctx, - event_name, channel_name); + cds_list_for_each_entry(usess, &session->ust_session_list.head, list) { + ret = context_ust_add(usess, ctx, + event_name, channel_name, domain); if (ret != LTTCOMM_OK) { goto error; } } break; + */ } default: /* TODO: UST other domains */ @@ -2391,6 +2158,7 @@ static int cmd_enable_event(struct ltt_session *session, int domain, { int ret; struct lttng_channel *attr; + struct ltt_ust_session *usess = session->ust_session; switch (domain) { case LTTNG_DOMAIN_KERNEL: @@ -2424,7 +2192,8 @@ static int cmd_enable_event(struct ltt_session *session, int domain, goto error; } - ret = event_kernel_enable_tracepoint(session->kernel_session, kchan, event); + ret = event_kernel_enable_tracepoint(session->kernel_session, kchan, + event); if (ret != LTTCOMM_OK) { goto error; } @@ -2434,43 +2203,30 @@ static int cmd_enable_event(struct ltt_session *session, int domain, } case LTTNG_DOMAIN_UST: { - struct ltt_ust_session *ustsession; - - cds_list_for_each_entry(ustsession, &session->ust_session_list.head, list) { - struct ltt_ust_channel *ustchan; - - ustchan = trace_ust_get_channel_by_name(channel_name, - ustsession); - if (ustchan == NULL) { - attr = channel_new_default_attr(domain); - if (attr == NULL) { - ret = LTTCOMM_FATAL; - goto error; - } - snprintf(attr->name, NAME_MAX, "%s", channel_name); + struct ltt_ust_channel *uchan; + struct ltt_ust_event *uevent; - ret = channel_ust_create(ustsession, - attr, ustsession->sock); - if (ret != LTTCOMM_OK) { - goto error; - } - } + uchan = trace_ust_find_channel_by_name(usess->domain_global.channels, + channel_name); + if (uchan == NULL) { + /* TODO: Create default channel */ + ret = LTTCOMM_UST_CHAN_NOT_FOUND; + goto error; + } - /* Get the newly created ust channel pointer */ - ustchan = trace_ust_get_channel_by_name(channel_name, - ustsession); - if (ustchan == NULL) { - /* This sould not happen... */ + uevent = trace_ust_find_event_by_name(uchan->events, event->name); + if (uevent == NULL) { + uevent = trace_ust_create_event(event); + if (uevent == NULL) { ret = LTTCOMM_FATAL; goto error; } + } - ret = event_ust_enable_tracepoint(ustsession, ustchan, event); - if (ret != LTTCOMM_OK) { - goto error; - } - - ustctl_wait_quiescent(ustsession->sock); + ret = ust_app_add_event(usess, uchan, uevent); + if (ret < 0) { + ret = LTTCOMM_UST_ENABLE_FAIL; + goto error; } break; } @@ -2478,7 +2234,6 @@ static int cmd_enable_event(struct ltt_session *session, int domain, case LTTNG_DOMAIN_UST_PID: case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: default: - /* TODO: UST other domains */ ret = LTTCOMM_NOT_IMPLEMENTED; goto error; } @@ -2596,7 +2351,7 @@ static int cmd_start_trace(struct ltt_session *session) { int ret; struct ltt_kernel_session *ksession; - struct ltt_ust_session *ustsession; + struct ltt_ust_session *usess = session->ust_session; /* Short cut */ ksession = session->kernel_session; @@ -2655,100 +2410,10 @@ static int cmd_start_trace(struct ltt_session *session) kernel_wait_quiescent(kernel_tracer_fd); } - /* Start all UST traces */ - cds_list_for_each_entry(ustsession, &session->ust_session_list.head, list) { - struct ltt_ust_channel *ustchan; - - /* Open kernel metadata */ - if (ustsession->metadata == NULL) { - struct lttng_ust_channel_attr ustattr; - - /* Allocate UST metadata */ - ustsession->metadata = trace_ust_create_metadata(ustsession->path); - if (ustsession->metadata == NULL) { - ret = LTTCOMM_UST_META_FAIL; - goto error; - } - - ustattr.overwrite = ustsession->metadata->attr.overwrite; - ustattr.subbuf_size = ustsession->metadata->attr.subbuf_size; - ustattr.num_subbuf = ustsession->metadata->attr.num_subbuf; - ustattr.switch_timer_interval = ustsession->metadata->attr.switch_timer_interval; - ustattr.read_timer_interval = ustsession->metadata->attr.read_timer_interval; - ustattr.output = ustsession->metadata->attr.output; - - /* UST tracer metadata creation */ - ret = ustctl_open_metadata(ustsession->sock, - ustsession->handle, &ustattr, - &ustsession->metadata->obj); - if (ret < 0) { - ret = LTTCOMM_UST_META_FAIL; - goto error; - } - } - - /* Open UST metadata stream */ - if (ustsession->metadata->stream_obj == NULL) { - ret = ustctl_create_stream(ustsession->sock, - ustsession->metadata->obj, - &ustsession->metadata->stream_obj); - if (ret < 0) { - ERR("UST create metadata stream failed"); - ret = LTTCOMM_UST_STREAM_FAIL; - goto error; - } - ret = asprintf(&ustsession->metadata->pathname, "%s/%s", - ustsession->path, "metadata"); - if (ret < 0) { - perror("asprintf UST create stream"); - goto error; - } - } - - /* For each channel */ - cds_list_for_each_entry(ustchan, &ustsession->channels.head, list) { - if (ustchan->stream_count == 0) { - struct ltt_ust_stream *ustream; - - ustream = zmalloc(sizeof(*ustream)); - if (!ustream) { - ret = LTTCOMM_UST_STREAM_FAIL; - goto error; - } - ret = ustctl_create_stream(ustsession->sock, - ustchan->obj, &ustream->obj); - if (ret < 0) { - ret = LTTCOMM_UST_STREAM_FAIL; - goto error; - } - ret = asprintf(&ustream->pathname, "%s/%s_%d", - ustchan->trace_path, ustchan->name, - ustchan->stream_count); - if (ret < 0) { - perror("asprintf UST create stream"); - goto error; - } - cds_list_add(&ustream->list, &ustchan->stream_list.head); - ustchan->stream_count++; - } - } - - /* Setup UST consumer socket and send fds to it */ - ret = init_ust_tracing(ustsession); - if (ret < 0) { - ret = LTTCOMM_UST_START_FAIL; - goto error; - } - - /* This start the UST tracing */ - ret = ustctl_start_session(ustsession->sock, ustsession->handle); - if (ret < 0) { - ret = LTTCOMM_UST_START_FAIL; - goto error; - } - - /* Quiescent wait after starting trace */ - ustctl_wait_quiescent(ustsession->sock); + ret = ust_app_start_trace(usess); + if (ret < 0) { + ret = LTTCOMM_UST_START_FAIL; + goto error; } ret = LTTCOMM_OK; @@ -2765,8 +2430,8 @@ static int cmd_stop_trace(struct ltt_session *session) int ret; struct ltt_kernel_channel *kchan; struct ltt_kernel_session *ksession; - struct ltt_ust_session *ustsession; - struct ltt_ust_channel *ustchan; + //struct ltt_ust_session *usess; + //struct ltt_ust_channel *ustchan; /* Short cut */ ksession = session->kernel_session; @@ -2797,30 +2462,32 @@ static int cmd_stop_trace(struct ltt_session *session) kernel_wait_quiescent(kernel_tracer_fd); } +#ifdef DISABLE /* Stop each UST session */ DBG("Stop UST tracing"); - cds_list_for_each_entry(ustsession, &session->ust_session_list.head, list) { + cds_list_for_each_entry(usess, &session->ust_session_list.head, list) { /* Flush all buffers before stopping */ - ret = ustctl_flush_buffer(ustsession->sock, ustsession->metadata->obj); + ret = ustctl_flush_buffer(usess->sock, usess->metadata->obj); if (ret < 0) { ERR("UST metadata flush failed"); } - cds_list_for_each_entry(ustchan, &ustsession->channels.head, list) { - ret = ustctl_flush_buffer(ustsession->sock, ustchan->obj); + cds_list_for_each_entry(ustchan, &usess->channels.head, list) { + ret = ustctl_flush_buffer(usess->sock, ustchan->obj); if (ret < 0) { ERR("UST flush buffer error"); } } - ret = ustctl_stop_session(ustsession->sock, ustsession->handle); + ret = ustctl_stop_session(usess->sock, usess->handle); if (ret < 0) { ret = LTTCOMM_KERN_STOP_FAIL; goto error; } - ustctl_wait_quiescent(ustsession->sock); + ustctl_wait_quiescent(usess->sock); } +#endif ret = LTTCOMM_OK; @@ -3135,11 +2802,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx) } break; case LTTNG_DOMAIN_UST: - case LTTNG_DOMAIN_UST_EXEC_NAME: - case LTTNG_DOMAIN_UST_PID: - case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: { - struct ltt_ust_session *usess; if (need_tracing_session) { if (cmd_ctx->session->ust_session == NULL) { ret = create_ust_session(cmd_ctx->session, @@ -3158,10 +2821,14 @@ static int process_client_msg(struct command_ctx *cmd_ctx) ret = LTTCOMM_KERN_CONSUMER_FAIL; goto error; } + + cmd_ctx->session->ust_session->consumer_fd = + ustconsumer_data.cmd_sock; } pthread_mutex_unlock(&ustconsumer_data.pid_mutex); } break; + } default: break; } @@ -4094,6 +3761,7 @@ int main(int argc, char **argv) if (ret < 0) { goto exit; } + ret = set_consumer_sockets(&ustconsumer_data); if (ret < 0) { goto exit; diff --git a/ltt-sessiond/session.h b/ltt-sessiond/session.h index 41883c609..f6a9fff4d 100644 --- a/ltt-sessiond/session.h +++ b/ltt-sessiond/session.h @@ -80,6 +80,5 @@ void session_unlock_list(void); struct ltt_session *session_find_by_name(char *name); struct ltt_session_list *session_get_list(void); -unsigned long session_ust_count(struct ltt_session *session); #endif /* _LTT_SESSION_H */ diff --git a/ltt-sessiond/trace-ust.c b/ltt-sessiond/trace-ust.c index b1066072b..e912c53c7 100644 --- a/ltt-sessiond/trace-ust.c +++ b/ltt-sessiond/trace-ust.c @@ -83,7 +83,7 @@ error: * * Return pointer to structure or NULL. */ -struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid, +struct ltt_ust_session *trace_ust_create_session(char *path, unsigned int uid, struct lttng_domain *domain) { int ret; @@ -97,10 +97,8 @@ struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid, } /* Init data structure */ - lus->handle = -1; - lus->enabled = 1; lus->consumer_fds_sent = 0; - lus->metadata = NULL; + lus->uid = uid; /* Alloc UST domain hash tables */ lus->domain_pid = hashtable_new(0); @@ -110,7 +108,7 @@ struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid, lus->domain_global.channels = hashtable_new_str(0); /* Set session path */ - ret = snprintf(lus->path, PATH_MAX, "%s/ust_%d", path, pid); + ret = snprintf(lus->pathname, PATH_MAX, "%s/ust", path); if (ret < 0) { PERROR("snprintf kernel traces path"); goto error; @@ -142,7 +140,12 @@ struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *chan, } /* Copy UST channel attributes */ - memcpy(&luc->attr, &chan->attr, sizeof(struct lttng_ust_channel)); + luc->attr.overwrite = chan->attr.overwrite; + luc->attr.subbuf_size = chan->attr.subbuf_size; + luc->attr.num_subbuf = chan->attr.num_subbuf; + luc->attr.switch_timer_interval = chan->attr.switch_timer_interval; + luc->attr.read_timer_interval = chan->attr.read_timer_interval; + luc->attr.output = chan->attr.output; /* Translate to UST output enum */ switch (luc->attr.output) { @@ -151,9 +154,6 @@ struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *chan, break; } - luc->handle = -1; - luc->enabled = 1; - /* Copy channel name */ strncpy(luc->name, chan->name, sizeof(&luc->name)); luc->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; @@ -165,12 +165,11 @@ struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *chan, luc->ctx = hashtable_new_str(0); /* Set trace output path */ - ret = snprintf(luc->trace_path, PATH_MAX, "%s", path); + ret = snprintf(luc->pathname, PATH_MAX, "%s", path); if (ret < 0) { perror("asprintf ust create channel"); goto error; } - CDS_INIT_LIST_HEAD(&luc->stream_list.head); DBG2("Trace UST channel %s created", luc->name); @@ -217,10 +216,6 @@ struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev) strncpy(lue->attr.name, ev->name, LTTNG_UST_SYM_NAME_LEN); lue->attr.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; - /* Setting up a ust event */ - lue->handle = -1; - lue->enabled = 1; - /* Init node */ hashtable_node_init(&lue->node, (void *) lue->attr.name, strlen(lue->attr.name)); @@ -459,11 +454,11 @@ void trace_ust_destroy_session(struct ltt_ust_session *session) rcu_read_lock(); - DBG2("Trace UST destroy session %d", session->handle); + DBG2("Trace UST destroy session %d", session->uid); - if (session->metadata != NULL) { - trace_ust_destroy_metadata(session->metadata); - } + //if (session->metadata != NULL) { + // trace_ust_destroy_metadata(session->metadata); + //} /* Cleaning up UST domain */ destroy_domain_global(&session->domain_global); diff --git a/ltt-sessiond/trace-ust.h b/ltt-sessiond/trace-ust.h index 2b133e8c4..518eafbe6 100644 --- a/ltt-sessiond/trace-ust.h +++ b/ltt-sessiond/trace-ust.h @@ -25,21 +25,10 @@ #include #include -/* - * FIXME: temporary workaround: we use a lttng-tools local version of - * lttng-ust-abi.h if UST is not found. Eventually, we should use our - * own internal structures within lttng-tools instead of relying on the - * UST ABI. - */ -#ifdef CONFIG_CONFIG_LTTNG_TOOLS_HAVE_UST -#include -#else -#include "lttng-ust-abi.h" -#endif +#include "ust-ctl.h" #include "../hashtable/rculfhash.h" - /* UST Stream list */ struct ltt_ust_stream_list { unsigned int count; @@ -54,9 +43,6 @@ struct ltt_ust_context { /* UST event */ struct ltt_ust_event { - int handle; - int enabled; - struct object_data *obj; struct lttng_ust_event attr; struct cds_lfht *ctx; struct cds_lfht_node node; @@ -64,22 +50,16 @@ struct ltt_ust_event { /* UST stream */ struct ltt_ust_stream { - /* TODO hashtable */ + int handle; + char pathname[PATH_MAX]; struct object_data *obj; - struct cds_list_head list; - char *pathname; + struct cds_lfht_node node; }; /* UST channel */ struct ltt_ust_channel { - int handle; - int enabled; char name[LTTNG_UST_SYM_NAME_LEN]; - char trace_path[PATH_MAX]; /* Trace file path name */ - struct object_data *obj; - - unsigned int stream_count; - struct ltt_ust_stream_list stream_list; + char pathname[PATH_MAX]; struct lttng_ust_channel attr; struct cds_lfht *ctx; struct cds_lfht *events; @@ -116,19 +96,15 @@ struct ltt_ust_domain_exec { /* UST session */ struct ltt_ust_session { - int sock; /* socket to send cmds to app */ - int handle; - int enabled; + int uid; /* Unique identifier of session */ int consumer_fds_sent; int consumer_fd; - char path[PATH_MAX]; - struct ltt_ust_metadata *metadata; - struct object_data *obj; + char pathname[PATH_MAX]; struct ltt_ust_domain_global domain_global; /* - * Those two hash tables contains data for a specific UST domain and a HT - * of channels for each. See ltt_ust_domain_exec and ltt_ust_domain_pid - * data structures. + * Those two hash tables contains data for a specific UST domain and each + * contains a HT of channels. See ltt_ust_domain_exec and + * ltt_ust_domain_pid data structures. */ struct cds_lfht *domain_pid; struct cds_lfht *domain_exec; @@ -147,7 +123,7 @@ struct ltt_ust_channel *trace_ust_find_channel_by_name(struct cds_lfht *ht, /* * Create functions malloc() the data structure. */ -struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid, +struct ltt_ust_session *trace_ust_create_session(char *path, unsigned int uid, struct lttng_domain *domain); struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *attr, char *path); @@ -179,13 +155,6 @@ struct ltt_ust_channel *trace_ust_find_channel_by_name(struct cds_lfht *ht, return NULL; } -static inline -struct ltt_ust_session *trace_ust_get_session_by_pid( - struct ltt_ust_session_list *session_list, pid_t pid) -{ - return NULL; -} - static inline struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid, struct lttng_domain *domain) @@ -213,19 +182,22 @@ static inline void trace_ust_destroy_session(struct ltt_ust_session *session) { } + static inline void trace_ust_destroy_metadata(struct ltt_ust_metadata *metadata) { } + static inline void trace_ust_destroy_channel(struct ltt_ust_channel *channel) { } + static inline void trace_ust_destroy_event(struct ltt_ust_event *event) { } -#endif +#endif /* CONFIG_CONFIG_LTTNG_TOOLS_HAVE_UST */ #endif /* _LTT_TRACE_UST_H */ diff --git a/ltt-sessiond/ust-app.c b/ltt-sessiond/ust-app.c index c8dd848b1..6bdd04bd8 100644 --- a/ltt-sessiond/ust-app.c +++ b/ltt-sessiond/ust-app.c @@ -25,10 +25,13 @@ #include #include +#include #include "hashtable.h" #include "ust-app.h" #include "../hashtable/hash.h" +#include "ust-ctl.h" +#include "ust-consumer.h" /* * Delete a traceable application structure from the global list. @@ -41,17 +44,7 @@ static void delete_ust_app(struct ust_app *lta) rcu_read_lock(); - hashtable_get_first(lta->channels, &iter); - while ((node = hashtable_iter_get_node(&iter)) != NULL) { - ret = hashtable_del(lta->channels, &iter); - if (!ret) { - trace_ust_destroy_channel( - caa_container_of(node, struct ltt_ust_channel, node)); - } - hashtable_get_next(lta->channels, &iter); - } - - free(lta->channels); + free(lta->sessions); close(lta->key.sock); /* Remove from apps hash table */ @@ -111,7 +104,6 @@ static struct ust_app *find_app_by_sock(int sock) struct cds_lfht_node *node; struct ust_app_key *key; struct cds_lfht_iter iter; - //struct ust_app *app; rcu_read_lock(); @@ -186,7 +178,7 @@ int ust_app_register(struct ust_register_msg *msg, int sock) lta = malloc(sizeof(struct ust_app)); if (lta == NULL) { - perror("malloc"); + PERROR("malloc"); return -ENOMEM; } @@ -201,7 +193,9 @@ int ust_app_register(struct ust_register_msg *msg, int sock) lta->name[16] = '\0'; hashtable_node_init(<a->node, (void *)((unsigned long)lta->key.pid), sizeof(void *)); - lta->channels = hashtable_new_str(0); + + /* Session hashtable */ + lta->sessions = hashtable_new(0); /* Set sock key map */ hashtable_node_init(<a->key.node, (void *)((unsigned long)lta->key.sock), @@ -286,3 +280,552 @@ void ust_app_ht_alloc(void) ust_app_ht = hashtable_new(0); ust_app_sock_key_map = hashtable_new(0); } + +/* + * Alloc new UST app session. + */ +static struct ust_app_session *alloc_app_session(void) +{ + struct ust_app_session *ua_sess; + + ua_sess = zmalloc(sizeof(struct ust_app_session)); + if (ua_sess == NULL) { + PERROR("malloc"); + goto error; + } + + ua_sess->enabled = 0; + ua_sess->handle = -1; + ua_sess->channels = hashtable_new_str(0); + ua_sess->metadata = NULL; + ua_sess->obj = NULL; + + return ua_sess; + +error: + return NULL; +} + +static struct ust_app_channel *alloc_app_channel(char *name) +{ + struct ust_app_channel *ua_chan; + + ua_chan = zmalloc(sizeof(struct ust_app_channel)); + if (ua_chan == NULL) { + PERROR("malloc"); + goto error; + } + + strncpy(ua_chan->name, name, sizeof(ua_chan->name)); + ua_chan->name[sizeof(ua_chan->name) - 1] = '\0'; + ua_chan->enabled = 0; + ua_chan->handle = -1; + ua_chan->obj = NULL; + ua_chan->ctx = hashtable_new(0); + ua_chan->streams = hashtable_new(0); + ua_chan->events = hashtable_new_str(0); + hashtable_node_init(&ua_chan->node, (void *) ua_chan->name, + strlen(ua_chan->name)); + + DBG3("UST app channel %s allocated", ua_chan->name); + + return ua_chan; + +error: + return NULL; +} + +static struct ust_app_event *alloc_app_event(char *name) +{ + struct ust_app_event *ua_event; + + ua_event = zmalloc(sizeof(struct ust_app_event)); + if (ua_event == NULL) { + PERROR("malloc"); + goto error; + } + + strncpy(ua_event->name, name, sizeof(ua_event->name)); + ua_event->name[sizeof(ua_event->name) - 1] = '\0'; + ua_event->ctx = hashtable_new(0); + hashtable_node_init(&ua_event->node, (void *) ua_event->name, + strlen(ua_event->name)); + + DBG3("UST app event %s allocated", ua_event->name); + + return ua_event; + +error: + return NULL; +} + +static void shallow_copy_event(struct ust_app_event *ua_event, + struct ltt_ust_event *uevent) +{ + strncpy(ua_event->name, uevent->attr.name, sizeof(ua_event->name)); + ua_event->name[sizeof(ua_event->name) - 1] = '\0'; + + /* TODO: support copy context */ +} + +static void shallow_copy_channel(struct ust_app_channel *ua_chan, + struct ltt_ust_channel *uchan) +{ + struct cds_lfht_iter iter; + struct cds_lfht_node *node, *ua_event_node; + struct ltt_ust_event *uevent; + struct ust_app_event *ua_event; + + DBG2("Shallow copy of UST app channel %s", ua_chan->name); + + strncpy(ua_chan->name, uchan->name, sizeof(ua_chan->name)); + ua_chan->name[sizeof(ua_chan->name) - 1] = '\0'; + + /* TODO: support copy context */ + + hashtable_get_first(uchan->events, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + uevent = caa_container_of(node, struct ltt_ust_event, node); + + ua_event_node = hashtable_lookup(ua_chan->events, + (void *) uevent->attr.name, strlen(uevent->attr.name), &iter); + if (ua_event_node == NULL) { + DBG2("UST event %s not found on shallow copy channel", + uevent->attr.name); + ua_event = alloc_app_event(uevent->attr.name); + if (ua_event == NULL) { + continue; + } + hashtable_add_unique(ua_chan->events, &ua_event->node); + } else { + ua_event = caa_container_of(node, struct ust_app_event, node); + } + + shallow_copy_event(ua_event, uevent); + + /* Get next UST events */ + hashtable_get_next(uchan->events, &iter); + } + + DBG3("Shallow copy channel done"); +} + +static void shallow_copy_session(struct ust_app_session *ua_sess, + struct ltt_ust_session *usess) +{ + struct cds_lfht_node *node, *ua_chan_node; + struct cds_lfht_iter iter; + struct ltt_ust_channel *uchan; + struct ust_app_channel *ua_chan; + + DBG2("Shallow copy of session handle"); + + ua_sess->uid = usess->uid; + + /* TODO: support all UST domain */ + + /* Iterate over all channels in global domain. */ + hashtable_get_first(usess->domain_global.channels, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + uchan = caa_container_of(node, struct ltt_ust_channel, node); + + ua_chan_node = hashtable_lookup(ua_sess->channels, + (void *) uchan->name, strlen(uchan->name), &iter); + if (ua_chan_node == NULL) { + DBG2("Channel %s not found on shallow session copy, creating it", + uchan->name); + ua_chan = alloc_app_channel(uchan->name); + if (ua_chan == NULL) { + /* malloc failed... continuing */ + continue; + } + hashtable_add_unique(ua_sess->channels, &ua_chan->node); + } else { + ua_chan = caa_container_of(node, struct ust_app_channel, node); + } + + shallow_copy_channel(ua_chan, uchan); + + /* Next item in hash table */ + hashtable_get_next(usess->domain_global.channels, &iter); + } +} + +static struct ust_app_session *lookup_session_by_app( + struct ltt_ust_session *usess, struct ust_app *app) +{ + struct cds_lfht_iter iter; + struct cds_lfht_node *node; + + /* Get right UST app session from app */ + node = hashtable_lookup(app->sessions, + (void *) ((unsigned long) usess->uid), + sizeof(void *), &iter); + if (node == NULL) { + goto error; + } + + return caa_container_of(node, struct ust_app_session, node); + +error: + return NULL; +} + +int ust_app_add_channel(struct ltt_ust_session *usess, + struct ltt_ust_channel *uchan) +{ + int ret = 0; + struct cds_lfht_iter iter; + struct cds_lfht_node *node, *ua_chan_node; + struct ust_app *app; + struct ust_app_session *ua_sess; + struct ust_app_channel *ua_chan; + + DBG2("UST app adding channel %s to global domain for session uid %d", + uchan->name, usess->uid); + + rcu_read_lock(); + hashtable_get_first(ust_app_ht, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + app = caa_container_of(node, struct ust_app, node); + + ua_sess = lookup_session_by_app(usess, app); + if (ua_sess == NULL) { + DBG2("UST app pid: %d session uid %d not found, creating one", + app->key.pid, usess->uid); + ua_sess = alloc_app_session(); + if (ua_sess == NULL) { + /* Only malloc can failed so something is really wrong */ + goto next; + } + shallow_copy_session(ua_sess, usess); + } + + if (ua_sess->handle == -1) { + ret = ustctl_create_session(app->key.sock); + if (ret < 0) { + DBG("Error creating session for app pid %d, sock %d", + app->key.pid, app->key.sock); + /* TODO: free() ua_sess */ + goto next; + } + + DBG2("UST app ustctl create session handle %d", ret); + ua_sess->handle = ret; + + /* Add ust app session to app's HT */ + hashtable_node_init(&ua_sess->node, + (void *)((unsigned long) ua_sess->uid), sizeof(void *)); + hashtable_add_unique(app->sessions, &ua_sess->node); + } + + /* Lookup channel in the ust app session */ + ua_chan_node = hashtable_lookup(ua_sess->channels, + (void *) uchan->name, strlen(uchan->name), &iter); + if (ua_chan_node == NULL) { + ERR("Channel suppose to be present with the above shallow " + "session copy. Continuing..."); + goto next; + } + + ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node); + + /* TODO: remove cast and use lttng-ust-abi.h */ + ret = ustctl_create_channel(app->key.sock, ua_sess->handle, + (struct lttng_ust_channel_attr *)&uchan->attr, &ua_chan->obj); + if (ret < 0) { + DBG("Error creating channel %s for app (pid: %d, sock: %d) " + "and session handle %d with ret %d", + uchan->name, app->key.pid, app->key.sock, + ua_sess->handle, ret); + goto next; + } + + ua_chan->handle = ua_chan->obj->handle; + ua_chan->attr.shm_fd = ua_chan->obj->shm_fd; + ua_chan->attr.wait_fd = ua_chan->obj->wait_fd; + ua_chan->attr.memory_map_size = ua_chan->obj->memory_map_size; + + DBG2("Channel %s UST create successfully for pid:%d and sock:%d", + uchan->name, app->key.pid, app->key.sock); + +next: + /* Next applications */ + hashtable_get_next(ust_app_ht, &iter); + } + rcu_read_unlock(); + + return ret; +} + +int ust_app_add_event(struct ltt_ust_session *usess, + struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent) +{ + int ret = 0; + struct cds_lfht_iter iter; + struct cds_lfht_node *node, *ua_chan_node, *ua_event_node; + struct ust_app *app; + struct ust_app_session *ua_sess; + struct ust_app_channel *ua_chan; + struct ust_app_event *ua_event; + struct lttng_ust_event ltt_uevent; + struct object_data *obj_event; + + DBG2("UST app adding event %s to global domain for session uid %d", + uevent->attr.name, usess->uid); + + rcu_read_lock(); + hashtable_get_first(ust_app_ht, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + app = caa_container_of(node, struct ust_app, node); + + ua_sess = lookup_session_by_app(usess, app); + if (ua_sess == NULL) { + DBG2("UST app (pid: %d, sock: %d) session not found, creating one", + app->key.pid, app->key.sock); + ua_sess = alloc_app_session(); + if (ua_sess == NULL) { + /* Only malloc can failed so something is really wrong */ + goto next; + } + shallow_copy_session(ua_sess, usess); + } + + if (ua_sess->handle == -1) { + ret = ustctl_create_session(app->key.sock); + if (ret < 0) { + DBG("Error creating session for app pid %d, sock %d", + app->key.pid, app->key.sock); + /* TODO: free() ua_sess */ + goto next; + } + + DBG2("UST app ustctl create session handle %d", ret); + ua_sess->handle = ret; + /* Add ust app session to app's HT */ + hashtable_node_init(&ua_sess->node, + (void *)((unsigned long) ua_sess->uid), sizeof(void *)); + hashtable_add_unique(app->sessions, &ua_sess->node); + } + + /* Lookup channel in the ust app session */ + ua_chan_node = hashtable_lookup(ua_sess->channels, + (void *) uchan->name, strlen(uchan->name), &iter); + if (ua_chan_node == NULL) { + ERR("Channel suppose to be present with the above shallow " + "session copy. Continuing..."); + goto next; + } + + ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node); + + /* Prepare lttng ust event */ + strncpy(ltt_uevent.name, uevent->attr.name, sizeof(ltt_uevent.name)); + ltt_uevent.name[sizeof(ltt_uevent.name) - 1] = '\0'; + /* TODO: adjust to other instrumentation types */ + ltt_uevent.instrumentation = LTTNG_UST_TRACEPOINT; + + /* Get event node */ + ua_event_node = hashtable_lookup(ua_chan->events, + (void *) uevent->attr.name, strlen(uevent->attr.name), &iter); + if (ua_event_node == NULL) { + DBG2("UST app event %s not found, creating one", uevent->attr.name); + /* Does not exist so create one */ + ua_event = alloc_app_event(uevent->attr.name); + if (ua_event == NULL) { + /* Only malloc can failed so something is really wrong */ + goto next; + } + + shallow_copy_event(ua_event, uevent); + + /* Create UST event on tracer */ + ret = ustctl_create_event(app->key.sock, <t_uevent, ua_chan->obj, + &obj_event); + if (ret < 0) { + ERR("Error ustctl create event %s for app pid: %d with ret %d", + uevent->attr.name, app->key.pid, ret); + /* TODO: free() ua_event and obj_event */ + goto next; + } + ua_event->obj = obj_event; + ua_event->handle = obj_event->handle; + ua_event->enabled = 1; + } else { + ua_event = caa_container_of(ua_event_node, + struct ust_app_event, node); + + if (ua_event->enabled == 0) { + ret = ustctl_enable(app->key.sock, ua_event->obj); + if (ret < 0) { + ERR("Error ustctl enable event %s for app " + "pid: %d with ret %d", uevent->attr.name, + app->key.pid, ret); + goto next; + } + ua_event->enabled = 1; + } + } + + hashtable_add_unique(ua_chan->events, &ua_event->node); + + DBG2("Event %s UST create successfully for pid:%d", uevent->attr.name, + app->key.pid); + +next: + /* Next applications */ + hashtable_get_next(ust_app_ht, &iter); + } + rcu_read_unlock(); + + return ret; +} + +int ust_app_start_trace(struct ltt_ust_session *usess) +{ + int ret = 0; + struct cds_lfht_iter iter; + struct cds_lfht_node *node, *ua_chan_node; + struct ust_app *app; + struct ust_app_session *ua_sess; + struct ust_app_channel *ua_chan; + struct lttng_ust_channel_attr uattr; + struct ltt_ust_channel *uchan; + + rcu_read_lock(); + hashtable_get_first(ust_app_ht, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + app = caa_container_of(node, struct ust_app, node); + + ua_sess = lookup_session_by_app(usess, app); + if (ua_sess == NULL) { + /* Only malloc can failed so something is really wrong */ + goto next; + } + + if (ua_sess->metadata == NULL) { + /* Allocate UST metadata */ + ua_sess->metadata = trace_ust_create_metadata(usess->pathname); + if (ua_sess->metadata == NULL) { + ERR("UST app session %d creating metadata failed", + ua_sess->handle); + goto next; + } + + uattr.overwrite = ua_sess->metadata->attr.overwrite; + uattr.subbuf_size = ua_sess->metadata->attr.subbuf_size; + uattr.num_subbuf = ua_sess->metadata->attr.num_subbuf; + uattr.switch_timer_interval = + ua_sess->metadata->attr.switch_timer_interval; + uattr.read_timer_interval = + ua_sess->metadata->attr.read_timer_interval; + uattr.output = ua_sess->metadata->attr.output; + + /* UST tracer metadata creation */ + ret = ustctl_open_metadata(app->key.sock, ua_sess->handle, &uattr, + &ua_sess->metadata->obj); + if (ret < 0) { + ERR("UST app open metadata failed for app pid:%d", + app->key.pid); + goto next; + } + + DBG2("UST metadata opened for app pid %d", app->key.pid); + } + + /* Open UST metadata stream */ + if (ua_sess->metadata->stream_obj == NULL) { + ret = ustctl_create_stream(app->key.sock, ua_sess->metadata->obj, + &ua_sess->metadata->stream_obj); + if (ret < 0) { + ERR("UST create metadata stream failed"); + goto next; + } + + ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, "%s/%s", + usess->pathname, "metadata"); + if (ret < 0) { + PERROR("asprintf UST create stream"); + goto next; + } + + DBG2("UST metadata stream object created for app pid %d", + app->key.pid); + } + + /* For each channel */ + hashtable_get_first(usess->domain_global.channels, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + uchan = caa_container_of(node, struct ltt_ust_channel, node); + + /* Lookup channel in the ust app session */ + ua_chan_node = hashtable_lookup(ua_sess->channels, + (void *) uchan->name, strlen(uchan->name), &iter); + if (ua_chan_node == NULL) { + ERR("Channel suppose to be present with the above shallow " + "session copy. Continuing..."); + goto next; + } + + ua_chan = caa_container_of(ua_chan_node, + struct ust_app_channel, node); + + struct ltt_ust_stream *ustream; + + ustream = malloc(sizeof(*ustream)); + if (ustream == NULL) { + goto next_chan; + } + + memset(ustream, 0, sizeof(struct ltt_ust_stream)); + + ret = ustctl_create_stream(app->key.sock, ua_chan->obj, + &ustream->obj); + if (ret < 0) { + ERR("Creating channel stream failed"); + goto next_chan; + } + + ustream->handle = ustream->obj->handle; + + hashtable_node_init(&ustream->node, + (void *)((unsigned long) ustream->handle), sizeof(void *)); + hashtable_add_unique(ua_chan->streams, &ustream->node); + + ret = snprintf(ustream->pathname, PATH_MAX, "%s/%s_%lu", + uchan->pathname, uchan->name, + hashtable_get_count(ua_chan->streams)); + if (ret < 0) { + PERROR("asprintf UST create stream"); + goto next_chan; + } + +next_chan: + /* Next applications */ + hashtable_get_next(ua_sess->channels, &iter); + } + + /* Setup UST consumer socket and send fds to it */ + printf("WTF HERE: sock: %d\n", usess->consumer_fd); + ret = ust_consumer_send_session(usess->consumer_fd, ua_sess); + if (ret < 0) { + goto next; + } + + /* This start the UST tracing */ + ret = ustctl_start_session(app->key.sock, ua_sess->handle); + if (ret < 0) { + ERR("Error starting tracing for app pid: %d", app->key.pid); + goto next; + } + + /* Quiescent wait after starting trace */ + ustctl_wait_quiescent(app->key.sock); +next: + /* Next applications */ + hashtable_get_next(ust_app_ht, &iter); + } + rcu_read_unlock(); + + return 0; +} diff --git a/ltt-sessiond/ust-app.h b/ltt-sessiond/ust-app.h index 91be50320..fe6ac8418 100644 --- a/ltt-sessiond/ust-app.h +++ b/ltt-sessiond/ust-app.h @@ -37,6 +37,9 @@ struct ust_register_msg { char name[16]; }; +/* + * Global applications HT used by the session daemon. + */ struct cds_lfht *ust_app_ht; struct cds_lfht *ust_app_sock_key_map; @@ -47,20 +50,49 @@ struct ust_app_key { struct cds_lfht_node node; }; +struct ust_app_event { + int enabled; + int handle; + struct object_data *obj; + char name[LTTNG_UST_SYM_NAME_LEN]; + struct cds_lfht *ctx; + struct cds_lfht_node node; +}; + +struct ust_app_channel { + int enabled; + int handle; + char name[LTTNG_UST_SYM_NAME_LEN]; + struct lttng_ust_channel attr; + struct object_data *obj; + struct cds_lfht *streams; + struct cds_lfht *ctx; + struct cds_lfht *events; + struct cds_lfht_node node; +}; + +struct ust_app_session { + int enabled; + int handle; /* Used has unique identifier */ + unsigned int uid; + struct ltt_ust_metadata *metadata; + struct object_data *obj; + struct cds_lfht *channels; /* Registered channels */ + struct cds_lfht_node node; +}; + /* * Registered traceable applications. Libust registers to the session daemon * and a linked list is kept of all running traceable app. */ struct ust_app { - //int sock; - //pid_t pid; pid_t ppid; uid_t uid; /* User ID that owns the apps */ gid_t gid; /* Group ID that owns the apps */ uint32_t v_major; /* Verion major number */ uint32_t v_minor; /* Verion minor number */ char name[17]; /* Process name (short) */ - struct cds_lfht *channels; + struct cds_lfht *sessions; struct cds_lfht_node node; struct ust_app_key key; }; @@ -69,7 +101,12 @@ struct ust_app { int ust_app_register(struct ust_register_msg *msg, int sock); void ust_app_unregister(int sock); +int ust_app_add_channel(struct ltt_ust_session *usess, + struct ltt_ust_channel *uchan); +int ust_app_add_event(struct ltt_ust_session *usess, + struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent); unsigned long ust_app_list_count(void); +int ust_app_start_trace(struct ltt_ust_session *usess); void ust_app_clean_list(void); void ust_app_ht_alloc(void); @@ -116,6 +153,13 @@ struct ust_app *ust_app_get_by_pid(pid_t pid) return NULL; } -#endif +static inline +int ust_app_add_channel(struct ltt_ust_session *usess, + struct ltt_ust_channel *uchan) +{ + return 0; +} + +#endif /* CONFIG_LTTNG_TOOLS_HAVE_UST */ #endif /* _LTT_UST_APP_H */ diff --git a/ltt-sessiond/ust-consumer.c b/ltt-sessiond/ust-consumer.c new file mode 100644 index 000000000..b3b97552e --- /dev/null +++ b/ltt-sessiond/ust-consumer.c @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2011 - David Goulet + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; only version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "hashtable.h" +#include "ust-consumer.h" + +/* + * Send all stream fds of UST channel to the consumer. + */ +static int send_channel_streams(int sock, + struct ust_app_channel *uchan) +{ + int ret, fds[2]; + struct ltt_ust_stream *stream; + struct lttcomm_consumer_msg lum; + struct cds_lfht_iter iter; + struct cds_lfht_node *node; + + DBG("Sending streams of channel %s to UST consumer", uchan->name); + + /* Send channel */ + lum.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL; + + /* + * We need to keep shm_fd open to make sure this key stays unique within + * the session daemon. + */ + lum.u.channel.channel_key = uchan->obj->shm_fd; + lum.u.channel.max_sb_size = uchan->attr.subbuf_size; + lum.u.channel.mmap_len = uchan->obj->memory_map_size; + DBG("Sending channel %d to consumer", lum.u.channel.channel_key); + ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum)); + if (ret < 0) { + perror("send consumer channel"); + goto error; + } + fds[0] = uchan->obj->shm_fd; + fds[1] = uchan->obj->wait_fd; + ret = lttcomm_send_fds_unix_sock(sock, fds, 2); + if (ret < 0) { + perror("send consumer channel ancillary data"); + goto error; + } + + + rcu_read_lock(); + hashtable_get_first(uchan->streams, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + stream = caa_container_of(node, struct ltt_ust_stream, node); + + int fds[2]; + + if (!stream->obj->shm_fd) { + goto next; + } + + lum.cmd_type = LTTNG_CONSUMER_ADD_STREAM; + lum.u.stream.channel_key = uchan->obj->shm_fd; + lum.u.stream.stream_key = stream->obj->shm_fd; + lum.u.stream.state = LTTNG_CONSUMER_ACTIVE_STREAM; + lum.u.stream.output = uchan->attr.output; + lum.u.stream.mmap_len = stream->obj->memory_map_size; + strncpy(lum.u.stream.path_name, stream->pathname, PATH_MAX - 1); + lum.u.stream.path_name[PATH_MAX - 1] = '\0'; + DBG("Sending stream %d to consumer", lum.u.stream.stream_key); + ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum)); + if (ret < 0) { + perror("send consumer stream"); + goto error; + } + + fds[0] = stream->obj->shm_fd; + fds[1] = stream->obj->wait_fd; + ret = lttcomm_send_fds_unix_sock(sock, fds, 2); + if (ret < 0) { + perror("send consumer stream ancillary data"); + goto error; + } + +next: + hashtable_get_next(uchan->streams, &iter); + } + rcu_read_unlock(); + + DBG("consumer channel streams sent"); + + return 0; + +error: + return ret; +} + +/* + * Send all stream fds of the UST session to the consumer. + */ +int ust_consumer_send_session(int consumer_fd, struct ust_app_session *usess) +{ + int ret = 0; + int sock = consumer_fd; + struct cds_lfht_iter iter; + struct cds_lfht_node *node; + struct lttcomm_consumer_msg lum; + struct ust_app_channel *uchan; + + DBG("Sending metadata stream fd"); + + if (usess->metadata->obj->shm_fd != 0) { + int fds[2]; + + /* Send metadata channel fd */ + lum.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL; + lum.u.channel.channel_key = usess->metadata->obj->shm_fd; + lum.u.channel.max_sb_size = usess->metadata->attr.subbuf_size; + lum.u.channel.mmap_len = 0; /* for kernel */ + DBG("Sending metadata channel %d to consumer", lum.u.stream.stream_key); + ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum)); + if (ret < 0) { + perror("send consumer channel"); + goto error; + } + fds[0] = usess->metadata->obj->shm_fd; + fds[1] = usess->metadata->obj->wait_fd; + ret = lttcomm_send_fds_unix_sock(sock, fds, 2); + if (ret < 0) { + perror("send consumer metadata channel"); + goto error; + } + + /* Send metadata stream fd */ + lum.cmd_type = LTTNG_CONSUMER_ADD_STREAM; + lum.u.stream.channel_key = usess->metadata->obj->shm_fd; + lum.u.stream.stream_key = usess->metadata->stream_obj->shm_fd; + lum.u.stream.state = LTTNG_CONSUMER_ACTIVE_STREAM; + lum.u.stream.output = DEFAULT_UST_CHANNEL_OUTPUT; + lum.u.stream.mmap_len = usess->metadata->stream_obj->memory_map_size; + strncpy(lum.u.stream.path_name, usess->metadata->pathname, PATH_MAX - 1); + lum.u.stream.path_name[PATH_MAX - 1] = '\0'; + DBG("Sending metadata stream %d to consumer", lum.u.stream.stream_key); + ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum)); + if (ret < 0) { + perror("send consumer metadata stream"); + goto error; + } + fds[0] = usess->metadata->stream_obj->shm_fd; + fds[1] = usess->metadata->stream_obj->wait_fd; + ret = lttcomm_send_fds_unix_sock(sock, fds, 2); + if (ret < 0) { + perror("send consumer stream"); + goto error; + } + } + + /* Send each channel fd streams of session */ + rcu_read_lock(); + hashtable_get_first(usess->channels, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + uchan = caa_container_of(node, struct ust_app_channel, node); + + ret = send_channel_streams(sock, uchan); + if (ret < 0) { + goto error; + } + hashtable_get_next(usess->channels, &iter); + } + rcu_read_unlock(); + + DBG("consumer fds (metadata and channel streams) sent"); + + return 0; + +error: + return ret; +} diff --git a/ltt-sessiond/ust-consumer.h b/ltt-sessiond/ust-consumer.h new file mode 100644 index 000000000..85169e6b8 --- /dev/null +++ b/ltt-sessiond/ust-consumer.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2011 - David Goulet + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; only version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _UST_CONSUMER_H +#define _UST_CONSUMER_H + +#include "ust-app.h" + +int ust_consumer_send_session(int consumer_fd, struct ust_app_session *usess); + +#endif /* _UST_CONSUMER_H */ diff --git a/ltt-sessiond/ust-ctl.h b/ltt-sessiond/ust-ctl.h index 0ceccff45..1fe29c877 100644 --- a/ltt-sessiond/ust-ctl.h +++ b/ltt-sessiond/ust-ctl.h @@ -1,33 +1,41 @@ /* + * ust-ctl.h + * + * Meta header used to include all relevant file from the lttng ust ABI. + * * Copyright (C) 2011 - David Goulet * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; only version 2 - * of the License. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; only version 2 of the License. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _LTT_UST_CTL_H #define _LTT_UST_CTL_H #include -#include - -#include "trace-ust.h" +/* + * FIXME: temporary workaround: we use a lttng-tools local version of + * lttng-ust-abi.h if UST is not found. Eventually, we should use our + * own internal structures within lttng-tools instead of relying on the + * UST ABI. + */ #ifdef CONFIG_LTTNG_TOOLS_HAVE_UST - +#include +#include #else - +#include "lttng-ust-ctl.h" +#include "lttng-ust-abi.h" #endif #endif /* _LTT_UST_CTL_H */ -- 2.34.1