X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Ftrace-ust.c;h=a6c0c04ad864075d64cbf0c8dba6b66e96ce21cc;hp=178c7d04eb9f6f3ede96c59bdd82616975820168;hb=a5a309207b81778262744a9de568f6d7c54996e2;hpb=890d8fe47755c3bad936389cf48ffa141cff41c9 diff --git a/src/bin/lttng-sessiond/trace-ust.c b/src/bin/lttng-sessiond/trace-ust.c index 178c7d04e..a6c0c04ad 100644 --- a/src/bin/lttng-sessiond/trace-ust.c +++ b/src/bin/lttng-sessiond/trace-ust.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 - David Goulet + * Copyright (C) 2016 - Jérémie Galarneau * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2 only, @@ -24,6 +25,7 @@ #include #include +#include #include "buffer-registry.h" #include "trace-ust.h" @@ -116,12 +118,46 @@ int trace_ust_ht_match_event(struct cds_lfht_node *node, const void *_key) } if (key->exclusion && event->exclusion) { - /* Both exclusions exist; check count followed by names. */ - if (event->exclusion->count != key->exclusion->count || - memcmp(event->exclusion->names, key->exclusion->names, - event->exclusion->count * LTTNG_SYMBOL_NAME_LEN) != 0) { + size_t i; + + /* Check exclusion counts first. */ + if (event->exclusion->count != key->exclusion->count) { goto no_match; } + + /* Compare names individually. */ + for (i = 0; i < event->exclusion->count; ++i) { + size_t j; + bool found = false; + const char *name_ev = + LTTNG_EVENT_EXCLUSION_NAME_AT( + event->exclusion, i); + + /* + * Compare this exclusion name to all the key's + * exclusion names. + */ + for (j = 0; j < key->exclusion->count; ++j) { + const char *name_key = + LTTNG_EVENT_EXCLUSION_NAME_AT( + key->exclusion, j); + + if (!strncmp(name_ev, name_key, + LTTNG_SYMBOL_NAME_LEN)) { + /* Names match! */ + found = true; + break; + } + } + + /* + * If the current exclusion name was not found amongst + * the key's exclusion names, then there's no match. + */ + if (!found) { + goto no_match; + } + } } /* Match. */ return 1; @@ -135,7 +171,7 @@ no_match: * lock MUST be acquired before calling this. */ struct ltt_ust_channel *trace_ust_find_channel_by_name(struct lttng_ht *ht, - char *name) + const char *name) { struct lttng_ht_node_str *node; struct lttng_ht_iter iter; @@ -321,6 +357,10 @@ struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *chan, luc->attr.switch_timer_interval = chan->attr.switch_timer_interval; luc->attr.read_timer_interval = chan->attr.read_timer_interval; luc->attr.output = (enum lttng_ust_output) chan->attr.output; + luc->monitor_timer_interval = ((struct lttng_channel_extended *) + chan->attr.extended.ptr)->monitor_timer_interval; + luc->attr.u.s.blocking_timeout = ((struct lttng_channel_extended *) + chan->attr.extended.ptr)->blocking_timeout; /* Translate to UST output enum */ switch (luc->attr.output) { @@ -359,95 +399,141 @@ error: return luc; } +/* + * Validates an exclusion list. + * + * Returns 0 if valid, negative value if invalid. + */ +static int validate_exclusion(struct lttng_event_exclusion *exclusion) +{ + size_t i; + int ret = 0; + + assert(exclusion); + + for (i = 0; i < exclusion->count; ++i) { + size_t j; + const char *name_a = + LTTNG_EVENT_EXCLUSION_NAME_AT(exclusion, i); + + for (j = 0; j < i; ++j) { + const char *name_b = + LTTNG_EVENT_EXCLUSION_NAME_AT(exclusion, j); + + if (!strncmp(name_a, name_b, LTTNG_SYMBOL_NAME_LEN)) { + /* Match! */ + ret = -1; + goto end; + } + } + } + +end: + return ret; +} + /* * Allocate and initialize a ust event. Set name and event type. * We own filter_expression, filter, and exclusion. * - * Return pointer to structure or NULL. + * Return an lttng_error_code */ -struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev, +enum lttng_error_code trace_ust_create_event(struct lttng_event *ev, char *filter_expression, struct lttng_filter_bytecode *filter, struct lttng_event_exclusion *exclusion, - bool internal_event) + bool internal_event, + struct ltt_ust_event **ust_event) { - struct ltt_ust_event *lue; + struct ltt_ust_event *local_ust_event; + enum lttng_error_code ret = LTTNG_OK; assert(ev); - lue = zmalloc(sizeof(struct ltt_ust_event)); - if (lue == NULL) { + if (exclusion && validate_exclusion(exclusion)) { + ret = LTTNG_ERR_INVALID; + goto error; + } + + local_ust_event = zmalloc(sizeof(struct ltt_ust_event)); + if (local_ust_event == NULL) { PERROR("ust event zmalloc"); + ret = LTTNG_ERR_NOMEM; goto error; } - lue->internal = internal_event; + local_ust_event->internal = internal_event; switch (ev->type) { case LTTNG_EVENT_PROBE: - lue->attr.instrumentation = LTTNG_UST_PROBE; + local_ust_event->attr.instrumentation = LTTNG_UST_PROBE; break; case LTTNG_EVENT_FUNCTION: - lue->attr.instrumentation = LTTNG_UST_FUNCTION; + local_ust_event->attr.instrumentation = LTTNG_UST_FUNCTION; break; case LTTNG_EVENT_FUNCTION_ENTRY: - lue->attr.instrumentation = LTTNG_UST_FUNCTION; + local_ust_event->attr.instrumentation = LTTNG_UST_FUNCTION; break; case LTTNG_EVENT_TRACEPOINT: - lue->attr.instrumentation = LTTNG_UST_TRACEPOINT; + local_ust_event->attr.instrumentation = LTTNG_UST_TRACEPOINT; break; default: ERR("Unknown ust instrumentation type (%d)", ev->type); + ret = LTTNG_ERR_INVALID; goto error_free_event; } /* Copy event name */ - strncpy(lue->attr.name, ev->name, LTTNG_UST_SYM_NAME_LEN); - lue->attr.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; + strncpy(local_ust_event->attr.name, ev->name, LTTNG_UST_SYM_NAME_LEN); + local_ust_event->attr.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; switch (ev->loglevel_type) { case LTTNG_EVENT_LOGLEVEL_ALL: - lue->attr.loglevel_type = LTTNG_UST_LOGLEVEL_ALL; - lue->attr.loglevel = -1; /* Force to -1 */ + local_ust_event->attr.loglevel_type = LTTNG_UST_LOGLEVEL_ALL; + local_ust_event->attr.loglevel = -1; /* Force to -1 */ break; case LTTNG_EVENT_LOGLEVEL_RANGE: - lue->attr.loglevel_type = LTTNG_UST_LOGLEVEL_RANGE; - lue->attr.loglevel = ev->loglevel; + local_ust_event->attr.loglevel_type = LTTNG_UST_LOGLEVEL_RANGE; + local_ust_event->attr.loglevel = ev->loglevel; break; case LTTNG_EVENT_LOGLEVEL_SINGLE: - lue->attr.loglevel_type = LTTNG_UST_LOGLEVEL_SINGLE; - lue->attr.loglevel = ev->loglevel; + local_ust_event->attr.loglevel_type = LTTNG_UST_LOGLEVEL_SINGLE; + local_ust_event->attr.loglevel = ev->loglevel; break; default: ERR("Unknown ust loglevel type (%d)", ev->loglevel_type); + ret = LTTNG_ERR_INVALID; goto error_free_event; } /* Same layout. */ - lue->filter_expression = filter_expression; - lue->filter = filter; - lue->exclusion = exclusion; + local_ust_event->filter_expression = filter_expression; + local_ust_event->filter = filter; + local_ust_event->exclusion = exclusion; /* Init node */ - lttng_ht_node_init_str(&lue->node, lue->attr.name); + lttng_ht_node_init_str(&local_ust_event->node, local_ust_event->attr.name); DBG2("Trace UST event %s, loglevel (%d,%d) created", - lue->attr.name, lue->attr.loglevel_type, - lue->attr.loglevel); + local_ust_event->attr.name, local_ust_event->attr.loglevel_type, + local_ust_event->attr.loglevel); + + *ust_event = local_ust_event; - return lue; + return ret; error_free_event: - free(lue); + free(local_ust_event); error: free(filter_expression); free(filter); free(exclusion); - return NULL; + return ret; } static -int trace_ust_context_type_event_to_ust(enum lttng_event_context_type type) +int trace_ust_context_type_event_to_ust( + enum lttng_event_context_type type) { int utype; @@ -475,8 +561,49 @@ int trace_ust_context_type_event_to_ust(enum lttng_event_context_type type) utype = LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER; } break; + case LTTNG_EVENT_CONTEXT_APP_CONTEXT: + utype = LTTNG_UST_CONTEXT_APP_CONTEXT; + break; + case LTTNG_EVENT_CONTEXT_CGROUP_NS: + utype = LTTNG_UST_CONTEXT_CGROUP_NS; + break; + case LTTNG_EVENT_CONTEXT_IPC_NS: + utype = LTTNG_UST_CONTEXT_IPC_NS; + break; + case LTTNG_EVENT_CONTEXT_MNT_NS: + utype = LTTNG_UST_CONTEXT_MNT_NS; + break; + case LTTNG_EVENT_CONTEXT_NET_NS: + utype = LTTNG_UST_CONTEXT_NET_NS; + break; + case LTTNG_EVENT_CONTEXT_PID_NS: + utype = LTTNG_UST_CONTEXT_PID_NS; + break; + case LTTNG_EVENT_CONTEXT_USER_NS: + utype = LTTNG_UST_CONTEXT_USER_NS; + break; + case LTTNG_EVENT_CONTEXT_UTS_NS: + utype = LTTNG_UST_CONTEXT_UTS_NS; + break; + case LTTNG_EVENT_CONTEXT_VUID: + utype = LTTNG_UST_CONTEXT_VUID; + break; + case LTTNG_EVENT_CONTEXT_VEUID: + utype = LTTNG_UST_CONTEXT_VEUID; + break; + case LTTNG_EVENT_CONTEXT_VSUID: + utype = LTTNG_UST_CONTEXT_VSUID; + break; + case LTTNG_EVENT_CONTEXT_VGID: + utype = LTTNG_UST_CONTEXT_VGID; + break; + case LTTNG_EVENT_CONTEXT_VEGID: + utype = LTTNG_UST_CONTEXT_VEGID; + break; + case LTTNG_EVENT_CONTEXT_VSGID: + utype = LTTNG_UST_CONTEXT_VSGID; + break; default: - ERR("Invalid UST context"); utype = -1; break; } @@ -486,8 +613,8 @@ int trace_ust_context_type_event_to_ust(enum lttng_event_context_type type) /* * Return 1 if contexts match, 0 otherwise. */ -int trace_ust_match_context(struct ltt_ust_context *uctx, - struct lttng_event_context *ctx) +int trace_ust_match_context(const struct ltt_ust_context *uctx, + const struct lttng_event_context *ctx) { int utype; @@ -514,6 +641,15 @@ int trace_ust_match_context(struct ltt_ust_context *uctx, return 0; } break; + case LTTNG_UST_CONTEXT_APP_CONTEXT: + assert(uctx->ctx.u.app_ctx.provider_name); + assert(uctx->ctx.u.app_ctx.ctx_name); + if (strcmp(uctx->ctx.u.app_ctx.provider_name, + ctx->u.app_ctx.provider_name) || + strcmp(uctx->ctx.u.app_ctx.ctx_name, + ctx->u.app_ctx.ctx_name)) { + return 0; + } default: break; @@ -527,22 +663,23 @@ int trace_ust_match_context(struct ltt_ust_context *uctx, * Return pointer to structure or NULL. */ struct ltt_ust_context *trace_ust_create_context( - struct lttng_event_context *ctx) + const struct lttng_event_context *ctx) { - struct ltt_ust_context *uctx; + struct ltt_ust_context *uctx = NULL; int utype; assert(ctx); utype = trace_ust_context_type_event_to_ust(ctx->ctx); if (utype < 0) { - return NULL; + ERR("Invalid UST context"); + goto end; } uctx = zmalloc(sizeof(struct ltt_ust_context)); - if (uctx == NULL) { + if (!uctx) { PERROR("zmalloc ltt_ust_context"); - goto error; + goto end; } uctx->ctx.ctx = (enum lttng_ust_context_type) utype; @@ -554,14 +691,31 @@ struct ltt_ust_context *trace_ust_create_context( LTTNG_UST_SYM_NAME_LEN); uctx->ctx.u.perf_counter.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; break; + case LTTNG_UST_CONTEXT_APP_CONTEXT: + { + char *provider_name = NULL, *ctx_name = NULL; + + provider_name = strdup(ctx->u.app_ctx.provider_name); + if (!provider_name) { + goto error; + } + uctx->ctx.u.app_ctx.provider_name = provider_name; + + ctx_name = strdup(ctx->u.app_ctx.ctx_name); + if (!ctx_name) { + goto error; + } + uctx->ctx.u.app_ctx.ctx_name = ctx_name; + break; + } default: break; } lttng_ht_node_init_ulong(&uctx->node, (unsigned long) uctx->ctx.ctx); - +end: return uctx; - error: + trace_ust_destroy_context(uctx); return NULL; } @@ -713,13 +867,14 @@ int trace_ust_pid_tracker_lookup(struct ltt_ust_session *session, int pid) int trace_ust_track_pid(struct ltt_ust_session *session, int pid) { int retval = LTTNG_OK; + bool should_update_apps = false; if (pid == -1) { /* Track all pids: destroy tracker if exists. */ if (session->pid_tracker.ht) { fini_pid_tracker(&session->pid_tracker); /* Ensure all apps have session. */ - ust_app_global_update_all(session); + should_update_apps = true; } } else { int ret; @@ -738,7 +893,7 @@ int trace_ust_track_pid(struct ltt_ust_session *session, int pid) goto end; } /* Remove all apps from session except pid. */ - ust_app_global_update_all(session); + should_update_apps = true; } else { struct ust_app *app; @@ -750,10 +905,13 @@ int trace_ust_track_pid(struct ltt_ust_session *session, int pid) /* Add session to application */ app = ust_app_find_by_pid(pid); if (app) { - ust_app_global_update(session, app); + should_update_apps = true; } } } + if (should_update_apps && session->active) { + ust_app_global_update_all(session); + } end: return retval; } @@ -764,6 +922,7 @@ end: int trace_ust_untrack_pid(struct ltt_ust_session *session, int pid) { int retval = LTTNG_OK; + bool should_update_apps = false; if (pid == -1) { /* Create empty tracker, replace old tracker. */ @@ -780,7 +939,7 @@ int trace_ust_untrack_pid(struct ltt_ust_session *session, int pid) fini_pid_tracker(&tmp_tracker); /* Remove session from all applications */ - ust_app_global_update_all(session); + should_update_apps = true; } else { int ret; struct ust_app *app; @@ -799,9 +958,12 @@ int trace_ust_untrack_pid(struct ltt_ust_session *session, int pid) /* Remove session from application. */ app = ust_app_find_by_pid(pid); if (app) { - ust_app_global_update(session, app); + should_update_apps = true; } } + if (should_update_apps && session->active) { + ust_app_global_update_all(session); + } end: return retval; } @@ -860,7 +1022,7 @@ static void destroy_context_rcu(struct rcu_head *head) struct ltt_ust_context *ctx = caa_container_of(node, struct ltt_ust_context, node); - free(ctx); + trace_ust_destroy_context(ctx); } /* @@ -905,6 +1067,20 @@ void trace_ust_destroy_event(struct ltt_ust_event *event) free(event); } +/* + * Cleanup ust context structure. + */ +void trace_ust_destroy_context(struct ltt_ust_context *ctx) +{ + assert(ctx); + + if (ctx->ctx.ctx == LTTNG_UST_CONTEXT_APP_CONTEXT) { + free(ctx->ctx.u.app_ctx.provider_name); + free(ctx->ctx.u.app_ctx.ctx_name); + } + free(ctx); +} + /* * URCU intermediate call to complete destroy event. */ @@ -1028,7 +1204,8 @@ static void destroy_domain_global(struct ltt_ust_domain_global *dom) } /* - * Cleanup ust session structure + * Cleanup ust session structure, keeping data required by + * destroy notifier. * * Should *NOT* be called with RCU read-side lock held. */ @@ -1064,9 +1241,13 @@ void trace_ust_destroy_session(struct ltt_ust_session *session) buffer_reg_uid_destroy(reg, session->consumer); } - consumer_output_put(session->consumer); - fini_pid_tracker(&session->pid_tracker); + lttng_trace_chunk_put(session->current_trace_chunk); +} +/* Free elements needed by destroy notifiers. */ +void trace_ust_free_session(struct ltt_ust_session *session) +{ + consumer_output_put(session->consumer); free(session); }