Fix: check userspace perf counter name when looking up contexts
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 6 Nov 2014 22:34:08 +0000 (17:34 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Sun, 16 Nov 2014 12:29:08 +0000 (07:29 -0500)
create_ust_app_channel_context() looks for a context's existance
in a channel before adding it. However, it only checks for
context types. This is valid for all context types except for
LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER since multiple perf
thread counters may be enabled at the same time.

This fix ensures that the perf counter name is taken into
consideration when checking for a context's presence in a
channel.

Reported-by: Alexander Grigoriev <alexgri@tbricks.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
src/bin/lttng-sessiond/ust-app.c

index ed994a966ebe3c534b2a27991632d457ffdeecb1..7e4bf94051028f7c361749f0a162a4baee8e53b4 100644 (file)
@@ -1948,6 +1948,74 @@ error:
        return ret;
 }
 
+/*
+ * Match function for a hash table lookup of ust_app_ctx.
+ *
+ * It matches an ust app context based on the context type and, in the case
+ * of perf counters, their name.
+ */
+static int ht_match_ust_app_ctx(struct cds_lfht_node *node, const void *_key)
+{
+       struct ust_app_ctx *ctx;
+       const struct lttng_ust_context *key;
+
+       assert(node);
+       assert(_key);
+
+       ctx = caa_container_of(node, struct ust_app_ctx, node.node);
+       key = _key;
+
+       /* Context type */
+       if (ctx->ctx.ctx != key->ctx) {
+               goto no_match;
+       }
+
+       /* Check the name in the case of perf thread counters. */
+       if (key->ctx == LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER) {
+               if (strncmp(key->u.perf_counter.name,
+                       ctx->ctx.u.perf_counter.name,
+                       sizeof(key->u.perf_counter.name))) {
+                       goto no_match;
+               }
+       }
+
+       /* Match. */
+       return 1;
+
+no_match:
+       return 0;
+}
+
+/*
+ * Lookup for an ust app context from an lttng_ust_context.
+ *
+ * Return an ust_app_ctx object or NULL on error.
+ */
+static
+struct ust_app_ctx *find_ust_app_context(struct lttng_ht *ht,
+               struct lttng_ust_context *uctx)
+{
+       struct lttng_ht_iter iter;
+       struct lttng_ht_node_ulong *node;
+       struct ust_app_ctx *app_ctx = NULL;
+
+       assert(uctx);
+       assert(ht);
+
+       /* Lookup using the lttng_ust_context_type and a custom match fct. */
+       cds_lfht_lookup(ht->ht, ht->hash_fct((void *) uctx->ctx, lttng_ht_seed),
+                       ht_match_ust_app_ctx, uctx, &iter.iter);
+       node = lttng_ht_iter_get_node_ulong(&iter);
+       if (!node) {
+               goto end;
+       }
+
+       app_ctx = caa_container_of(node, struct ust_app_ctx, node);
+
+end:
+       return app_ctx;
+}
+
 /*
  * Create a context for the channel on the tracer.
  *
@@ -1959,15 +2027,12 @@ int create_ust_app_channel_context(struct ust_app_session *ua_sess,
                struct ust_app *app)
 {
        int ret = 0;
-       struct lttng_ht_iter iter;
-       struct lttng_ht_node_ulong *node;
        struct ust_app_ctx *ua_ctx;
 
        DBG2("UST app adding context to channel %s", ua_chan->name);
 
-       lttng_ht_lookup(ua_chan->ctx, (void *)((unsigned long)uctx->ctx), &iter);
-       node = lttng_ht_iter_get_node_ulong(&iter);
-       if (node != NULL) {
+       ua_ctx = find_ust_app_context(ua_chan->ctx, uctx);
+       if (ua_ctx) {
                ret = -EEXIST;
                goto error;
        }
This page took 0.027756 seconds and 4 git commands to generate.