SoW-2020-0003: Trace Hit Counters
[lttng-tools.git] / src / bin / lttng-sessiond / trace-ust.c
index 4a7e2610510cd805722315add867db300ea66823..3df0e65dc258cf143d9a97b1438ff4e717759f80 100644 (file)
@@ -1,19 +1,9 @@
 /*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
  *
- * 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,
- * as published by the Free Software Foundation.
+ * SPDX-License-Identifier: GPL-2.0-only
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #define _LGPL_SOURCE
 #include <common/common.h>
 #include <common/defaults.h>
 #include <common/trace-chunk.h>
+#include <common/utils.h>
+
+#include <lttng/map-key-internal.h>
+#include <lttng/map/map-internal.h>
 
 #include "buffer-registry.h"
+#include "map.h"
 #include "trace-ust.h"
 #include "utils.h"
 #include "ust-app.h"
@@ -82,7 +77,14 @@ int trace_ust_ht_match_event(struct cds_lfht_node *node, const void *_key)
        key = _key;
        ev_loglevel_value = event->attr.loglevel;
 
-       /* Match the 4 elements of the key: name, filter, loglevel, exclusions. */
+       /* Match the 6 elements of the key: tracer_token, map_key, name, filter, loglevel, exclusions. */
+       if (event->attr.token != key->tracer_token) {
+               goto no_match;
+       }
+
+       if (!lttng_map_key_is_equal(event->key, key->key)) {
+               goto no_match;
+       }
 
        /* Event name */
        if (strncmp(event->attr.name, key->name, sizeof(event->attr.name)) != 0) {
@@ -198,14 +200,44 @@ error:
        return NULL;
 }
 
+/*
+ * Find the map in the hashtable and return map pointer. RCU read side
+ * lock MUST be acquired before calling this.
+ */
+struct ltt_ust_map *trace_ust_find_map_by_name(struct lttng_ht *ht,
+               const char *name)
+{
+       struct lttng_ht_node_str *node;
+       struct lttng_ht_iter iter;
+
+       if (name[0] == '\0') {
+               goto error;
+       }
+
+       lttng_ht_lookup(ht, (void *)name, &iter);
+       node = lttng_ht_iter_get_node_str(&iter);
+       if (node == NULL) {
+               goto error;
+       }
+
+       DBG2("Trace UST map %s found by name", name);
+
+       return caa_container_of(node, struct ltt_ust_map, node);
+
+error:
+       DBG2("Trace UST map %s not found by name", name);
+       return NULL;
+}
+
 /*
  * Find the event in the hashtable and return event pointer. RCU read side lock
  * MUST be acquired before calling this.
  */
 struct ltt_ust_event *trace_ust_find_event(struct lttng_ht *ht,
-               char *name, struct lttng_filter_bytecode *filter,
+               uint64_t tracer_token, char *name, struct lttng_bytecode *filter,
                enum lttng_ust_loglevel_type loglevel_type, int loglevel_value,
-               struct lttng_event_exclusion *exclusion)
+               struct lttng_event_exclusion *exclusion,
+               struct lttng_map_key *map_key)
 {
        struct lttng_ht_node_str *node;
        struct lttng_ht_iter iter;
@@ -214,11 +246,13 @@ struct ltt_ust_event *trace_ust_find_event(struct lttng_ht *ht,
        assert(name);
        assert(ht);
 
+       key.tracer_token = tracer_token;
        key.name = name;
        key.filter = filter;
        key.loglevel_type = loglevel_type;
        key.loglevel_value = loglevel_value;
        key.exclusion = exclusion;
+       key.key = map_key;
 
        cds_lfht_lookup(ht->ht, ht->hash_fct((void *) name, lttng_ht_seed),
                        trace_ust_ht_match_event, &key, &iter.iter);
@@ -310,19 +344,21 @@ struct ltt_ust_session *trace_ust_create_session(uint64_t session_id)
 
        /* Alloc UST global domain channels' HT */
        lus->domain_global.channels = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
+       /* Alloc UST global domain maps' HT */
+       lus->domain_global.maps = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
        /* Alloc agent hash table. */
        lus->agents = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
 
-       lus->tracker_list_vpid = lttng_tracker_list_create();
-       if (!lus->tracker_list_vpid) {
+       lus->tracker_vpid = process_attr_tracker_create();
+       if (!lus->tracker_vpid) {
                goto error;
        }
-       lus->tracker_list_vuid = lttng_tracker_list_create();
-       if (!lus->tracker_list_vuid) {
+       lus->tracker_vuid = process_attr_tracker_create();
+       if (!lus->tracker_vuid) {
                goto error;
        }
-       lus->tracker_list_vgid = lttng_tracker_list_create();
-       if (!lus->tracker_list_vgid) {
+       lus->tracker_vgid = process_attr_tracker_create();
+       if (!lus->tracker_vgid) {
                goto error;
        }
        lus->consumer = consumer_create_output(CONSUMER_DST_LOCAL);
@@ -335,10 +371,11 @@ struct ltt_ust_session *trace_ust_create_session(uint64_t session_id)
        return lus;
 
 error:
-       lttng_tracker_list_destroy(lus->tracker_list_vpid);
-       lttng_tracker_list_destroy(lus->tracker_list_vuid);
-       lttng_tracker_list_destroy(lus->tracker_list_vgid);
+       process_attr_tracker_destroy(lus->tracker_vpid);
+       process_attr_tracker_destroy(lus->tracker_vuid);
+       process_attr_tracker_destroy(lus->tracker_vgid);
        ht_cleanup_push(lus->domain_global.channels);
+       ht_cleanup_push(lus->domain_global.maps);
        ht_cleanup_push(lus->agents);
        free(lus);
 error_alloc:
@@ -414,6 +451,67 @@ error:
        return luc;
 }
 
+/*
+ * Allocate and initialize a ust map data structure.
+ *
+ * Return pointer to structure or NULL.
+ */
+struct ltt_ust_map *trace_ust_create_map(const struct lttng_map *map)
+{
+       struct ltt_ust_map *umap = NULL;
+       enum lttng_map_status map_status;
+       const char *map_name = NULL;
+       unsigned int dimension_count;
+       uint64_t dimension_len;
+
+       umap = zmalloc(sizeof(*umap));
+       if (!umap) {
+               PERROR("ltt_ust_map zmalloc");
+               goto end;
+       }
+
+       map_status = lttng_map_get_name(map, &map_name);
+       if (map_status != LTTNG_MAP_STATUS_OK) {
+               ERR("Can't get map name");
+               umap = NULL;
+               goto end;
+       }
+
+       dimension_count = lttng_map_get_dimension_count(map);
+       assert(dimension_count == 1);
+
+       map_status = lttng_map_get_dimension_length(map, 0, &dimension_len);
+       if (map_status != LTTNG_MAP_STATUS_OK) {
+               ERR("Can't get map first dimension length");
+               umap = NULL;
+               goto end;
+       }
+       assert(dimension_len > 0);
+
+       strncpy(umap->name, map_name, sizeof(umap->name));
+
+       umap->enabled = 1;
+       umap->bucket_count = dimension_len;
+       umap->coalesce_hits = lttng_map_get_coalesce_hits(map);
+       umap->bitness = lttng_map_get_bitness(map);
+       umap->nr_cpu = ustctl_get_nr_cpu_per_counter();
+
+       umap->dead_app_kv_values.dead_app_kv_values_32bits = lttng_ht_new(0,
+                       LTTNG_HT_TYPE_STRING);
+       umap->dead_app_kv_values.dead_app_kv_values_64bits = lttng_ht_new(0,
+                       LTTNG_HT_TYPE_STRING);
+       pthread_mutex_init(&umap->dead_app_kv_values.lock, NULL);
+
+       umap->events = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
+
+       /* Init node */
+       lttng_ht_node_init_str(&umap->node, umap->name);
+
+       DBG2("Trace UST map %s created", umap->name);
+end:
+       return umap;
+}
+
 /*
  * Validates an exclusion list.
  *
@@ -453,9 +551,14 @@ end:
  *
  * Return an lttng_error_code
  */
-enum lttng_error_code trace_ust_create_event(struct lttng_event *ev,
+enum lttng_error_code trace_ust_create_event(uint64_t tracer_token,
+               const char *ev_name,
+               struct lttng_map_key *key,
+               enum lttng_event_type ev_type,
+               enum lttng_loglevel_type ev_loglevel_type,
+               enum lttng_loglevel ev_loglevel,
                char *filter_expression,
-               struct lttng_filter_bytecode *filter,
+               struct lttng_bytecode *filter,
                struct lttng_event_exclusion *exclusion,
                bool internal_event,
                struct ltt_ust_event **ust_event)
@@ -463,8 +566,6 @@ enum lttng_error_code trace_ust_create_event(struct lttng_event *ev,
        struct ltt_ust_event *local_ust_event;
        enum lttng_error_code ret = LTTNG_OK;
 
-       assert(ev);
-
        if (exclusion && validate_exclusion(exclusion)) {
                ret = LTTNG_ERR_INVALID;
                goto error;
@@ -478,8 +579,9 @@ enum lttng_error_code trace_ust_create_event(struct lttng_event *ev,
        }
 
        local_ust_event->internal = internal_event;
+       local_ust_event->attr.token = tracer_token;
 
-       switch (ev->type) {
+       switch (ev_type) {
        case LTTNG_EVENT_PROBE:
                local_ust_event->attr.instrumentation = LTTNG_UST_PROBE;
                break;
@@ -493,44 +595,53 @@ enum lttng_error_code trace_ust_create_event(struct lttng_event *ev,
                local_ust_event->attr.instrumentation = LTTNG_UST_TRACEPOINT;
                break;
        default:
-               ERR("Unknown ust instrumentation type (%d)", ev->type);
+               ERR("Unknown ust instrumentation type (%d)", ev_type);
                ret = LTTNG_ERR_INVALID;
                goto error_free_event;
        }
 
        /* Copy event name */
-       strncpy(local_ust_event->attr.name, ev->name, LTTNG_UST_SYM_NAME_LEN);
+       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) {
+       switch (ev_loglevel_type) {
        case LTTNG_EVENT_LOGLEVEL_ALL:
                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:
                local_ust_event->attr.loglevel_type = LTTNG_UST_LOGLEVEL_RANGE;
-               local_ust_event->attr.loglevel = ev->loglevel;
+               local_ust_event->attr.loglevel = ev_loglevel;
                break;
        case LTTNG_EVENT_LOGLEVEL_SINGLE:
                local_ust_event->attr.loglevel_type = LTTNG_UST_LOGLEVEL_SINGLE;
-               local_ust_event->attr.loglevel = ev->loglevel;
+               local_ust_event->attr.loglevel = ev_loglevel;
                break;
        default:
-               ERR("Unknown ust loglevel type (%d)", ev->loglevel_type);
+               ERR("Unknown ust loglevel type (%d)", ev_loglevel_type);
                ret = LTTNG_ERR_INVALID;
                goto error_free_event;
        }
 
        /* Same layout. */
+       local_ust_event->key = key;
        local_ust_event->filter_expression = filter_expression;
        local_ust_event->filter = filter;
        local_ust_event->exclusion = exclusion;
 
+       /* Take a reference on the lttng_map_key to bounds its lifetime to the
+        * ust_event.
+        */
+       if (key) {
+               lttng_map_key_get(key);
+       }
+
        /* Init node */
        lttng_ht_node_init_str(&local_ust_event->node, local_ust_event->attr.name);
 
-       DBG2("Trace UST event %s, loglevel (%d,%d) created",
-               local_ust_event->attr.name, local_ust_event->attr.loglevel_type,
+       DBG2("Trace UST event %s, tracer token %"PRIu64", loglevel (%d,%d) created",
+               local_ust_event->attr.name, local_ust_event->attr.token,
+               local_ust_event->attr.loglevel_type,
                local_ust_event->attr.loglevel);
 
        *ust_event = local_ust_event;
@@ -594,6 +705,9 @@ int trace_ust_context_type_event_to_ust(
        case LTTNG_EVENT_CONTEXT_PID_NS:
                utype = LTTNG_UST_CONTEXT_PID_NS;
                break;
+       case LTTNG_EVENT_CONTEXT_TIME_NS:
+               utype = LTTNG_UST_CONTEXT_TIME_NS;
+               break;
        case LTTNG_EVENT_CONTEXT_USER_NS:
                utype = LTTNG_UST_CONTEXT_USER_NS;
                break;
@@ -814,7 +928,7 @@ static int id_tracker_add_id(struct ust_id_tracker *id_tracker, int id)
        tracker_node = id_tracker_lookup(id_tracker, id, &iter);
        if (tracker_node) {
                /* Already exists. */
-               retval = LTTNG_ERR_ID_TRACKED;
+               retval = LTTNG_ERR_PROCESS_ATTR_EXISTS;
                goto end;
        }
        tracker_node = zmalloc(sizeof(*tracker_node));
@@ -841,7 +955,7 @@ static int id_tracker_del_id(struct ust_id_tracker *id_tracker, int id)
        tracker_node = id_tracker_lookup(id_tracker, id, &iter);
        if (!tracker_node) {
                /* Not found */
-               retval = LTTNG_ERR_ID_NOT_TRACKED;
+               retval = LTTNG_ERR_PROCESS_ATTR_MISSING;
                goto end;
        }
        ret = lttng_ht_del(id_tracker->ht, &iter);
@@ -853,47 +967,56 @@ end:
 }
 
 static struct ust_id_tracker *get_id_tracker(struct ltt_ust_session *session,
-               enum lttng_tracker_type tracker_type)
+               enum lttng_process_attr process_attr)
 {
-       switch (tracker_type) {
-       case LTTNG_TRACKER_VPID:
+       switch (process_attr) {
+       case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
                return &session->vpid_tracker;
-       case LTTNG_TRACKER_VUID:
+       case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
                return &session->vuid_tracker;
-       case LTTNG_TRACKER_VGID:
+       case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
                return &session->vgid_tracker;
        default:
                return NULL;
        }
 }
 
-static struct lttng_tracker_list *get_id_tracker_list(
+static struct process_attr_tracker *_trace_ust_get_process_attr_tracker(
                struct ltt_ust_session *session,
-               enum lttng_tracker_type tracker_type)
+               enum lttng_process_attr process_attr)
 {
-       switch (tracker_type) {
-       case LTTNG_TRACKER_VPID:
-               return session->tracker_list_vpid;
-       case LTTNG_TRACKER_VUID:
-               return session->tracker_list_vuid;
-       case LTTNG_TRACKER_VGID:
-               return session->tracker_list_vgid;
+       switch (process_attr) {
+       case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
+               return session->tracker_vpid;
+       case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
+               return session->tracker_vuid;
+       case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
+               return session->tracker_vgid;
        default:
                return NULL;
        }
 }
 
+const struct process_attr_tracker *trace_ust_get_process_attr_tracker(
+               struct ltt_ust_session *session,
+               enum lttng_process_attr process_attr)
+{
+       return (const struct process_attr_tracker *)
+                       _trace_ust_get_process_attr_tracker(
+                                       session, process_attr);
+}
+
 /*
  * The session lock is held when calling this function.
  */
-int trace_ust_id_tracker_lookup(enum lttng_tracker_type tracker_type,
+int trace_ust_id_tracker_lookup(enum lttng_process_attr process_attr,
                struct ltt_ust_session *session,
                int id)
 {
        struct lttng_ht_iter iter;
        struct ust_id_tracker *id_tracker;
 
-       id_tracker = get_id_tracker(session, tracker_type);
+       id_tracker = get_id_tracker(session, process_attr);
        if (!id_tracker) {
                abort();
        }
@@ -909,226 +1032,285 @@ int trace_ust_id_tracker_lookup(enum lttng_tracker_type tracker_type,
 /*
  * Called with the session lock held.
  */
-int trace_ust_track_id(enum lttng_tracker_type tracker_type,
+enum lttng_error_code trace_ust_process_attr_tracker_set_tracking_policy(
                struct ltt_ust_session *session,
-               const struct lttng_tracker_id *id)
+               enum lttng_process_attr process_attr,
+               enum lttng_tracking_policy policy)
 {
-       int retval = LTTNG_OK;
+       int ret;
+       enum lttng_error_code ret_code = LTTNG_OK;
+       struct ust_id_tracker *id_tracker =
+                       get_id_tracker(session, process_attr);
+       struct process_attr_tracker *tracker =
+                       _trace_ust_get_process_attr_tracker(
+                                       session, process_attr);
        bool should_update_apps = false;
-       struct ust_id_tracker *id_tracker;
-       struct lttng_tracker_list *tracker_list;
-       int value;
-       struct lttng_tracker_id **saved_ids;
-       ssize_t saved_ids_count;
+       enum lttng_tracking_policy previous_policy;
 
-       if (tracker_type == LTTNG_TRACKER_PID) {
-               DBG("Backward compatible behavior: translate PID tracker to VPID tracker for UST domain.");
-               tracker_type = LTTNG_TRACKER_VPID;
+       if (!tracker) {
+               ret_code = LTTNG_ERR_INVALID;
+               goto end;
        }
 
-       retval = lttng_tracker_id_lookup_string(tracker_type, id, &value);
-       if (retval != LTTNG_OK) {
-               return retval;
-       }
-       tracker_list = get_id_tracker_list(session, tracker_type);
-       if (!tracker_list) {
-               return LTTNG_ERR_INVALID;
-       }
-       /* Save list for restore on error. */
-       saved_ids_count = lttng_tracker_id_get_list(tracker_list, &saved_ids);
-       if (saved_ids_count < 0) {
-               return LTTNG_ERR_INVALID;
-       }
-       /* Add to list. */
-       retval = lttng_tracker_list_add(tracker_list, id);
-       if (retval != LTTNG_OK) {
+       previous_policy = process_attr_tracker_get_tracking_policy(tracker);
+       ret = process_attr_tracker_set_tracking_policy(tracker, policy);
+       if (ret) {
+               ret_code = LTTNG_ERR_UNK;
                goto end;
        }
 
-       id_tracker = get_id_tracker(session, tracker_type);
-       if (!id_tracker) {
-               abort();
+       if (previous_policy == policy) {
+               goto end;
        }
-       if (value == -1) {
-               /* Track all ids: destroy tracker if exists. */
+
+       switch (policy) {
+       case LTTNG_TRACKING_POLICY_INCLUDE_ALL:
+               /* Track all values: destroy tracker if exists. */
                if (id_tracker->ht) {
                        fini_id_tracker(id_tracker);
                        /* Ensure all apps have session. */
                        should_update_apps = true;
                }
-       } else {
-               if (!id_tracker->ht) {
-                       /* Create tracker. */
-                       retval = init_id_tracker(id_tracker);
-                       if (retval != LTTNG_OK) {
-                               ERR("Error initializing ID tracker");
-                               goto end_restore;
-                       }
-                       retval = id_tracker_add_id(id_tracker, value);
-                       if (retval != LTTNG_OK) {
-                               fini_id_tracker(id_tracker);
-                               goto end_restore;
-                       }
-                       /* Remove all apps from session except pid. */
-                       should_update_apps = true;
-               } else {
-                       struct ust_app *app;
-
-                       retval = id_tracker_add_id(id_tracker, value);
-                       if (retval != LTTNG_OK) {
-                               goto end_restore;
-                       }
-                       /* Add session to application */
-                       switch (tracker_type) {
-                       case LTTNG_TRACKER_VPID:
-                               app = ust_app_find_by_pid(value);
-                               if (app) {
-                                       should_update_apps = true;
-                               }
-                               break;
-                       default:
-                               should_update_apps = true;
-                       }
+               break;
+       case LTTNG_TRACKING_POLICY_EXCLUDE_ALL:
+       case LTTNG_TRACKING_POLICY_INCLUDE_SET:
+               /* fall-through. */
+               fini_id_tracker(id_tracker);
+               ret_code = init_id_tracker(id_tracker);
+               if (ret_code != LTTNG_OK) {
+                       ERR("Error initializing ID tracker");
+                       goto end;
                }
+               /* Remove all apps from session. */
+               should_update_apps = true;
+               break;
+       default:
+               abort();
        }
        if (should_update_apps && session->active) {
                ust_app_global_update_all(session);
        }
-       goto end;
-
-end_restore:
-       if (lttng_tracker_id_set_list(tracker_list, saved_ids,
-                           saved_ids_count) != LTTNG_OK) {
-               ERR("Error on tracker add error handling.\n");
-       }
 end:
-       lttng_tracker_ids_destroy(saved_ids, saved_ids_count);
-       free(saved_ids);
-       return retval;
+       return ret_code;
 }
 
-/*
- * Called with the session lock held.
- */
-int trace_ust_untrack_id(enum lttng_tracker_type tracker_type,
+/* Called with the session lock held. */
+enum lttng_error_code trace_ust_process_attr_tracker_inclusion_set_add_value(
                struct ltt_ust_session *session,
-               const struct lttng_tracker_id *id)
+               enum lttng_process_attr process_attr,
+               const struct process_attr_value *value)
 {
-       int retval = LTTNG_OK;
+       enum lttng_error_code ret_code = LTTNG_OK;
        bool should_update_apps = false;
-       struct ust_id_tracker *id_tracker;
-       struct lttng_tracker_list *tracker_list;
-       int value;
-       struct lttng_tracker_id **saved_ids;
-       ssize_t saved_ids_count;
-
-       if (tracker_type == LTTNG_TRACKER_PID) {
-               DBG("Backward compatible behavior: translate PID tracker to VPID tracker for UST domain.");
-               tracker_type = LTTNG_TRACKER_VPID;
-       }
+       struct ust_id_tracker *id_tracker =
+                       get_id_tracker(session, process_attr);
+       struct process_attr_tracker *tracker;
+       int integral_value;
+       enum process_attr_tracker_status status;
+       struct ust_app *app;
 
-       retval = lttng_tracker_id_lookup_string(tracker_type, id, &value);
-       if (retval != LTTNG_OK) {
-               return retval;
-       }
-
-       tracker_list = get_id_tracker_list(session, tracker_type);
-       if (!tracker_list) {
-               return LTTNG_ERR_INVALID;
-       }
-       /* Save list for restore on error. */
-       saved_ids_count = lttng_tracker_id_get_list(tracker_list, &saved_ids);
-       if (saved_ids_count < 0) {
-               return LTTNG_ERR_INVALID;
-       }
-       /* Remove from list. */
-       retval = lttng_tracker_list_remove(tracker_list, id);
-       if (retval != LTTNG_OK) {
+       /*
+        * Convert process attribute tracker value to the integral
+        * representation required by the kern-ctl API.
+        */
+       switch (process_attr) {
+       case LTTNG_PROCESS_ATTR_PROCESS_ID:
+       case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
+               integral_value = (int) value->value.pid;
+               break;
+       case LTTNG_PROCESS_ATTR_USER_ID:
+       case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
+               if (value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME) {
+                       uid_t uid;
+
+                       ret_code = utils_user_id_from_name(
+                                       value->value.user_name, &uid);
+                       if (ret_code != LTTNG_OK) {
+                               goto end;
+                       }
+                       integral_value = (int) uid;
+               } else {
+                       integral_value = (int) value->value.uid;
+               }
+               break;
+       case LTTNG_PROCESS_ATTR_GROUP_ID:
+       case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
+               if (value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME) {
+                       gid_t gid;
+
+                       ret_code = utils_group_id_from_name(
+                                       value->value.group_name, &gid);
+                       if (ret_code != LTTNG_OK) {
+                               goto end;
+                       }
+                       integral_value = (int) gid;
+               } else {
+                       integral_value = (int) value->value.gid;
+               }
+               break;
+       default:
+               ret_code = LTTNG_ERR_INVALID;
                goto end;
        }
 
-       id_tracker = get_id_tracker(session, tracker_type);
-       if (!id_tracker) {
-               abort();
+       tracker = _trace_ust_get_process_attr_tracker(session, process_attr);
+       if (!tracker) {
+               ret_code = LTTNG_ERR_INVALID;
+               goto end;
        }
 
-       if (value == -1) {
-               /* Create empty tracker, replace old tracker. */
-               struct ust_id_tracker tmp_tracker;
-
-               tmp_tracker = *id_tracker;
-               retval = init_id_tracker(id_tracker);
-               if (retval != LTTNG_OK) {
-                       ERR("Error initializing ID tracker");
-                       /* Rollback operation. */
-                       *id_tracker = tmp_tracker;
-                       goto end_restore;
+       status = process_attr_tracker_inclusion_set_add_value(tracker, value);
+       if (status != PROCESS_ATTR_TRACKER_STATUS_OK) {
+               switch (status) {
+               case PROCESS_ATTR_TRACKER_STATUS_EXISTS:
+                       ret_code = LTTNG_ERR_PROCESS_ATTR_EXISTS;
+                       break;
+               case PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY:
+                       ret_code = LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY;
+                       break;
+               case PROCESS_ATTR_TRACKER_STATUS_ERROR:
+               default:
+                       ret_code = LTTNG_ERR_UNK;
+                       break;
                }
-               fini_id_tracker(&tmp_tracker);
+               goto end;
+       }
 
-               /* Remove session from all applications */
-               should_update_apps = true;
-       } else {
-               struct ust_app *app;
+       DBG("User space track %s %d for session id %" PRIu64,
+                       lttng_process_attr_to_string(process_attr),
+                       integral_value, session->id);
 
-               if (!id_tracker->ht) {
-                       /* No ID being tracked. */
-                       retval = LTTNG_ERR_ID_NOT_TRACKED;
-                       goto end_restore;
-               }
-               /* Remove ID from tracker */
-               retval = id_tracker_del_id(id_tracker, value);
-               if (retval != LTTNG_OK) {
-                       goto end_restore;
-               }
-               switch (tracker_type) {
-               case LTTNG_TRACKER_VPID:
-                       /* Remove session from application. */
-                       app = ust_app_find_by_pid(value);
-                       if (app) {
-                               should_update_apps = true;
-                       }
-                       break;
-               default:
-                       /* Keep only apps matching ID. */
+       ret_code = id_tracker_add_id(id_tracker, integral_value);
+       if (ret_code != LTTNG_OK) {
+               goto end;
+       }
+       /* Add session to application */
+       switch (process_attr) {
+       case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
+               app = ust_app_find_by_pid(integral_value);
+               if (app) {
                        should_update_apps = true;
                }
+               break;
+       default:
+               should_update_apps = true;
+               break;
        }
        if (should_update_apps && session->active) {
                ust_app_global_update_all(session);
        }
-       goto end;
-
-end_restore:
-       if (lttng_tracker_id_set_list(tracker_list, saved_ids,
-                           saved_ids_count) != LTTNG_OK) {
-               ERR("Error on tracker remove error handling.\n");
-       }
 end:
-       lttng_tracker_ids_destroy(saved_ids, saved_ids_count);
-       free(saved_ids);
-       return retval;
+       return ret_code;
 }
 
-/*
- * Called with session lock held.
- */
-ssize_t trace_ust_list_tracker_ids(enum lttng_tracker_type tracker_type,
+/* Called with the session lock held. */
+enum lttng_error_code trace_ust_process_attr_tracker_inclusion_set_remove_value(
                struct ltt_ust_session *session,
-               struct lttng_tracker_id ***_ids)
+               enum lttng_process_attr process_attr,
+               const struct process_attr_value *value)
 {
-       struct lttng_tracker_list *tracker_list;
+       enum lttng_error_code ret_code = LTTNG_OK;
+       bool should_update_apps = false;
+       struct ust_id_tracker *id_tracker =
+                       get_id_tracker(session, process_attr);
+       struct process_attr_tracker *tracker;
+       int integral_value;
+       enum process_attr_tracker_status status;
+       struct ust_app *app;
 
-       if (tracker_type == LTTNG_TRACKER_PID) {
-               DBG("Backward compatible behavior: translate PID tracker to VPID tracker for UST domain.");
-               tracker_type = LTTNG_TRACKER_VPID;
+       /*
+        * Convert process attribute tracker value to the integral
+        * representation required by the kern-ctl API.
+        */
+       switch (process_attr) {
+       case LTTNG_PROCESS_ATTR_PROCESS_ID:
+       case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
+               integral_value = (int) value->value.pid;
+               break;
+       case LTTNG_PROCESS_ATTR_USER_ID:
+       case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
+               if (value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME) {
+                       uid_t uid;
+
+                       ret_code = utils_user_id_from_name(
+                                       value->value.user_name, &uid);
+                       if (ret_code != LTTNG_OK) {
+                               goto end;
+                       }
+                       integral_value = (int) uid;
+               } else {
+                       integral_value = (int) value->value.uid;
+               }
+               break;
+       case LTTNG_PROCESS_ATTR_GROUP_ID:
+       case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
+               if (value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME) {
+                       gid_t gid;
+
+                       ret_code = utils_group_id_from_name(
+                                       value->value.group_name, &gid);
+                       if (ret_code != LTTNG_OK) {
+                               goto end;
+                       }
+                       integral_value = (int) gid;
+               } else {
+                       integral_value = (int) value->value.gid;
+               }
+               break;
+       default:
+               ret_code = LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       tracker = _trace_ust_get_process_attr_tracker(session, process_attr);
+       if (!tracker) {
+               ret_code = LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       status = process_attr_tracker_inclusion_set_remove_value(
+                       tracker, value);
+       if (status != PROCESS_ATTR_TRACKER_STATUS_OK) {
+               switch (status) {
+               case PROCESS_ATTR_TRACKER_STATUS_MISSING:
+                       ret_code = LTTNG_ERR_PROCESS_ATTR_MISSING;
+                       break;
+               case PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY:
+                       ret_code = LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY;
+                       break;
+               case PROCESS_ATTR_TRACKER_STATUS_ERROR:
+               default:
+                       ret_code = LTTNG_ERR_UNK;
+                       break;
+               }
+               goto end;
        }
 
-       tracker_list = get_id_tracker_list(session, tracker_type);
-       if (!tracker_list) {
-               return -LTTNG_ERR_INVALID;
+       DBG("User space untrack %s %d for session id %" PRIu64,
+                       lttng_process_attr_to_string(process_attr),
+                       integral_value, session->id);
+
+       ret_code = id_tracker_del_id(id_tracker, integral_value);
+       if (ret_code != LTTNG_OK) {
+               goto end;
+       }
+       /* Add session to application */
+       switch (process_attr) {
+       case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
+               app = ust_app_find_by_pid(integral_value);
+               if (app) {
+                       should_update_apps = true;
+               }
+               break;
+       default:
+               should_update_apps = true;
+               break;
+       }
+       if (should_update_apps && session->active) {
+               ust_app_global_update_all(session);
        }
-       return lttng_tracker_id_get_list(tracker_list, _ids);
+end:
+       return ret_code;
 }
 
 /*
@@ -1180,6 +1362,7 @@ void trace_ust_destroy_event(struct ltt_ust_event *event)
        assert(event);
 
        DBG2("Trace destroy UST event %s", event->attr.name);
+       lttng_map_key_put(event->key);
        free(event->filter_expression);
        free(event->filter);
        free(event->exclusion);
@@ -1249,6 +1432,53 @@ static void _trace_ust_destroy_channel(struct ltt_ust_channel *channel)
        free(channel);
 }
 
+/*
+ * Cleanup ust map structure.
+ *
+ * Should _NOT_ be called with RCU read lock held.
+ */
+static void _trace_ust_destroy_map(struct ltt_ust_map *map)
+{
+       struct map_kv_ht_entry *kv_entry;
+       struct lttng_ht_iter ht_iter;
+       struct lttng_ht *dead_app_kv_ht;
+
+       assert(map);
+
+       DBG2("Trace destroy UST map %s", map->name);
+
+       /*
+        * Remove all the keys before destroying the hashtables.
+        */
+       dead_app_kv_ht = map->dead_app_kv_values.dead_app_kv_values_32bits;
+       cds_lfht_for_each_entry(dead_app_kv_ht->ht, &ht_iter.iter, kv_entry, node.node) {
+               struct lttng_ht_iter entry_iter;
+
+               entry_iter.iter.node = &kv_entry->node.node;
+               lttng_ht_del(dead_app_kv_ht, &entry_iter);
+
+               free(kv_entry->key);
+               free(kv_entry);
+       }
+       lttng_ht_destroy(map->dead_app_kv_values.dead_app_kv_values_32bits);
+
+       dead_app_kv_ht = map->dead_app_kv_values.dead_app_kv_values_64bits;
+       cds_lfht_for_each_entry(dead_app_kv_ht->ht, &ht_iter.iter, kv_entry, node.node) {
+               struct lttng_ht_iter entry_iter;
+
+               entry_iter.iter.node = &kv_entry->node.node;
+               lttng_ht_del(dead_app_kv_ht, &entry_iter);
+
+               free(kv_entry->key);
+               free(kv_entry);
+       }
+
+       lttng_ht_destroy(map->dead_app_kv_values.dead_app_kv_values_64bits);
+
+       lttng_map_put(map->map);
+       free(map);
+}
+
 /*
  * URCU intermediate call to complete destroy channel.
  */
@@ -1262,6 +1492,19 @@ static void destroy_channel_rcu(struct rcu_head *head)
        _trace_ust_destroy_channel(channel);
 }
 
+/*
+ * URCU intermediate call to complete destroy map.
+ */
+static void destroy_map_rcu(struct rcu_head *head)
+{
+       struct lttng_ht_node_str *node =
+               caa_container_of(head, struct lttng_ht_node_str, head);
+       struct ltt_ust_map *map =
+               caa_container_of(node, struct ltt_ust_map, node);
+
+       _trace_ust_destroy_map(map);
+}
+
 void trace_ust_destroy_channel(struct ltt_ust_channel *channel)
 {
        /* Destroying all events of the channel */
@@ -1272,6 +1515,14 @@ void trace_ust_destroy_channel(struct ltt_ust_channel *channel)
        call_rcu(&channel->node.head, destroy_channel_rcu);
 }
 
+void trace_ust_destroy_map(struct ltt_ust_map *map)
+{
+       /* Destroying all events of the map */
+       destroy_events(map->events);
+
+       call_rcu(&map->node.head, destroy_map_rcu);
+}
+
 /*
  * Remove an UST channel from a channel HT.
  */
@@ -1289,6 +1540,23 @@ void trace_ust_delete_channel(struct lttng_ht *ht,
        assert(!ret);
 }
 
+/*
+ * Remove an UST map from a map HT.
+ */
+void trace_ust_delete_map(struct lttng_ht *ht,
+               struct ltt_ust_map *map)
+{
+       int ret;
+       struct lttng_ht_iter iter;
+
+       assert(ht);
+       assert(map);
+
+       iter.iter.node = &map->node.node;
+       ret = lttng_ht_del(ht, &iter);
+       assert(!ret);
+}
+
 /*
  * Iterate over a hash table containing channels and cleanup safely.
  */
@@ -1312,6 +1580,28 @@ static void destroy_channels(struct lttng_ht *channels)
        ht_cleanup_push(channels);
 }
 
+/*
+ * Iterate over a hash table containing maps and cleanup safely.
+ */
+static void destroy_maps(struct lttng_ht *maps)
+{
+       struct lttng_ht_node_str *node;
+       struct lttng_ht_iter iter;
+
+       assert(maps);
+
+       rcu_read_lock();
+       cds_lfht_for_each_entry(maps->ht, &iter.iter, node, node) {
+               struct ltt_ust_map *map =
+                       caa_container_of(node, struct ltt_ust_map, node);
+
+               trace_ust_delete_map(maps, map);
+               trace_ust_destroy_map(map);
+       }
+       rcu_read_unlock();
+
+       ht_cleanup_push(maps);
+}
 /*
  * Cleanup UST global domain.
  */
@@ -1320,6 +1610,7 @@ static void destroy_domain_global(struct ltt_ust_domain_global *dom)
        assert(dom);
 
        destroy_channels(dom->channels);
+       destroy_maps(dom->maps);
 }
 
 /*
@@ -1360,9 +1651,9 @@ void trace_ust_destroy_session(struct ltt_ust_session *session)
                buffer_reg_uid_destroy(reg, session->consumer);
        }
 
-       lttng_tracker_list_destroy(session->tracker_list_vpid);
-       lttng_tracker_list_destroy(session->tracker_list_vuid);
-       lttng_tracker_list_destroy(session->tracker_list_vgid);
+       process_attr_tracker_destroy(session->tracker_vpid);
+       process_attr_tracker_destroy(session->tracker_vuid);
+       process_attr_tracker_destroy(session->tracker_vgid);
 
        fini_id_tracker(&session->vpid_tracker);
        fini_id_tracker(&session->vuid_tracker);
This page took 0.048079 seconds and 5 git commands to generate.