From 55cc08a60ad1b188d59161842e630402e738e62e Mon Sep 17 00:00:00 2001 From: David Goulet Date: Wed, 30 Nov 2011 16:34:47 -0500 Subject: [PATCH] Support for UST context Adds the support to add context on channel and/or events for UST global domain. Signed-off-by: David Goulet --- lttng-sessiond/context.c | 259 ++++++++++----------------- lttng-sessiond/context.h | 4 +- lttng-sessiond/main.c | 17 +- lttng-sessiond/trace-ust.c | 30 +++- lttng-sessiond/trace-ust.h | 2 + lttng-sessiond/ust-app.c | 332 ++++++++++++++++++++++++++++++++--- lttng-sessiond/ust-app.h | 25 +++ lttng/commands/add_context.c | 57 +++--- 8 files changed, 499 insertions(+), 227 deletions(-) diff --git a/lttng-sessiond/context.c b/lttng-sessiond/context.c index c7c902197..d6f4d2f75 100644 --- a/lttng-sessiond/context.c +++ b/lttng-sessiond/context.c @@ -28,6 +28,7 @@ #include "context.h" #include "hashtable.h" #include "kernel.h" +#include "ust-app.h" /* * Add kernel context to an event of a specific channel. @@ -194,192 +195,124 @@ error: } /* - * UST support. - */ - -/* - * 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) -{ - int ret, found = 0; - struct ltt_ust_event *ustevent; - struct object_data *context_data; /* FIXME: currently a memleak */ - - DBG("Add UST context to event %s", event_name); - - 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); - if (ret < 0) { - goto error; - } - found = 1; - } - - ret = found; - -error: - return ret; -} -#endif - -/* - * Add UST context to all channel. - * - * If event_name is specified, add context to event instead. + * Add UST context to tracer. */ -static int add_ustctx_all_channels(struct ltt_ust_session *ustsession, - struct lttng_ust_context *ustctx, char *event_name, - struct cds_lfht *channels) +int context_ust_add(struct ltt_ust_session *usess, int domain, + struct lttng_event_context *ctx, char *event_name, + char *channel_name) { -#ifdef DISABLE - int ret, no_event = 0, found = 0; - struct ltt_ust_channel *ustchan; - struct object_data *context_data; /* FIXME: currently a memleak */ + int ret = LTTCOMM_OK, have_event = 0; + struct cds_lfht_iter iter, uiter; + struct cds_lfht *chan_ht; + struct ltt_ust_channel *uchan = NULL; + struct ltt_ust_event *uevent = NULL; + struct ltt_ust_context *uctx; - if (strlen(event_name) == 0) { - no_event = 1; - } - - DBG("Adding ust context to all channels (event: %s)", event_name); - - 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); - if (ret < 0) { - ret = LTTCOMM_UST_CONTEXT_FAIL; - goto error; - } - } else { - ret = add_ustctx_to_event(ustsession, ustctx, ustchan, event_name); - if (ret < 0) { - ret = LTTCOMM_UST_CONTEXT_FAIL; - goto error; - } else if (ret == 1) { - /* Event found and context added */ - found = 1; - break; - } - } - hashtable_get_next(channels, &iter); - } - if (!found && !no_event) { - ret = LTTCOMM_NO_EVENT; + switch (domain) { + case LTTNG_DOMAIN_UST: + chan_ht = usess->domain_global.channels; + break; + case LTTNG_DOMAIN_UST_EXEC_NAME: + case LTTNG_DOMAIN_UST_PID: + case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: + default: + ret = LTTCOMM_NOT_IMPLEMENTED; goto error; } - ret = LTTCOMM_OK; -error: - rcu_read_unlock(); - return ret; -#endif - return 0; -} - -/* - * Add UST context to a specific channel. - * - * If event_name is specified, add context to that event. - */ -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 */ - if (strlen(event_name) == 0) { - no_event = 1; + if (strlen(event_name) != 0) { + have_event = 1; } - DBG("Add UST context to channel '%s', event '%s'", - ustchan->name, event_name); - - if (no_event) { - //ret = ustctl_add_context(ustsession->sock, ustctx, - // ustchan->obj, &context_data); - if (ret < 0) { - ret = LTTCOMM_UST_CONTEXT_FAIL; + /* Get UST channel if defined */ + if (strlen(channel_name) != 0) { + uchan = trace_ust_find_channel_by_name(chan_ht, channel_name); + if (uchan == NULL) { + ret = LTTCOMM_UST_CHAN_NOT_FOUND; goto error; } - } else { - ret = add_ustctx_to_event(ustsession, ustctx, ustchan, event_name); - if (ret < 0) { - ret = LTTCOMM_UST_CONTEXT_FAIL; + } + + /* If UST channel specified and event name, get UST event ref */ + if (uchan && have_event) { + uevent = trace_ust_find_event_by_name(uchan->events, event_name); + if (uevent == NULL) { + ret = LTTCOMM_UST_EVENT_NOT_FOUND; goto error; - } else if (ret == 1) { - /* Event found and context added */ - found = 1; } } - if (!found && !no_event) { - ret = LTTCOMM_NO_EVENT; + /* Create ltt UST context */ + uctx = trace_ust_create_context(ctx); + if (uctx == NULL) { + ret = LTTCOMM_FATAL; goto error; } - ret = LTTCOMM_OK; - -error: - return ret; -#endif - return 0; -} - -/* - * Add UST context to tracer. - */ -int context_ust_add(struct ltt_ust_session *ustsession, - struct lttng_event_context *ctx, char *event_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, chan_ht); - if (ret != LTTCOMM_OK) { - goto error; + /* At this point, we have 4 possibilities */ + + if (uchan && uevent) { /* Add ctx to event in channel */ + ret = ust_app_add_ctx_event_glb(usess, uchan, uevent, uctx); + } else if (uchan && !have_event) { /* Add ctx to channel */ + ret = ust_app_add_ctx_channel_glb(usess, uchan, uctx); + } else if (!uchan && have_event) { /* Add ctx to event */ + cds_lfht_for_each_entry(chan_ht, &iter, uchan, node) { + uevent = trace_ust_find_event_by_name(uchan->events, event_name); + if (uevent != NULL) { + ret = ust_app_add_ctx_event_glb(usess, uchan, uevent, uctx); + /* + * LTTng UST does not allowed the same event to be registered + * multiple time in different or the same channel. So, if we + * found our event in the first place, no need to continue. + */ + goto end; + } } - } else { - /* Get UST channel */ - ustchan = trace_ust_find_channel_by_name(chan_ht, channel_name); - if (ustchan == NULL) { - ret = LTTCOMM_UST_CHAN_NOT_FOUND; - goto error; + ret = LTTCOMM_UST_EVENT_NOT_FOUND; + goto error_free_ctx; + } else if (!uchan && !have_event) { /* Add ctx to all events, all channels */ + cds_lfht_for_each_entry(chan_ht, &iter, uchan, node) { + ret = ust_app_add_ctx_channel_glb(usess, uchan, uctx); + if (ret < 0) { + /* Add failed so uctx was not added. We can keep it. */ + continue; + } + cds_lfht_for_each_entry(uchan->events, &uiter, uevent, node) { + ret = ust_app_add_ctx_event_glb(usess, uchan, uevent, uctx); + if (ret < 0) { + /* Add failed so uctx was not added. We can keep it. */ + continue; + } + /* Create ltt UST context */ + uctx = trace_ust_create_context(ctx); + if (uctx == NULL) { + ret = LTTCOMM_FATAL; + goto error; + } + } + /* Create ltt UST context */ + uctx = trace_ust_create_context(ctx); + if (uctx == NULL) { + ret = LTTCOMM_FATAL; + goto error; + } } + } - ret = add_ustctx_to_channel(ustsession, &ustctx, ustchan, event_name); - if (ret != LTTCOMM_OK) { - goto error; - } +end: + switch (ret) { + case -EEXIST: + ret = LTTCOMM_UST_CONTEXT_EXIST; + goto error_free_ctx; + case -ENOMEM: + ret = LTTCOMM_FATAL; + goto error_free_ctx; } - ret = LTTCOMM_OK; + return LTTCOMM_OK; +error_free_ctx: + free(uctx); error: return ret; } diff --git a/lttng-sessiond/context.h b/lttng-sessiond/context.h index 589b1e16e..4383f9abc 100644 --- a/lttng-sessiond/context.h +++ b/lttng-sessiond/context.h @@ -26,8 +26,8 @@ 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, +int context_ust_add(struct ltt_ust_session *usess, int domain, struct lttng_event_context *ctx, char *event_name, - char *channel_name, int domain); + char *channel_name); #endif /* _LTT_CONTEXT_H */ diff --git a/lttng-sessiond/main.c b/lttng-sessiond/main.c index ff096e1b9..56a12518e 100644 --- a/lttng-sessiond/main.c +++ b/lttng-sessiond/main.c @@ -2519,21 +2519,18 @@ static int cmd_add_context(struct ltt_session *session, int domain, break; case LTTNG_DOMAIN_UST: { - /* - struct ltt_ust_session *usess; + struct ltt_ust_session *usess = session->ust_session; - 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; - } + ret = context_ust_add(usess, domain, ctx, event_name, channel_name); + if (ret != LTTCOMM_OK) { + goto error; } break; - */ } + case LTTNG_DOMAIN_UST_EXEC_NAME: + case LTTNG_DOMAIN_UST_PID: + case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: default: - /* TODO: UST other domains */ ret = LTTCOMM_NOT_IMPLEMENTED; goto error; } diff --git a/lttng-sessiond/trace-ust.c b/lttng-sessiond/trace-ust.c index 20e3dc5f1..1a1304ac1 100644 --- a/lttng-sessiond/trace-ust.c +++ b/lttng-sessiond/trace-ust.c @@ -165,7 +165,7 @@ struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *chan, hashtable_node_init(&luc->node, (void *) luc->name, strlen(luc->name)); /* Alloc hash tables */ luc->events = hashtable_new_str(0); - luc->ctx = hashtable_new_str(0); + luc->ctx = hashtable_new(0); /* Set trace output path */ ret = snprintf(luc->pathname, PATH_MAX, "%s", path); @@ -225,7 +225,7 @@ struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev) hashtable_node_init(&lue->node, (void *) lue->attr.name, strlen(lue->attr.name)); /* Alloc context hash tables */ - lue->ctx = hashtable_new_str(0); + lue->ctx = hashtable_new(0); DBG2("Trace UST event %s created", lue->attr.name); @@ -277,6 +277,32 @@ error: return NULL; } +/* + * Allocate and initialize an UST context. + * + * Return pointer to structure or NULL. + */ +struct ltt_ust_context *trace_ust_create_context( + struct lttng_event_context *ctx) +{ + struct ltt_ust_context *uctx; + + uctx = zmalloc(sizeof(struct ltt_ust_context)); + if (uctx == NULL) { + PERROR("zmalloc ltt_ust_context"); + goto error; + } + + uctx->ctx.ctx = ctx->ctx; + hashtable_node_init(&uctx->node, (void *)((unsigned long) uctx->ctx.ctx), + sizeof(void *)); + + return uctx; + +error: + return NULL; +} + /* * RCU safe free context structure. */ diff --git a/lttng-sessiond/trace-ust.h b/lttng-sessiond/trace-ust.h index f0b639cba..18d3b5fc7 100644 --- a/lttng-sessiond/trace-ust.h +++ b/lttng-sessiond/trace-ust.h @@ -131,6 +131,8 @@ struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *attr, char *path); struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev); struct ltt_ust_metadata *trace_ust_create_metadata(char *path); +struct ltt_ust_context *trace_ust_create_context( + struct lttng_event_context *ctx); /* * Destroy functions free() the data structure and remove from linked list if diff --git a/lttng-sessiond/ust-app.c b/lttng-sessiond/ust-app.c index 1afb6d199..37dbfcb91 100644 --- a/lttng-sessiond/ust-app.c +++ b/lttng-sessiond/ust-app.c @@ -35,17 +35,37 @@ #include "ust-consumer.h" #include "ust-ctl.h" +/* + * Delete ust context safely. RCU read lock must be held before calling + * this function. + */ +static +void delete_ust_app_ctx(int sock, struct ust_app_ctx *ua_ctx) +{ + if (ua_ctx->obj) { + ustctl_release_object(sock, ua_ctx->obj); + free(ua_ctx->obj); + } + free(ua_ctx); +} + /* * Delete ust app event safely. RCU read lock must be held before calling * this function. */ static void delete_ust_app_event(int sock, struct ust_app_event *ua_event) { - /* TODO : remove context */ - //struct ust_app_ctx *ltctx; - //cds_lfht_for_each_entry(lte->ctx, &iter, ltctx, node) { - // delete_ust_app_ctx(sock, ltctx); - //} + int ret; + struct cds_lfht_iter iter; + struct ust_app_ctx *ua_ctx; + + cds_lfht_for_each_entry(ua_event->ctx, &iter, ua_ctx, node) { + ret = hashtable_del(ua_event->ctx, &iter); + assert(!ret); + delete_ust_app_ctx(sock, ua_ctx); + } + ret = hashtable_destroy(ua_event->ctx); + assert(!ret); if (ua_event->obj != NULL) { ustctl_release_object(sock, ua_event->obj); @@ -74,41 +94,38 @@ static void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan) int ret; struct cds_lfht_iter iter; struct ust_app_event *ua_event; + struct ust_app_ctx *ua_ctx; struct ltt_ust_stream *stream, *stmp; + /* Wipe stream */ cds_list_for_each_entry_safe(stream, stmp, &ua_chan->streams.head, list) { cds_list_del(&stream->list); delete_ust_app_stream(sock, stream); } - /* TODO : remove channel context */ - //cds_lfht_for_each_entry(ltc->ctx, &iter, ltctx, node) { - // ret = hashtable_del(ltc->ctx, &iter); - // assert(!ret); - // delete_ust_app_ctx(sock, ltctx); - //} - //ret = hashtable_destroy(ltc->ctx); + /* Wipe context */ + cds_lfht_for_each_entry(ua_chan->ctx, &iter, ua_ctx, node) { + ret = hashtable_del(ua_chan->ctx, &iter); + assert(!ret); + delete_ust_app_ctx(sock, ua_ctx); + } + ret = hashtable_destroy(ua_chan->ctx); + assert(!ret); + /* Wipe events */ cds_lfht_for_each_entry(ua_chan->events, &iter, ua_event, node) { ret = hashtable_del(ua_chan->events, &iter); assert(!ret); delete_ust_app_event(sock, ua_event); } - ret = hashtable_destroy(ua_chan->events); - if (ret < 0) { - ERR("UST app destroy session hashtable failed"); - goto error; - } + assert(!ret); if (ua_chan->obj != NULL) { ustctl_release_object(sock, ua_chan->obj); free(ua_chan->obj); } free(ua_chan); - -error: - return; } /* @@ -253,6 +270,52 @@ error: return NULL; } +/* + * Create the channel context on the tracer. + */ +static +int create_ust_channel_context(struct ust_app_channel *ua_chan, + struct ust_app_ctx *ua_ctx, struct ust_app *app) +{ + int ret; + + ret = ustctl_add_context(app->key.sock, &ua_ctx->ctx, + ua_chan->obj, &ua_ctx->obj); + if (ret < 0) { + goto error; + } + + ua_ctx->handle = ua_ctx->obj->handle; + + DBG2("UST app context added to channel %s successfully", ua_chan->name); + +error: + return ret; +} + +/* + * Create the event context on the tracer. + */ +static +int create_ust_event_context(struct ust_app_event *ua_event, + struct ust_app_ctx *ua_ctx, struct ust_app *app) +{ + int ret; + + ret = ustctl_add_context(app->key.sock, &ua_ctx->ctx, + ua_event->obj, &ua_ctx->obj); + if (ret < 0) { + goto error; + } + + ua_ctx->handle = ua_ctx->obj->handle; + + DBG2("UST app context added to event %s successfully", ua_event->name); + +error: + return ret; +} + /* * Disable the specified event on to UST tracer for the UST session. */ @@ -570,19 +633,54 @@ error: return NULL; } +/* + * Alloc new UST app context. + */ +static +struct ust_app_ctx *alloc_ust_app_ctx(struct lttng_ust_context *uctx) +{ + struct ust_app_ctx *ua_ctx; + + ua_ctx = zmalloc(sizeof(struct ust_app_ctx)); + if (ua_ctx == NULL) { + goto error; + } + + if (uctx) { + memcpy(&ua_ctx->ctx, uctx, sizeof(ua_ctx->ctx)); + } + + DBG3("UST app context %d allocated", ua_ctx->ctx.ctx); + +error: + return ua_ctx; +} + /* * Copy data between an UST app event and a LTT event. */ static void shadow_copy_event(struct ust_app_event *ua_event, struct ltt_ust_event *uevent) { + struct cds_lfht_iter iter; + struct ltt_ust_context *uctx; + struct ust_app_ctx *ua_ctx; + strncpy(ua_event->name, uevent->attr.name, sizeof(ua_event->name)); ua_event->name[sizeof(ua_event->name) - 1] = '\0'; /* Copy event attributes */ memcpy(&ua_event->attr, &uevent->attr, sizeof(ua_event->attr)); - /* TODO: support copy context */ + cds_lfht_for_each_entry(uevent->ctx, &iter, uctx, node) { + ua_ctx = alloc_ust_app_ctx(&uctx->ctx); + if (ua_ctx == NULL) { + continue; + } + hashtable_node_init(&ua_ctx->node, + (void *)((unsigned long) ua_ctx->ctx.ctx), sizeof(void *)); + hashtable_add_unique(ua_event->ctx, &ua_ctx->node); + } } /* @@ -594,7 +692,9 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan, struct cds_lfht_iter iter; struct cds_lfht_node *ua_event_node; struct ltt_ust_event *uevent; + struct ltt_ust_context *uctx; struct ust_app_event *ua_event; + struct ust_app_ctx *ua_ctx; DBG2("Shadow copy of UST app channel %s", ua_chan->name); @@ -603,7 +703,15 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan, /* Copy event attributes */ memcpy(&ua_chan->attr, &uchan->attr, sizeof(ua_chan->attr)); - /* TODO: support copy context */ + cds_lfht_for_each_entry(uchan->ctx, &iter, uctx, node) { + ua_ctx = alloc_ust_app_ctx(&uctx->ctx); + if (ua_ctx == NULL) { + continue; + } + hashtable_node_init(&ua_ctx->node, + (void *)((unsigned long) ua_ctx->ctx.ctx), sizeof(void *)); + hashtable_add_unique(ua_chan->ctx, &ua_ctx->node); + } /* Copy all events from ltt ust channel to ust app channel */ cds_lfht_for_each_entry(uchan->events, &iter, uevent, node) { @@ -774,6 +882,90 @@ error: return NULL; } +/* + * Create a context for the channel on the tracer. + */ +static +int create_ust_app_channel_context(struct ust_app_session *ua_sess, + struct ust_app_channel *ua_chan, struct lttng_ust_context *uctx, + struct ust_app *app) +{ + int ret = 0; + struct cds_lfht_iter iter; + struct cds_lfht_node *node; + struct ust_app_ctx *ua_ctx; + + DBG2("UST app adding context to channel %s", ua_chan->name); + + node = hashtable_lookup(ua_chan->ctx, (void *)((unsigned long)uctx->ctx), + sizeof(void *), &iter); + if (node != NULL) { + ret = -EEXIST; + goto error; + } + + ua_ctx = alloc_ust_app_ctx(uctx); + if (ua_ctx == NULL) { + /* malloc failed */ + ret = -1; + goto error; + } + + hashtable_node_init(&ua_ctx->node, + (void *)((unsigned long) ua_ctx->ctx.ctx), sizeof(void *)); + hashtable_add_unique(ua_chan->ctx, &ua_ctx->node); + + ret = create_ust_channel_context(ua_chan, ua_ctx, app); + if (ret < 0) { + goto error; + } + +error: + return ret; +} + +/* + * Create an UST context and enable it for the event on the tracer. + */ +static +int create_ust_app_event_context(struct ust_app_session *ua_sess, + struct ust_app_event *ua_event, struct lttng_ust_context *uctx, + struct ust_app *app) +{ + int ret = 0; + struct cds_lfht_iter iter; + struct cds_lfht_node *node; + struct ust_app_ctx *ua_ctx; + + DBG2("UST app adding context to event %s", ua_event->name); + + node = hashtable_lookup(ua_event->ctx, (void *)((unsigned long)uctx->ctx), + sizeof(void *), &iter); + if (node != NULL) { + ret = -EEXIST; + goto error; + } + + ua_ctx = alloc_ust_app_ctx(uctx); + if (ua_ctx == NULL) { + /* malloc failed */ + ret = -1; + goto error; + } + + hashtable_node_init(&ua_ctx->node, + (void *)((unsigned long) ua_ctx->ctx.ctx), sizeof(void *)); + hashtable_add_unique(ua_event->ctx, &ua_ctx->node); + + ret = create_ust_event_context(ua_event, ua_ctx, app); + if (ret < 0) { + goto error; + } + +error: + return ret; +} + /* * Enable on the tracer side a ust app event for the session and channel. */ @@ -1953,3 +2145,99 @@ error: rcu_read_unlock(); return; } + +/* + * Add context to a specific channel for global UST domain. + */ +int ust_app_add_ctx_channel_glb(struct ltt_ust_session *usess, + struct ltt_ust_channel *uchan, struct ltt_ust_context *uctx) +{ + int ret = 0; + struct cds_lfht_node *ua_chan_node; + struct cds_lfht_iter iter, uiter; + struct ust_app_channel *ua_chan = NULL; + struct ust_app_session *ua_sess; + struct ust_app *app; + + rcu_read_lock(); + + cds_lfht_for_each_entry(ust_app_ht, &iter, app, node) { + ua_sess = lookup_session_by_app(usess, app); + if (ua_sess == NULL) { + continue; + } + + /* Lookup channel in the ust app session */ + ua_chan_node = hashtable_lookup(ua_sess->channels, + (void *)uchan->name, strlen(uchan->name), &uiter); + if (ua_chan_node == NULL) { + continue; + } + ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, + node); + + ret = create_ust_app_channel_context(ua_sess, ua_chan, &uctx->ctx, app); + if (ret < 0) { + continue; + } + } + + /* Add ltt UST context node to ltt UST channel */ + hashtable_add_unique(uchan->ctx, &uctx->node); + + rcu_read_unlock(); + return ret; +} + +/* + * Add context to a specific event in a channel for global UST domain. + */ +int ust_app_add_ctx_event_glb(struct ltt_ust_session *usess, + struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent, + struct ltt_ust_context *uctx) +{ + int ret = 0; + struct cds_lfht_node *ua_chan_node, *ua_event_node; + struct cds_lfht_iter iter, uiter; + struct ust_app_session *ua_sess; + struct ust_app_event *ua_event; + struct ust_app_channel *ua_chan = NULL; + struct ust_app *app; + + rcu_read_lock(); + + cds_lfht_for_each_entry(ust_app_ht, &iter, app, node) { + ua_sess = lookup_session_by_app(usess, app); + if (ua_sess == NULL) { + continue; + } + + /* Lookup channel in the ust app session */ + ua_chan_node = hashtable_lookup(ua_sess->channels, + (void *)uchan->name, strlen(uchan->name), &uiter); + if (ua_chan_node == NULL) { + continue; + } + ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, + node); + + ua_event_node = hashtable_lookup(ua_chan->events, + (void *)uevent->attr.name, strlen(uevent->attr.name), &uiter); + if (ua_event_node == NULL) { + continue; + } + ua_event = caa_container_of(ua_event_node, struct ust_app_event, + node); + + ret = create_ust_app_event_context(ua_sess, ua_event, &uctx->ctx, app); + if (ret < 0) { + continue; + } + } + + /* Add ltt UST context node to ltt UST event */ + hashtable_add_unique(uevent->ctx, &uctx->node); + + rcu_read_unlock(); + return ret; +} diff --git a/lttng-sessiond/ust-app.h b/lttng-sessiond/ust-app.h index 8a0130f07..1dc0e8ba2 100644 --- a/lttng-sessiond/ust-app.h +++ b/lttng-sessiond/ust-app.h @@ -55,6 +55,13 @@ struct ust_app_key { struct cds_lfht_node node; }; +struct ust_app_ctx { + int handle; + struct lttng_ust_context ctx; + struct lttng_ust_object_data *obj; + struct cds_lfht_node node; +}; + struct ust_app_event { int enabled; int handle; @@ -134,6 +141,11 @@ int ust_app_enable_all_event_glb(struct ltt_ust_session *usess, struct ltt_ust_channel *uchan); int ust_app_disable_event_glb(struct ltt_ust_session *usess, struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent); +int ust_app_add_ctx_event_glb(struct ltt_ust_session *usess, + struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent, + struct ltt_ust_context *uctx); +int ust_app_add_ctx_channel_glb(struct ltt_ust_session *usess, + struct ltt_ust_channel *uchan, struct ltt_ust_context *uctx); void ust_app_global_update(struct ltt_ust_session *usess, int sock); void ust_app_clean_list(void); @@ -263,6 +275,19 @@ int ust_app_enable_event_glb(struct ltt_ust_session *usess, { return 0; } +static inline +int ust_app_add_ctx_event_glb(struct ltt_ust_session *usess, + struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent, + struct ltt_ust_context *uctx) +{ + return 0; +} +static inline +int ust_app_add_ctx_channel_glb(struct ltt_ust_session *usess, + struct ltt_ust_channel *uchan, struct ltt_ust_context *uctx) +{ + return 0; +} #endif /* HAVE_LIBLTTNG_UST_CTL */ diff --git a/lttng/commands/add_context.c b/lttng/commands/add_context.c index 44c4d4815..5986195b4 100644 --- a/lttng/commands/add_context.c +++ b/lttng/commands/add_context.c @@ -37,7 +37,7 @@ static char *opt_event_name; static char *opt_channel_name; static char *opt_session_name; -static int *opt_kernel; +static int opt_kernel; static int opt_pid_all; static int opt_userspace; static char *opt_cmd_name; @@ -141,7 +141,7 @@ static struct poptOption long_options[] = { {"channel", 'c', POPT_ARG_STRING, &opt_channel_name, 0, 0, 0}, {"event", 'e', POPT_ARG_STRING, &opt_event_name, 0, 0, 0}, {"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0}, - {"userspace", 'u', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, 0, OPT_USERSPACE, 0, 0}, + {"userspace", 'u', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_cmd_name, OPT_USERSPACE, 0, 0}, {"all", 0, POPT_ARG_VAL, &opt_pid_all, 1, 0, 0}, {"pid", 'p', POPT_ARG_INT, &opt_pid, 0, 0, 0}, {"type", 't', POPT_ARG_STRING, &opt_type, OPT_TYPE, 0, 0}, @@ -297,10 +297,9 @@ static void usage(FILE *ofp) { fprintf(ofp, "usage: lttng add-context -t TYPE\n"); fprintf(ofp, "\n"); - fprintf(ofp, "If no event name is given (-e), the context will be added to\n"); - fprintf(ofp, "all events in the channel.\n"); + fprintf(ofp, "If no event name is given (-e), the context will be added to the channel\n"); fprintf(ofp, "If no channel and no event is given (-c/-e), the context\n"); - fprintf(ofp, "will be added to all events in all channels.\n"); + fprintf(ofp, "will be added to all events and all channels.\n"); fprintf(ofp, "\n"); fprintf(ofp, "Options:\n"); fprintf(ofp, " -h, --help Show this help\n"); @@ -308,7 +307,7 @@ static void usage(FILE *ofp) fprintf(ofp, " -c, --channel NAME Apply on channel\n"); fprintf(ofp, " -e, --event NAME Apply on event\n"); fprintf(ofp, " -k, --kernel Apply for the kernel tracer\n"); - fprintf(ofp, " -u, --userspace Apply for the user-space tracer\n"); + fprintf(ofp, " -u, --userspace [CMD] Apply for the user-space tracer\n"); fprintf(ofp, " --all If -u, apply on all traceable apps\n"); fprintf(ofp, " -p, --pid PID If -u, apply on a specific PID\n"); fprintf(ofp, " -t, --type TYPE Context type. You can repeat that option on\n"); @@ -356,6 +355,19 @@ static int add_context(char *session_name) if (opt_kernel) { dom.type = LTTNG_DOMAIN_KERNEL; + } else if (opt_pid != 0) { + dom.type = LTTNG_DOMAIN_UST_PID; + dom.attr.pid = opt_pid; + DBG("PID %d set to lttng handle", opt_pid); + } else if (opt_userspace && opt_cmd_name == NULL) { + dom.type = LTTNG_DOMAIN_UST; + } else if (opt_userspace && opt_cmd_name != NULL) { + dom.type = LTTNG_DOMAIN_UST_EXEC_NAME; + strncpy(dom.attr.exec_name, opt_cmd_name, NAME_MAX); + } else { + ERR("Please specify a tracer (--kernel or --userspace)"); + ret = CMD_NOT_IMPLEMENTED; + goto error; } handle = lttng_create_handle(session_name, &dom); @@ -366,7 +378,6 @@ static int add_context(char *session_name) /* Iterate over all context type given */ cds_list_for_each_entry(type, &ctx_type_list.head, list) { - context.ctx = type->opt->ctx_type; if (context.ctx == LTTNG_EVENT_CONTEXT_PERF_COUNTER) { context.u.perf_counter.type = type->opt->u.perf.type; @@ -380,28 +391,18 @@ static int add_context(char *session_name) *ptr = '_'; } } - if (opt_kernel) { - DBG("Adding kernel context"); - ret = lttng_add_context(handle, &context, opt_event_name, - opt_channel_name); - if (ret < 0) { - fprintf(stderr, "%s: ", type->opt->symbol); - continue; - } else { - MSG("Kernel context %s added", type->opt->symbol); - } - } else if (opt_userspace) { /* User-space tracer action */ - /* - * TODO: Waiting on lttng UST 2.0 - */ - if (opt_pid_all) { - } else if (opt_pid != 0) { - } - ret = CMD_NOT_IMPLEMENTED; - goto error; + DBG("Adding context..."); + + ret = lttng_add_context(handle, &context, opt_event_name, + opt_channel_name); + if (ret < 0) { + fprintf(stderr, "%s: ", type->opt->symbol); + continue; } else { - ERR("Please specify a tracer (--kernel or --userspace)"); - goto error; + MSG("%s context %s added to %s event in %s", + opt_kernel ? "kernel" : "UST", type->opt->symbol, + opt_event_name ? opt_event_name : "all", + opt_channel_name ? opt_channel_name : "all channels"); } } -- 2.34.1