From: David Goulet Date: Wed, 21 Nov 2012 17:28:03 +0000 (-0500) Subject: Change the UST event hash table match function X-Git-Tag: v2.1.0-rc8~4 X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=commitdiff_plain;h=18eace3ba4aeaa6b869c8ad9ec1273381b4cbdee;hp=178191b3899f114001f000c2e7f46909969f9c6f Change the UST event hash table match function The event are now matched, when looked up, with the name/filter/loglevel triplet since the UST tracer now allows us to enable the same event with different filters or/and loglevels. The disable command however only takes the event name so for now it disable all events matching that name which is why we still hash by event name. Acked-by: Mathieu Desnoyers Signed-off-by: David Goulet --- diff --git a/src/bin/lttng-sessiond/event.c b/src/bin/lttng-sessiond/event.c index a2e6c37ef..70f6fe62d 100644 --- a/src/bin/lttng-sessiond/event.c +++ b/src/bin/lttng-sessiond/event.c @@ -32,6 +32,26 @@ #include "trace-kernel.h" #include "trace-ust.h" +static void add_unique_ust_event(struct lttng_ht *ht, + struct ltt_ust_event *event) +{ + struct cds_lfht_node *node_ptr; + struct ltt_ust_ht_key key; + + assert(ht); + assert(ht->ht); + assert(event); + + key.name = event->attr.name; + key.filter = (struct lttng_filter_bytecode *) event->filter; + key.loglevel = event->attr.loglevel; + + node_ptr = cds_lfht_add_unique(ht->ht, + ht->hash_fct(event->node.key, lttng_ht_seed), + trace_ust_ht_match_event, &key, &event->node.node); + assert(node_ptr == &event->node.node); +} + /* * Setup a lttng_event used to enable *all* syscall tracing. */ @@ -337,8 +357,8 @@ int event_ust_enable_all_tracepoints(struct ltt_ust_session *usess, int domain, * Check if event exist and if so, continue since it was enable * previously. */ - uevent = trace_ust_find_event_by_name(uchan->events, - events[i].name); + uevent = trace_ust_find_event(uchan->events, events[i].name, NULL, + events[i].loglevel); if (uevent != NULL) { ret = ust_app_enable_event_pid(usess, uchan, uevent, events[i].pid); @@ -374,7 +394,7 @@ int event_ust_enable_all_tracepoints(struct ltt_ust_session *usess, int domain, uevent->enabled = 1; /* Add ltt ust event to channel */ rcu_read_lock(); - lttng_ht_add_unique_str(uchan->events, &uevent->node); + add_unique_ust_event(uchan->events, uevent); rcu_read_unlock(); } @@ -410,7 +430,12 @@ int event_ust_enable_tracepoint(struct ltt_ust_session *usess, int domain, int ret = LTTNG_OK, to_create = 0; struct ltt_ust_event *uevent; - uevent = trace_ust_find_event_by_name(uchan->events, event->name); + DBG3("Enable ust: %s l:%d f:%p", event->name, event->loglevel, NULL); + + rcu_read_lock(); + + uevent = trace_ust_find_event(uchan->events, event->name, NULL, + event->loglevel); if (uevent == NULL) { uevent = trace_ust_create_event(event); if (uevent == NULL) { @@ -476,10 +501,8 @@ int event_ust_enable_tracepoint(struct ltt_ust_session *usess, int domain, } if (to_create) { - rcu_read_lock(); /* Add ltt ust event to channel */ - lttng_ht_add_unique_str(uchan->events, &uevent->node); - rcu_read_unlock(); + add_unique_ust_event(uchan->events, uevent); } DBG("Event UST %s %s in channel %s", uevent->attr.name, @@ -488,6 +511,7 @@ int event_ust_enable_tracepoint(struct ltt_ust_session *usess, int domain, ret = LTTNG_OK; end: + rcu_read_unlock(); return ret; error: @@ -502,6 +526,7 @@ error: /* In this code path, the uevent was not added to the hash table */ trace_ust_destroy_event(uevent); } + rcu_read_unlock(); return ret; } @@ -513,45 +538,67 @@ int event_ust_disable_tracepoint(struct ltt_ust_session *usess, int domain, { int ret; struct ltt_ust_event *uevent; + struct lttng_ht_node_str *node; + struct lttng_ht_iter iter; + void *orig_match_fct; + struct lttng_ht *ht; - uevent = trace_ust_find_event_by_name(uchan->events, event_name); - if (uevent == NULL) { + ht = uchan->events; + + /* Save match function so we can use the event by name match. */ + orig_match_fct = (void *) ht->match_fct; + ht->match_fct = trace_ust_ht_match_event_by_name; + + rcu_read_lock(); + lttng_ht_lookup(ht, (void *) event_name, &iter); + node = lttng_ht_iter_get_node_str(&iter); + if (node == NULL) { + DBG2("Trace UST event NOT found by name %s", event_name); ret = LTTNG_ERR_UST_EVENT_NOT_FOUND; goto error; } - if (uevent->enabled == 0) { - /* It's already enabled so everything is OK */ - ret = LTTNG_OK; - goto end; - } - - switch (domain) { - case LTTNG_DOMAIN_UST: - ret = ust_app_disable_event_glb(usess, uchan, uevent); - if (ret < 0 && ret != -LTTNG_UST_ERR_EXIST) { - ret = LTTNG_ERR_UST_DISABLE_FAIL; - goto error; + do { + uevent = caa_container_of(node, struct ltt_ust_event, node); + if (uevent->enabled == 0) { + /* It's already disabled so everything is OK */ + ret = LTTNG_OK; + continue; } - break; + + switch (domain) { + case LTTNG_DOMAIN_UST: + ret = ust_app_disable_event_glb(usess, uchan, uevent); + if (ret < 0 && ret != -LTTNG_UST_ERR_EXIST) { + ret = LTTNG_ERR_UST_DISABLE_FAIL; + goto error; + } + break; #if 0 - case LTTNG_DOMAIN_UST_EXEC_NAME: - case LTTNG_DOMAIN_UST_PID: - case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: + case LTTNG_DOMAIN_UST_EXEC_NAME: + case LTTNG_DOMAIN_UST_PID: + case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: #endif - default: - ret = LTTNG_ERR_UND; - goto error; - } + default: + ret = LTTNG_ERR_UND; + goto error; + } + + uevent->enabled = 0; + + /* Get next duplicate event by name. */ + cds_lfht_next_duplicate(ht->ht, trace_ust_ht_match_event_by_name, + event_name, &iter.iter); + node = lttng_ht_iter_get_node_str(&iter); + } while (node); - uevent->enabled = 0; ret = LTTNG_OK; -end: DBG2("Event UST %s disabled in channel %s", uevent->attr.name, uchan->name); - error: + ht->match_fct = orig_match_fct; + rcu_read_unlock(); return ret; } @@ -589,16 +636,10 @@ int event_ust_disable_all_tracepoints(struct ltt_ust_session *usess, int domain, } for (i = 0; i < size; i++) { - uevent = trace_ust_find_event_by_name(uchan->events, + ret = event_ust_disable_tracepoint(usess, domain, uchan, events[i].name); - if (uevent != NULL && uevent->enabled == 1) { - ret = ust_app_disable_event_pid(usess, uchan, uevent, - events[i].pid); - if (ret < 0 && ret != -LTTNG_UST_ERR_EXIST) { - ret = LTTNG_ERR_UST_DISABLE_FAIL; - goto error; - } - uevent->enabled = 0; + if (ret != LTTNG_OK) { + /* Continue to disable the rest... */ continue; } } diff --git a/src/bin/lttng-sessiond/filter.c b/src/bin/lttng-sessiond/filter.c index 1088cbed5..d37773d49 100644 --- a/src/bin/lttng-sessiond/filter.c +++ b/src/bin/lttng-sessiond/filter.c @@ -118,7 +118,8 @@ int filter_ust_set(struct ltt_ust_session *usess, int domain, /* 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); + uevent = trace_ust_find_event(uchan->events, event->name, bytecode, + event->loglevel); if (uevent == NULL) { ret = LTTNG_ERR_UST_EVENT_NOT_FOUND; goto error; @@ -137,7 +138,8 @@ int filter_ust_set(struct ltt_ust_session *usess, int domain, } else if (!uchan && have_event) { /* Add filter to event */ /* Add context to event without having the channel name */ cds_lfht_for_each_entry(chan_ht->ht, &iter.iter, uchan, node.node) { - uevent = trace_ust_find_event_by_name(uchan->events, event->name); + uevent = trace_ust_find_event(uchan->events, event->name, bytecode, + event->loglevel); if (uevent != NULL) { ret = add_ufilter_to_event(usess, domain, uchan, uevent, bytecode); /* diff --git a/src/bin/lttng-sessiond/trace-ust.c b/src/bin/lttng-sessiond/trace-ust.c index 4c7dac8b7..962255b5c 100644 --- a/src/bin/lttng-sessiond/trace-ust.c +++ b/src/bin/lttng-sessiond/trace-ust.c @@ -26,6 +26,96 @@ #include "trace-ust.h" +int trace_ust_ht_match_event_by_name(struct cds_lfht_node *node, + const void *_key) +{ + struct ltt_ust_event *event; + const char *name; + + assert(node); + assert(_key); + + event = caa_container_of(node, struct ltt_ust_event, node.node); + name = _key; + + /* Event name */ + if (strncmp(event->attr.name, name, sizeof(event->attr.name)) != 0) { + goto no_match; + } + + /* Match. */ + return 1; + +no_match: + return 0; +} + +int trace_ust_ht_match_event(struct cds_lfht_node *node, const void *_key) +{ + struct ltt_ust_event *event; + const struct ltt_ust_ht_key *key; + + assert(node); + assert(_key); + + event = caa_container_of(node, struct ltt_ust_event, node.node); + key = _key; + + /* Match the 3 elements of the key: name, filter and loglevel. */ + + /* Event name */ + if (strncmp(event->attr.name, key->name, sizeof(event->attr.name)) != 0) { + DBG3("[Match] name failed: %s and %s", + event->attr.name, key->name); + goto no_match; + } + + /* Event loglevel. */ + if (event->attr.loglevel != key->loglevel) { + if (event->attr.loglevel_type == 0 && key->loglevel == 0 && + event->attr.loglevel == -1) { + /* + * This is because on event creation, the loglevel is set to -1 if + * the event loglevel type is ALL so 0 and -1 are accepted for this + * loglevel type. + */ + } else { + DBG3("[Match] loglevel failed: %d and %d", + event->attr.loglevel, key->loglevel); + goto no_match; + } + } + + /* Only one of the filters is NULL, fail. */ + if ((key->filter && !event->filter) || (!key->filter && event->filter)) { + DBG3("[Match] filters failed: k:%p and e:%p", + key->filter, event->filter); + goto no_match; + } + + /* Both filters are NULL, success. */ + if (!key->filter && !event->filter) { + goto match; + } + + /* Both filters exists, check length followed by the bytecode. */ + if (event->filter->len == key->filter->len && + memcmp(event->filter->data, key->filter->data, + event->filter->len) == 0) { + goto match; + } + + DBG3("[Match] filters failed: k:%p and e:%p", + key->filter, event->filter); + +no_match: + return 0; + +match: + DBG3("[MATCH] %s", key->name); + return 1; +} + /* * Find the channel in the hashtable. */ @@ -56,27 +146,40 @@ error: /* * Find the event in the hashtable. */ -struct ltt_ust_event *trace_ust_find_event_by_name(struct lttng_ht *ht, - char *name) +struct ltt_ust_event *trace_ust_find_event(struct lttng_ht *ht, + char *name, struct lttng_filter_bytecode *filter, int loglevel) { struct lttng_ht_node_str *node; struct lttng_ht_iter iter; + struct ltt_ust_ht_key key; + void *orig_match_fct; - rcu_read_lock(); - lttng_ht_lookup(ht, (void *) name, &iter); + assert(name); + assert(ht); + + key.name = name; + key.filter = filter; + key.loglevel = loglevel; + + /* Save match function so we can use the ust app event match. */ + orig_match_fct = (void *) ht->match_fct; + ht->match_fct = trace_ust_ht_match_event; + + cds_lfht_lookup(ht->ht, ht->hash_fct((void *) name, lttng_ht_seed), + trace_ust_ht_match_event, &key, &iter.iter); node = lttng_ht_iter_get_node_str(&iter); if (node == NULL) { - rcu_read_unlock(); goto error; } - rcu_read_unlock(); - DBG2("Trace UST event found by name %s", name); + DBG2("Trace UST event %s found", key.name); return caa_container_of(node, struct ltt_ust_event, node); error: - DBG2("Trace UST event NOT found by name %s", name); + DBG2("Trace UST event %s NOT found", key.name); + /* Put back original match function. */ + ht->match_fct = orig_match_fct; return NULL; } diff --git a/src/bin/lttng-sessiond/trace-ust.h b/src/bin/lttng-sessiond/trace-ust.h index 297037b20..efca4d23b 100644 --- a/src/bin/lttng-sessiond/trace-ust.h +++ b/src/bin/lttng-sessiond/trace-ust.h @@ -29,6 +29,12 @@ #include "consumer.h" #include "ust-ctl.h" +struct ltt_ust_ht_key { + const char *name; + const struct lttng_filter_bytecode *filter; + enum lttng_ust_loglevel_type loglevel; +}; + /* UST Stream list */ struct ltt_ust_stream_list { unsigned int count; @@ -129,11 +135,15 @@ struct ltt_ust_session { #ifdef HAVE_LIBLTTNG_UST_CTL +int trace_ust_ht_match_event(struct cds_lfht_node *node, const void *_key); +int trace_ust_ht_match_event_by_name(struct cds_lfht_node *node, + const void *_key); + /* * Lookup functions. NULL is returned if not found. */ -struct ltt_ust_event *trace_ust_find_event_by_name(struct lttng_ht *ht, - char *name); +struct ltt_ust_event *trace_ust_find_event(struct lttng_ht *ht, + char *name, struct lttng_filter_bytecode *filter, int loglevel); struct ltt_ust_channel *trace_ust_find_channel_by_name(struct lttng_ht *ht, char *name); @@ -160,13 +170,6 @@ void trace_ust_destroy_event(struct ltt_ust_event *event); #else /* HAVE_LIBLTTNG_UST_CTL */ -static inline -struct ltt_ust_event *trace_ust_find_event_by_name(struct lttng_ht *ht, - char *name) -{ - return NULL; -} - static inline struct ltt_ust_channel *trace_ust_find_channel_by_name(struct lttng_ht *ht, char *name) diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index 8dd7a9d1c..97792d9fe 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -36,6 +36,74 @@ #include "ust-consumer.h" #include "ust-ctl.h" +static int ht_match_ust_app_event(struct cds_lfht_node *node, const void *_key) +{ + struct ust_app_event *event; + const struct ust_app_ht_key *key; + + assert(node); + assert(_key); + + event = caa_container_of(node, struct ust_app_event, node.node); + key = _key; + + /* Match the 3 elements of the key: name, filter and loglevel. */ + + /* Event name */ + if (strncmp(event->attr.name, key->name, sizeof(event->attr.name)) != 0) { + goto no_match; + } + + /* Event loglevel. */ + if (event->attr.loglevel != key->loglevel) { + goto no_match; + } + + /* One of the filters is NULL, fail. */ + if ((key->filter && !event->filter) || (!key->filter && event->filter)) { + goto no_match; + } + + /* Both filters are NULL, success. */ + if (!key->filter && !event->filter) { + goto match; + } + + /* Both filters exists, check length followed by the bytecode. */ + if (event->filter->len == key->filter->len && + memcmp(event->filter->data, key->filter->data, + event->filter->len) == 0) { + goto match; + } + +match: + return 1; + +no_match: + return 0; + +} + +static void add_unique_ust_app_event(struct lttng_ht *ht, + struct ust_app_event *event) +{ + struct cds_lfht_node *node_ptr; + struct ust_app_ht_key key; + + assert(ht); + assert(ht->ht); + assert(event); + + key.name = event->attr.name; + key.filter = event->filter; + key.loglevel = event->attr.loglevel; + + node_ptr = cds_lfht_add_unique(ht->ht, + ht->hash_fct(event->node.key, lttng_ht_seed), + ht_match_ust_app_event, &key, &event->node.node); + assert(node_ptr == &event->node.node); +} + /* * Delete ust context safely. RCU read lock must be held before calling * this function. @@ -375,6 +443,41 @@ error: return NULL; } +static struct ust_app_event *find_ust_app_event(struct lttng_ht *ht, + char *name, struct lttng_ust_filter_bytecode *filter, int loglevel) +{ + struct lttng_ht_iter iter; + struct lttng_ht_node_str *node; + struct ust_app_event *event = NULL; + struct ust_app_ht_key key; + void *orig_match_fct; + + assert(name); + assert(ht); + + /* Setup key for event lookup. */ + key.name = name; + key.filter = filter; + key.loglevel = loglevel; + + /* Save match function so we can use the ust app event match. */ + orig_match_fct = (void *) ht->match_fct; + ht->match_fct = ht_match_ust_app_event; + + lttng_ht_lookup(ht, (void *) &key, &iter); + node = lttng_ht_iter_get_node_str(&iter); + if (node == NULL) { + goto end; + } + + event = caa_container_of(node, struct ust_app_event, node); + +end: + /* Put back original match function. */ + ht->match_fct = orig_match_fct; + return event; +} + /* * Create the channel context on the tracer. */ @@ -747,7 +850,6 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan, struct ltt_ust_channel *uchan) { struct lttng_ht_iter iter; - struct lttng_ht_node_str *ua_event_node; struct ltt_ust_event *uevent; struct ltt_ust_context *uctx; struct ust_app_event *ua_event; @@ -774,11 +876,9 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan, /* Copy all events from ltt ust channel to ust app channel */ cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent, node.node) { - struct lttng_ht_iter uiter; - - lttng_ht_lookup(ua_chan->events, (void *) uevent->attr.name, &uiter); - ua_event_node = lttng_ht_iter_get_node_str(&uiter); - if (ua_event_node == NULL) { + ua_event = find_ust_app_event(ua_chan->events, uevent->attr.name, + uevent->filter, uevent->attr.loglevel); + if (ua_event == NULL) { DBG2("UST event %s not found on shadow copy channel", uevent->attr.name); ua_event = alloc_ust_app_event(uevent->attr.name, &uevent->attr); @@ -786,7 +886,7 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan, continue; } shadow_copy_event(ua_event, uevent); - lttng_ht_add_unique_str(ua_chan->events, &ua_event->node); + add_unique_ust_app_event(ua_chan->events, ua_event); } } @@ -1154,14 +1254,12 @@ int create_ust_app_event(struct ust_app_session *ua_sess, struct ust_app *app) { int ret = 0; - struct lttng_ht_iter iter; - struct lttng_ht_node_str *ua_event_node; struct ust_app_event *ua_event; /* Get event node */ - lttng_ht_lookup(ua_chan->events, (void *)uevent->attr.name, &iter); - ua_event_node = lttng_ht_iter_get_node_str(&iter); - if (ua_event_node != NULL) { + ua_event = find_ust_app_event(ua_chan->events, uevent->attr.name, + uevent->filter, uevent->attr.loglevel); + if (ua_event != NULL) { ret = -EEXIST; goto end; } @@ -1183,7 +1281,7 @@ int create_ust_app_event(struct ust_app_session *ua_sess, goto error; } - lttng_ht_add_unique_str(ua_chan->events, &ua_event->node); + add_unique_ust_app_event(ua_chan->events, ua_event); DBG2("UST app create event %s for PID %d completed", ua_event->name, app->pid); @@ -1948,7 +2046,7 @@ int ust_app_enable_event_glb(struct ltt_ust_session *usess, { int ret = 0; struct lttng_ht_iter iter, uiter; - struct lttng_ht_node_str *ua_chan_node, *ua_event_node; + struct lttng_ht_node_str *ua_chan_node; struct ust_app *app; struct ust_app_session *ua_sess; struct ust_app_channel *ua_chan; @@ -1986,14 +2084,14 @@ int ust_app_enable_event_glb(struct ltt_ust_session *usess, ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node); - lttng_ht_lookup(ua_chan->events, (void*)uevent->attr.name, &uiter); - ua_event_node = lttng_ht_iter_get_node_str(&uiter); - if (ua_event_node == NULL) { + /* Get event node */ + ua_event = find_ust_app_event(ua_chan->events, uevent->attr.name, + uevent->filter, uevent->attr.loglevel); + if (ua_event == NULL) { DBG3("UST app enable event %s not found for app PID %d." "Skipping app", uevent->attr.name, app->pid); continue; } - ua_event = caa_container_of(ua_event_node, struct ust_app_event, node); ret = enable_ust_app_event(ua_sess, ua_event, app); if (ret < 0) { @@ -2581,7 +2679,7 @@ int ust_app_set_filter_event_glb(struct ltt_ust_session *usess, struct lttng_filter_bytecode *bytecode) { int ret = 0; - struct lttng_ht_node_str *ua_chan_node, *ua_event_node; + struct lttng_ht_node_str *ua_chan_node; struct lttng_ht_iter iter, uiter; struct ust_app_session *ua_sess; struct ust_app_event *ua_event; @@ -2612,13 +2710,12 @@ int ust_app_set_filter_event_glb(struct ltt_ust_session *usess, ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node); - lttng_ht_lookup(ua_chan->events, (void *)uevent->attr.name, &uiter); - ua_event_node = lttng_ht_iter_get_node_str(&uiter); - if (ua_event_node == NULL) { + ua_event = find_ust_app_event(ua_chan->events, uevent->attr.name, + (struct lttng_ust_filter_bytecode *) bytecode, + uevent->attr.loglevel); + if (ua_event == NULL) { continue; } - ua_event = caa_container_of(ua_event_node, struct ust_app_event, - node); ret = set_ust_app_event_filter(ua_sess, ua_event, bytecode, app); if (ret < 0) { @@ -2638,7 +2735,7 @@ int ust_app_enable_event_pid(struct ltt_ust_session *usess, { int ret = 0; struct lttng_ht_iter iter; - struct lttng_ht_node_str *ua_chan_node, *ua_event_node; + struct lttng_ht_node_str *ua_chan_node; struct ust_app *app; struct ust_app_session *ua_sess; struct ust_app_channel *ua_chan; @@ -2672,16 +2769,14 @@ int ust_app_enable_event_pid(struct ltt_ust_session *usess, ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node); - lttng_ht_lookup(ua_chan->events, (void *)uevent->attr.name, &iter); - ua_event_node = lttng_ht_iter_get_node_str(&iter); - if (ua_event_node == NULL) { + ua_event = find_ust_app_event(ua_chan->events, uevent->attr.name, + uevent->filter, uevent->attr.loglevel); + if (ua_event == NULL) { ret = create_ust_app_event(ua_sess, ua_chan, uevent, app); if (ret < 0) { goto error; } } else { - ua_event = caa_container_of(ua_event_node, struct ust_app_event, node); - ret = enable_ust_app_event(ua_sess, ua_event, app); if (ret < 0) { goto error; diff --git a/src/bin/lttng-sessiond/ust-app.h b/src/bin/lttng-sessiond/ust-app.h index 605b4a69b..72adf50aa 100644 --- a/src/bin/lttng-sessiond/ust-app.h +++ b/src/bin/lttng-sessiond/ust-app.h @@ -33,6 +33,12 @@ struct lttng_ust_filter_bytecode; extern int ust_consumerd64_fd, ust_consumerd32_fd; +struct ust_app_ht_key { + const char *name; + const struct lttng_ust_filter_bytecode *filter; + enum lttng_ust_loglevel_type loglevel; +}; + /* * Application registration data structure. */