SoW-2020-0002: Trace Hit Counters
[lttng-tools.git] / src / bin / lttng-sessiond / event.c
index 125adb9a058bf4fdedac31a1daaeaa02733c26c5..dd2e4b382fa46ca76978898a2a0e1b38bd8ccf9c 100644 (file)
 #include <common/compat/errno.h>
 #include <lttng/lttng.h>
 #include <lttng/condition/condition.h>
-#include <lttng/condition/event-rule.h>
+#include <lttng/condition/on-event.h>
 #include <lttng/event-rule/event-rule.h>
 #include <lttng/event-rule/event-rule-internal.h>
 #include <common/bytecode/bytecode.h>
 #include <common/error.h>
 #include <common/sessiond-comm/sessiond-comm.h>
 #include <common/filter.h>
+#include <common/kernel-ctl/kernel-ctl.h>
 #include <common/context.h>
 
 #include "channel.h"
@@ -38,7 +39,7 @@
  * Add unique UST event based on the event name, filter bytecode and loglevel.
  */
 static void add_unique_ust_event(struct lttng_ht *ht,
-               struct ltt_ust_event *event)
+               struct ltt_ust_event *event, struct lttng_map_key *map_key)
 {
        struct cds_lfht_node *node_ptr;
        struct ltt_ust_ht_key key;
@@ -52,6 +53,7 @@ static void add_unique_ust_event(struct lttng_ht *ht,
        key.loglevel_type = event->attr.loglevel_type;
        key.loglevel_value = event->attr.loglevel;
        key.exclusion = event->exclusion;
+       key.key = map_key;
 
        node_ptr = cds_lfht_add_unique(ht->ht,
                        ht->hash_fct(event->node.key, lttng_ht_seed),
@@ -113,8 +115,8 @@ int event_kernel_enable_event(struct ltt_kernel_channel *kchan,
        assert(kchan);
        assert(event);
 
-       kevent = trace_kernel_find_event(event->name, kchan,
-                       event->type, filter);
+       kevent = trace_kernel_find_event(&kchan->events_list,
+                       0, event->name, event->type, filter);
        if (kevent == NULL) {
                ret = kernel_create_event(event, kchan, filter_expression, filter);
                /* We have passed ownership */
@@ -142,6 +144,104 @@ end:
        return ret;
 }
 
+/*
+ * Disable kernel tracepoint events for a map from the kernel session of
+ * a specified event_name and event type.
+ * On type LTTNG_EVENT_ALL all events with event_name are disabled.
+ * If event_name is NULL all events of the specified type are disabled.
+ */
+int map_event_kernel_disable_event(struct ltt_kernel_map *kmap,
+               uint64_t action_tracer_token)
+{
+       struct ltt_kernel_event_counter *kevent_counter;
+       struct lttng_ht_iter iter;
+       const struct lttng_ht_node_u64 *node;
+       enum lttng_error_code ret_code;
+       int ret;
+
+       assert(kmap);
+
+       lttng_ht_lookup(kmap->event_counters_ht, (void *) &action_tracer_token, &iter);
+       node = lttng_ht_iter_get_node_u64(&iter);
+       if (node){
+               kevent_counter = caa_container_of(node,
+                               struct ltt_kernel_event_counter, ht_node);
+               ret = kernctl_disable(kevent_counter->fd);
+               if (ret < 0) {
+                       ret_code = LTTNG_ERR_KERN_DISABLE_FAIL;
+                       goto end;
+               }
+               kevent_counter->enabled = false;
+               DBG("Disable kernel event counter");
+       } else {
+               ret_code = LTTNG_ERR_NO_EVENT;
+               goto end;
+       }
+
+       ret_code = LTTNG_OK;
+end:
+       return ret_code;
+}
+
+/*
+ * Enable kernel tracepoint event for a map from the kernel session.
+ * We own filter_expression and filter.
+ */
+int map_event_kernel_enable_event(struct ltt_kernel_map *kmap,
+               const struct lttng_credentials *creds,
+               uint64_t action_tracer_token,
+               const struct lttng_event_rule *event_rule,
+               struct lttng_map_key *key)
+{
+       int err;
+       enum lttng_error_code ret_code;
+       struct ltt_kernel_event_counter *kevent_counter;
+       struct lttng_ht_iter iter;
+       const struct lttng_ht_node_u64 *node;
+
+       assert(kmap);
+       assert(event_rule);
+       assert(key);
+
+       lttng_ht_lookup(kmap->event_counters_ht, (void *) &action_tracer_token, &iter);
+       node = lttng_ht_iter_get_node_u64(&iter);
+       if (node){
+               kevent_counter = caa_container_of(node,
+                               struct ltt_kernel_event_counter, ht_node);
+               if (kevent_counter->enabled) {
+                       /* At this point, the event is considered enabled */
+                       ret_code = LTTNG_ERR_KERN_EVENT_EXIST;
+                       goto end;
+               }
+
+               err = kernctl_enable(kevent_counter->fd);
+               if (err < 0) {
+                       switch (-err) {
+                       case EEXIST:
+                               ret_code = LTTNG_ERR_KERN_EVENT_EXIST;
+                               break;
+                       default:
+                               PERROR("enable kernel event counter");
+                               ret_code = LTTNG_ERR_KERN_ENABLE_FAIL;
+                               break;
+                       }
+                       goto end;
+               }
+
+       } else {
+
+               ret_code = kernel_create_event_counter(kmap, creds,
+                               action_tracer_token, event_rule, key);
+               if (ret_code != LTTNG_OK) {
+                       goto end;
+               }
+       }
+
+       ret_code = LTTNG_OK;
+end:
+       return ret_code;
+}
+
 /*
  * ============================
  * UST : The Ultimate Frontier!
@@ -162,18 +262,26 @@ int event_ust_enable_tracepoint(struct ltt_ust_session *usess,
        int ret = LTTNG_OK, to_create = 0;
        struct ltt_ust_event *uevent;
 
+       /*
+        * FIXME: Frdeso. The tracer token should probably me set for regular
+        * events too.
+        */
+       uint64_t tracer_token = 0;
+
        assert(usess);
        assert(uchan);
        assert(event);
 
        rcu_read_lock();
 
-       uevent = trace_ust_find_event(uchan->events, event->name, filter,
+       uevent = trace_ust_find_event(uchan->events, 0, event->name, filter,
                        (enum lttng_ust_loglevel_type) event->loglevel_type,
-                       event->loglevel, exclusion);
+                       event->loglevel, exclusion, NULL);
        if (!uevent) {
-               ret = trace_ust_create_event(event, filter_expression,
-                               filter, exclusion, internal_event, &uevent);
+               ret = trace_ust_create_event(tracer_token, event->name, NULL, event->type,
+                               event->loglevel_type, event->loglevel,
+                               filter_expression, filter, exclusion,
+                               internal_event, &uevent);
                /* We have passed ownership */
                filter_expression = NULL;
                filter = NULL;
@@ -196,7 +304,7 @@ int event_ust_enable_tracepoint(struct ltt_ust_session *usess,
        uevent->enabled = 1;
        if (to_create) {
                /* Add ltt ust event to channel */
-               add_unique_ust_event(uchan->events, uevent);
+               add_unique_ust_event(uchan->events, uevent, NULL);
        }
 
        if (!usess->active) {
@@ -205,10 +313,10 @@ int event_ust_enable_tracepoint(struct ltt_ust_session *usess,
 
        if (to_create) {
                /* Create event on all UST registered apps for session */
-               ret = ust_app_create_event_glb(usess, uchan, uevent);
+               ret = ust_app_create_channel_event_glb(usess, uchan, uevent);
        } else {
                /* Enable event on all UST registered apps for session */
-               ret = ust_app_enable_event_glb(usess, uchan, uevent);
+               ret = ust_app_enable_channel_event_glb(usess, uchan, uevent);
        }
 
        if (ret < 0) {
@@ -252,6 +360,140 @@ error:
        return ret;
 }
 
+/*
+ * Enable UST tracepoint event for a map from a UST session.
+ */
+enum lttng_error_code map_event_ust_enable_tracepoint(
+               struct ltt_ust_session *usess,
+               struct ltt_ust_map *umap,
+               uint64_t tracer_token,
+               char *ev_name,
+               struct lttng_map_key *key,
+               enum lttng_event_type ev_type,
+               enum lttng_loglevel_type ev_loglevel_type,
+               int ev_loglevel_value,
+               char *_filter_expression,
+               struct lttng_bytecode *_filter,
+               struct lttng_event_exclusion *exclusion,
+               bool internal_event)
+{
+       enum lttng_error_code ret_code = LTTNG_OK;
+       int ret, to_create = 0;
+       struct ltt_ust_event *uevent;
+       struct lttng_bytecode *filter = NULL;
+       char *filter_expression = NULL;
+
+
+       assert(usess);
+       assert(umap);
+
+       /*
+        * FIXME: FRDESO: this function was copied from ust-app.c
+        */
+       if (_filter_expression) {
+               filter_expression = strdup(_filter_expression);
+       }
+
+       if (_filter) {
+               filter = zmalloc(sizeof(*filter) + _filter->len);
+               if (!filter) {
+                       PERROR("Failed to allocate lttng_ust_filter_bytecode: bytecode len = %" PRIu32 " bytes", _filter->len);
+                       goto error;
+               }
+
+               assert(sizeof(struct lttng_bytecode) ==
+                       sizeof(struct lttng_ust_filter_bytecode));
+               memcpy(filter, _filter, sizeof(*filter) + _filter->len);
+       }
+
+       rcu_read_lock();
+
+       uevent = trace_ust_find_event(umap->events, tracer_token, ev_name, filter,
+                       (enum lttng_ust_loglevel_type) ev_loglevel_type,
+                       ev_loglevel_value, exclusion, key);
+       if (!uevent) {
+               ret_code = trace_ust_create_event(tracer_token, ev_name, key, ev_type,
+                               ev_loglevel_type, ev_loglevel_value,
+                               filter_expression, filter, exclusion,
+                               internal_event, &uevent);
+               /* We have passed ownership */
+               filter_expression = NULL;
+               filter = NULL;
+               exclusion = NULL;
+               if (ret_code != LTTNG_OK) {
+                       goto error;
+               }
+
+               /* Valid to set it after the goto error since uevent is still NULL */
+               to_create = 1;
+       }
+
+       if (uevent->enabled) {
+               /* It's already enabled so everything is OK */
+               assert(!to_create);
+               ret_code = LTTNG_ERR_UST_EVENT_ENABLED;
+               goto end;
+       }
+
+       uevent->enabled = 1;
+       if (to_create) {
+               /* Add ltt ust event to map */
+               add_unique_ust_event(umap->events, uevent, key);
+       }
+
+       if (!usess->active) {
+               goto end;
+       }
+
+       if (to_create) {
+               /* Create event on all UST registered apps for session */
+               ret = ust_app_create_map_event_glb(usess, umap, uevent);
+       } else {
+               /* Enable event on all UST registered apps for session */
+               ret = ust_app_enable_map_event_glb(usess, umap, uevent);
+       }
+
+       if (ret < 0) {
+               if (ret == -LTTNG_UST_ERR_EXIST) {
+                       ret_code = LTTNG_ERR_UST_EVENT_EXIST;
+                       goto end;
+               } else {
+                       ret_code = LTTNG_ERR_UST_ENABLE_FAIL;
+                       goto error;
+               }
+       }
+
+       DBG("Event UST %s %s in map %s", uevent->attr.name,
+                       to_create ? "created" : "enabled", umap->name);
+
+       ret_code = LTTNG_OK;
+
+end:
+       rcu_read_unlock();
+       free(filter_expression);
+       free(filter);
+       free(exclusion);
+       return ret_code;
+
+error:
+       /*
+        * Only destroy event on creation time (not enabling time) because if the
+        * event is found in the map (to_create == 0), it means that at some
+        * point the enable_event worked and it's thus valid to keep it alive.
+        * Destroying it also implies that we also destroy it's shadow copy to sync
+        * everyone up.
+        */
+       if (to_create) {
+               /* In this code path, the uevent was not added to the hash table */
+               trace_ust_destroy_event(uevent);
+       }
+       rcu_read_unlock();
+       free(filter_expression);
+       free(filter);
+       free(exclusion);
+       return ret_code;
+}
+
 /*
  * Disable UST tracepoint of a channel from a UST session.
  */
@@ -300,7 +542,7 @@ int event_ust_disable_tracepoint(struct ltt_ust_session *usess,
                if (!usess->active) {
                        goto next;
                }
-               ret = ust_app_disable_event_glb(usess, uchan, uevent);
+               ret = ust_app_disable_channel_event_glb(usess, uchan, uevent);
                if (ret < 0 && ret != -LTTNG_UST_ERR_EXIST) {
                        ret = LTTNG_ERR_UST_DISABLE_FAIL;
                        goto error;
@@ -319,6 +561,69 @@ error:
        return ret;
 }
 
+/*
+ * Disable UST tracepoint of a map from a UST session.
+ */
+enum lttng_error_code map_event_ust_disable_tracepoint(
+               struct ltt_ust_session *usess,
+               struct ltt_ust_map *umap,
+               uint64_t tracer_token,
+               char *event_name,
+               struct lttng_map_key *key,
+               enum lttng_event_type ev_type,
+               enum lttng_loglevel_type ev_loglevel_type,
+               int ev_loglevel_value,
+               char *filter_expression,
+               struct lttng_bytecode *filter,
+               struct lttng_event_exclusion *exclusion,
+               bool internal_event)
+{
+       int ret;
+       enum lttng_error_code ret_code;
+       struct ltt_ust_event *uevent;
+
+       assert(usess);
+       assert(umap);
+       assert(event_name);
+
+       rcu_read_lock();
+
+       /*
+        * FIXME: frdeso: We need to pass all the parameters to find the right
+        * event.
+        */
+       uevent = trace_ust_find_event(umap->events, tracer_token, event_name, filter,
+                       (enum lttng_ust_loglevel_type) ev_loglevel_type,
+                       ev_loglevel_value, exclusion, key);
+       assert(uevent);
+
+       if (uevent->enabled == 0) {
+               ret_code = LTTNG_OK;
+               goto end;
+       }
+
+       uevent->enabled = 0;
+       DBG2("Event UST %s disabled in map %s", uevent->attr.name,
+               umap->name);
+
+       if (!usess->active) {
+               ret_code = LTTNG_OK;
+               goto end;
+       }
+
+       ret = ust_app_disable_map_event_glb(usess, umap, uevent);
+       if (ret < 0 && ret != -LTTNG_UST_ERR_EXIST) {
+               ret_code = LTTNG_ERR_UST_DISABLE_FAIL;
+               goto end;
+       }
+
+       ret_code = LTTNG_OK;
+
+end:
+       rcu_read_unlock();
+       return ret_code;
+}
+
 /*
  * Disable all UST tracepoints for a channel from a UST session.
  */
@@ -372,6 +677,56 @@ error:
        return ret;
 }
 
+/*
+ * Disable all UST tracepoints for a map from a UST session.
+ */
+int map_event_ust_disable_all_tracepoints(struct ltt_ust_session *usess,
+               struct ltt_ust_map *umap)
+{
+       int ret, error = 0;
+       struct lttng_ht_iter iter;
+       struct ltt_ust_event *uevent = NULL;
+       struct lttng_event *events = NULL;
+
+       assert(usess);
+       assert(umap);
+
+       rcu_read_lock();
+
+       /* Disabling existing events */
+       cds_lfht_for_each_entry(umap->events->ht, &iter.iter, uevent,
+                       node.node) {
+               if (uevent->enabled == 1) {
+                       ret = map_event_ust_disable_tracepoint(usess, umap,
+                                       uevent->attr.token,
+                                       uevent->attr.name,
+                                       uevent->key,
+                                       uevent->attr.instrumentation,
+                                       (enum lttng_loglevel_type) uevent->attr.loglevel_type,
+                                       uevent->attr.loglevel,
+                                       uevent->filter_expression,
+                                       uevent->filter,
+                                       uevent->exclusion,
+                                       false);
+                       if (ret < 0) {
+                               error = LTTNG_ERR_UST_DISABLE_FAIL;
+                               continue;
+                       }
+               }
+       }
+
+       /*
+        * FIXME: FRDESO: in the equivalent function
+        * event_ust_disable_all_tracepoints() (above ^) we also iterator over
+        * all lttng_event. Do we need to do this here too?
+        */
+
+       ret = error ? error : LTTNG_OK;
+       rcu_read_unlock();
+       free(events);
+       return ret;
+}
+
 static void agent_enable_all(struct agent *agt)
 {
        struct agent_event *aevent;
@@ -601,9 +956,9 @@ int trigger_agent_enable(const struct lttng_trigger *trigger, struct agent *agt)
        condition = lttng_trigger_get_const_condition(trigger);
 
        assert(lttng_condition_get_type(condition) ==
-                       LTTNG_CONDITION_TYPE_EVENT_RULE_HIT);
+                       LTTNG_CONDITION_TYPE_ON_EVENT);
 
-       c_status = lttng_condition_event_rule_get_rule(condition, &rule);
+       c_status = lttng_condition_on_event_get_rule(condition, &rule);
        assert(c_status == LTTNG_CONDITION_STATUS_OK);
 
        assert(lttng_event_rule_get_type(rule) ==
@@ -779,13 +1134,15 @@ static int event_agent_disable_one(struct ltt_ust_session *usess,
         * happens thanks to an UST filter. The following -1 is actually
         * ignored since the type is LTTNG_UST_LOGLEVEL_ALL.
         */
-       uevent = trace_ust_find_event(uchan->events, (char *) ust_event_name,
-                       aevent->filter, LTTNG_UST_LOGLEVEL_ALL, -1, NULL);
+       /* TODO: JORAJ FRDESO: hmmm what to do with tracer token here?
+        */
+       uevent = trace_ust_find_event(uchan->events, 0, (char *) ust_event_name,
+                       aevent->filter, LTTNG_UST_LOGLEVEL_ALL, -1, NULL, NULL);
        /* If the agent event exists, it must be available on the UST side. */
        assert(uevent);
 
        if (usess->active) {
-               ret = ust_app_disable_event_glb(usess, uchan, uevent);
+               ret = ust_app_disable_channel_event_glb(usess, uchan, uevent);
                if (ret < 0 && ret != -LTTNG_UST_ERR_EXIST) {
                        ret = LTTNG_ERR_UST_DISABLE_FAIL;
                        goto error;
This page took 0.028947 seconds and 5 git commands to generate.