Add base support for event rule hit
authorJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Mon, 17 Aug 2020 22:23:27 +0000 (18:23 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 11 Dec 2020 17:10:39 +0000 (12:10 -0500)
Add some of the scafolding to support event-rule hit conditions.
This includes the hashing of event rule conditions and, consequently,
of event rules and the various probe location types.

The kernel module ABI is checked to verity that the kernel tracer
supports event notifiers.

Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Change-Id: Iab4db4fc7e9f0c5a7206106fa6a4781b6b95d306

13 files changed:
include/lttng/event-rule/event-rule-internal.h
include/lttng/kernel-probe-internal.h
include/lttng/userspace-probe-internal.h
src/bin/lttng-sessiond/kernel.c
src/bin/lttng-sessiond/kernel.h
src/bin/lttng-sessiond/notification-thread-events.c
src/common/event-rule/event-rule.c
src/common/event-rule/kprobe.c
src/common/event-rule/syscall.c
src/common/event-rule/tracepoint.c
src/common/event-rule/uprobe.c
src/common/kernel-probe.c
src/common/userspace-probe.c

index 7aca4a02ba62098be6d6fe271bc151920ddc82e3..ea0f46e480ec3f2d1454de147708a4607092d49e 100644 (file)
@@ -42,6 +42,8 @@ typedef const struct lttng_filter_bytecode *(
                const struct lttng_event_rule *event_rule);
 typedef struct lttng_event_exclusion *(*event_rule_generate_exclusions_cb)(
                const struct lttng_event_rule *event_rule);
+typedef unsigned long (*event_rule_hash_cb)(
+               const struct lttng_event_rule *event_rule);
 
 struct lttng_event_rule {
        struct urcu_ref ref;
@@ -54,6 +56,7 @@ struct lttng_event_rule {
        event_rule_get_filter_cb get_filter;
        event_rule_get_filter_bytecode_cb get_filter_bytecode;
        event_rule_generate_exclusions_cb generate_exclusions;
+       event_rule_hash_cb hash;
 };
 
 struct lttng_event_rule_comm {
@@ -123,4 +126,7 @@ struct lttng_event_exclusion *lttng_event_rule_generate_exclusions(
 LTTNG_HIDDEN
 const char *lttng_event_rule_type_str(enum lttng_event_rule_type type);
 
+LTTNG_HIDDEN
+unsigned long lttng_event_rule_hash(const struct lttng_event_rule *rule);
+
 #endif /* LTTNG_EVENT_RULE_INTERNAL_H */
index 381c6a411e7dddf8225c415880fee3738812e4a0..e2889fd78d2b04d034505d806486ba12c78d7ce0 100644 (file)
@@ -31,6 +31,8 @@ typedef bool (*kernel_probe_location_equal_cb)(
 typedef ssize_t (*kernel_probe_location_create_from_payload_cb)(
                struct lttng_payload_view *view,
                struct lttng_kernel_probe_location **kernel_probe_location);
+typedef unsigned long (*kernel_probe_location_hash_cb)(
+               const struct lttng_kernel_probe_location *location);
 
 struct lttng_kernel_probe_location_comm {
        /* enum lttng_kernel_probe_location_type */
@@ -63,6 +65,7 @@ struct lttng_kernel_probe_location {
        enum lttng_kernel_probe_location_type type;
        kernel_probe_location_equal_cb equal;
        kernel_probe_location_serialize_cb serialize;
+       kernel_probe_location_hash_cb hash;
 };
 
 struct lttng_kernel_probe_location_symbol {
@@ -95,4 +98,8 @@ LTTNG_HIDDEN
 struct lttng_kernel_probe_location *lttng_kernel_probe_location_copy(
                const struct lttng_kernel_probe_location *location);
 
+LTTNG_HIDDEN
+unsigned long lttng_kernel_probe_location_hash(
+               const struct lttng_kernel_probe_location *location);
+
 #endif /* LTTNG_KERNEL_PROBE_INTERNAL_H */
index e602a64e748bccee6fa91aaa230b60f8aee66799..b530e2963b70dfe4a2e9155e8754bbe0fd0b951c 100644 (file)
@@ -21,6 +21,8 @@ struct lttng_dynamic_buffer;
 typedef bool (*userspace_probe_location_equal_cb)(
                const struct lttng_userspace_probe_location *a,
                const struct lttng_userspace_probe_location *b);
+typedef unsigned long (*userspace_probe_location_hash_cb)(
+               const struct lttng_userspace_probe_location *location);
 
 /*
  * No elf-specific comm structure is defined since no elf-specific payload is
@@ -88,6 +90,7 @@ struct lttng_userspace_probe_location {
        enum lttng_userspace_probe_location_type type;
        struct lttng_userspace_probe_location_lookup_method *lookup_method;
        userspace_probe_location_equal_cb equal;
+       userspace_probe_location_hash_cb hash;
 };
 
 struct lttng_userspace_probe_location_function {
@@ -150,4 +153,8 @@ bool lttng_userspace_probe_location_is_equal(
                const struct lttng_userspace_probe_location *a,
                const struct lttng_userspace_probe_location *b);
 
+LTTNG_HIDDEN
+unsigned long lttng_userspace_probe_location_hash(
+               const struct lttng_userspace_probe_location *location);
+
 #endif /* LTTNG_USERSPACE_PROBE_INTERNAL_H */
index d7c7984d201ba96c82d050eb71a48dca798c8e38..d93478edf86c706b1dea1d710cb786fe621667e6 100644 (file)
@@ -1641,16 +1641,10 @@ int kernel_syscall_mask(int chan_fd, char **syscall_mask, uint32_t *nr_bits)
        return kernctl_syscall_mask(chan_fd, syscall_mask, nr_bits);
 }
 
-/*
- * Check for the support of the RING_BUFFER_SNAPSHOT_SAMPLE_POSITIONS via abi
- * version number.
- *
- * Return 1 on success, 0 when feature is not supported, negative value in case
- * of errors.
- */
-int kernel_supports_ring_buffer_snapshot_sample_positions(void)
+static
+int kernel_tracer_abi_greater_or_equal(unsigned int major, unsigned int minor)
 {
-       int ret = 0; // Not supported by default
+       int ret;
        struct lttng_kernel_tracer_abi_version abi;
 
        ret = kernctl_tracer_abi_version(kernel_tracer_fd, &abi);
@@ -1659,18 +1653,24 @@ int kernel_supports_ring_buffer_snapshot_sample_positions(void)
                goto error;
        }
 
+       ret = abi.major > major || (abi.major == major && abi.minor >= minor);
+error:
+       return ret;
+}
+
+/*
+ * Check for the support of the RING_BUFFER_SNAPSHOT_SAMPLE_POSITIONS via abi
+ * version number.
+ *
+ * Return 1 on success, 0 when feature is not supported, negative value in case
+ * of errors.
+ */
+int kernel_supports_ring_buffer_snapshot_sample_positions(void)
+{
        /*
         * RING_BUFFER_SNAPSHOT_SAMPLE_POSITIONS was introduced in 2.3
         */
-       if (abi.major >= 2 && abi.minor >= 3) {
-               /* Supported */
-               ret = 1;
-       } else {
-               /* Not supported */
-               ret = 0;
-       }
-error:
-       return ret;
+       return kernel_tracer_abi_greater_or_equal(2, 3);
 }
 
 /*
@@ -1681,28 +1681,25 @@ error:
  */
 int kernel_supports_ring_buffer_packet_sequence_number(void)
 {
-       int ret = 0; // Not supported by default
-       struct lttng_kernel_tracer_abi_version abi;
-
-       ret = kernctl_tracer_abi_version(kernel_tracer_fd, &abi);
-       if (ret < 0) {
-               ERR("Failed to retrieve lttng-modules ABI version");
-               goto error;
-       }
-
        /*
         * Packet sequence number was introduced in LTTng 2.8,
         * lttng-modules ABI 2.1.
         */
-       if (abi.major >= 2 && abi.minor >= 1) {
-               /* Supported */
-               ret = 1;
-       } else {
-               /* Not supported */
-               ret = 0;
-       }
-error:
-       return ret;
+       return kernel_tracer_abi_greater_or_equal(2, 1);
+}
+
+/*
+ * Check for the support of event notifiers via abi version number.
+ *
+ * Return 1 on success, 0 when feature is not supported, negative value in case
+ * of errors.
+ */
+int kernel_supports_event_notifiers(void)
+{
+       /*
+        * Event notifiers were introduced in LTTng 2.13, lttng-modules ABI 2.6.
+        */
+       return kernel_tracer_abi_greater_or_equal(2, 6);
 }
 
 /*
index 53d480313ad456d63e8cecb869876ac78dc2d117..1adf692530cbc7668c416e298c6b046e4f9c4db0 100644 (file)
@@ -74,6 +74,7 @@ enum lttng_error_code kernel_clear_session(struct ltt_session *session);
 int init_kernel_workarounds(void);
 int kernel_supports_ring_buffer_snapshot_sample_positions(void);
 int kernel_supports_ring_buffer_packet_sequence_number(void);
+int kernel_supports_event_notifiers(void);
 int init_kernel_tracer(void);
 void cleanup_kernel_tracer(void);
 bool kernel_tracer_is_initialized(void);
index a1af9c53526367018c774447837e352f2f349353..5956d53ca9e6f0c4e3006ac456979a621bf5f7e6 100644 (file)
 #include <lttng/condition/buffer-usage-internal.h>
 #include <lttng/condition/session-consumed-size-internal.h>
 #include <lttng/condition/session-rotation-internal.h>
+#include <lttng/condition/event-rule-internal.h>
 #include <lttng/notification/channel-internal.h>
 #include <lttng/trigger/trigger-internal.h>
+#include <lttng/event-rule/event-rule-internal.h>
 
 #include <time.h>
 #include <unistd.h>
@@ -444,6 +446,24 @@ unsigned long lttng_condition_session_rotation_hash(
        return hash;
 }
 
+static
+unsigned long lttng_condition_event_rule_hash(
+       const struct lttng_condition *condition)
+{
+       unsigned long hash, condition_type;
+       enum lttng_condition_status condition_status;
+       const struct lttng_event_rule *event_rule;
+
+       condition_type = (unsigned long) condition->type;
+
+       condition_status = lttng_condition_event_rule_get_rule(condition,
+                                                              &event_rule);
+       assert(condition_status == LTTNG_CONDITION_STATUS_OK);
+
+       hash = hash_key_ulong((void *) condition_type, lttng_ht_seed);
+       return hash ^ lttng_event_rule_hash(event_rule);
+}
+
 /*
  * The lttng_condition hashing code is kept in this file (rather than
  * condition.c) since it makes use of GPLv2 code (hashtable utils), which we
@@ -461,6 +481,8 @@ unsigned long lttng_condition_hash(const struct lttng_condition *condition)
        case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
        case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
                return lttng_condition_session_rotation_hash(condition);
+       case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT:
+               return lttng_condition_event_rule_hash(condition);
        default:
                ERR("[notification-thread] Unexpected condition type caught");
                abort();
@@ -509,6 +531,8 @@ enum lttng_object_type get_condition_binding_object(
        case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
        case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
                return LTTNG_OBJECT_TYPE_SESSION;
+       case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT:
+               return LTTNG_OBJECT_TYPE_NONE;
        default:
                return LTTNG_OBJECT_TYPE_UNKNOWN;
        }
@@ -2040,25 +2064,23 @@ end:
 }
 
 static
-int condition_is_supported(struct lttng_condition *condition)
+bool condition_is_supported(struct lttng_condition *condition)
 {
-       int ret;
+       bool is_supported;
 
        switch (lttng_condition_get_type(condition)) {
        case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
        case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
        {
+               int ret;
                enum lttng_domain_type domain;
 
                ret = lttng_condition_buffer_usage_get_domain_type(condition,
                                &domain);
-               if (ret) {
-                       ret = -1;
-                       goto end;
-               }
+               assert(ret == 0);
 
                if (domain != LTTNG_DOMAIN_KERNEL) {
-                       ret = 1;
+                       is_supported = true;
                        goto end;
                }
 
@@ -2066,15 +2088,43 @@ int condition_is_supported(struct lttng_condition *condition)
                 * Older kernel tracers don't expose the API to monitor their
                 * buffers. Therefore, we reject triggers that require that
                 * mechanism to be available to be evaluated.
+                *
+                * Assume unsupported on error.
                 */
-               ret = kernel_supports_ring_buffer_snapshot_sample_positions();
+               is_supported = kernel_supports_ring_buffer_snapshot_sample_positions() == 1;
+               break;
+       }
+       case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT:
+       {
+               const struct lttng_event_rule *event_rule;
+               enum lttng_domain_type domain;
+               const enum lttng_condition_status status =
+                               lttng_condition_event_rule_get_rule(
+                                               condition, &event_rule);
+
+               assert(status == LTTNG_CONDITION_STATUS_OK);
+
+               domain = lttng_event_rule_get_domain_type(event_rule);
+               if (domain != LTTNG_DOMAIN_KERNEL) {
+                       is_supported = true;
+                       goto end;
+               }
+
+               /*
+                * Older kernel tracers can't emit notification. Therefore, we
+                * reject triggers that require that mechanism to be available
+                * to be evaluated.
+                *
+                * Assume unsupported on error.
+                */
+               is_supported = kernel_supports_event_notifiers() == 1;
                break;
        }
        default:
-               ret = 1;
+               is_supported = true;
        }
 end:
-       return ret;
+       return is_supported;
 }
 
 /* Must be called with RCU read lock held. */
@@ -2316,15 +2366,10 @@ int handle_notification_thread_command_register_trigger(
        condition = lttng_trigger_get_condition(trigger);
        assert(condition);
 
-       ret = condition_is_supported(condition);
-       if (ret < 0) {
-               goto error;
-       } else if (ret == 0) {
+       /* Some conditions require tracers to implement a minimal ABI version. */
+       if (!condition_is_supported(condition)) {
                *cmd_result = LTTNG_ERR_NOT_SUPPORTED;
                goto error;
-       } else {
-               /* Feature is supported, continue. */
-               ret = 0;
        }
 
        trigger_ht_element = zmalloc(sizeof(*trigger_ht_element));
index 627674ba90026a84cb912aa407b2a4909465f8e0..a42d5555c409eff5e0693becd92b55a6ea1cb2dc 100644 (file)
@@ -11,6 +11,8 @@
 #include <common/macros.h>
 #include <common/payload.h>
 #include <common/payload-view.h>
+#include <common/hashtable/hashtable.h>
+#include <common/hashtable/utils.h>
 #include <lttng/event-rule/event-rule-internal.h>
 #include <lttng/event-rule/kprobe-internal.h>
 #include <lttng/event-rule/syscall-internal.h>
@@ -292,3 +294,10 @@ const char *lttng_event_rule_type_str(enum lttng_event_rule_type type)
                abort();
        }
 }
+
+LTTNG_HIDDEN
+unsigned long lttng_event_rule_hash(const struct lttng_event_rule *rule)
+{
+       assert(rule->hash);
+       return rule->hash(rule);
+}
index 6846f0cb16a2b664c4635227b09d4b2ee58535b9..15dabdde3d0ceca5e8f334c20255ba1132999d83 100644 (file)
@@ -12,6 +12,8 @@
 #include <common/payload.h>
 #include <common/payload-view.h>
 #include <common/runas.h>
+#include <common/hashtable/hashtable.h>
+#include <common/hashtable/utils.h>
 #include <ctype.h>
 #include <lttng/constant.h>
 #include <lttng/event-rule/event-rule-internal.h>
@@ -175,6 +177,22 @@ lttng_event_rule_kprobe_generate_exclusions(const struct lttng_event_rule *rule)
        return NULL;
 }
 
+static unsigned long
+lttng_event_rule_kprobe_hash(
+               const struct lttng_event_rule *rule)
+{
+       unsigned long hash;
+       struct lttng_event_rule_kprobe *krule =
+                       container_of(rule, typeof(*krule), parent);
+
+       hash = hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_KPROBE,
+                       lttng_ht_seed);
+       hash ^= hash_key_str(krule->name, lttng_ht_seed);
+       hash ^= lttng_kernel_probe_location_hash(krule->location);
+
+       return hash;
+}
+
 struct lttng_event_rule *lttng_event_rule_kprobe_create()
 {
        struct lttng_event_rule *rule = NULL;
@@ -198,6 +216,7 @@ struct lttng_event_rule *lttng_event_rule_kprobe_create()
                        lttng_event_rule_kprobe_get_filter_bytecode;
        krule->parent.generate_exclusions =
                        lttng_event_rule_kprobe_generate_exclusions;
+       krule->parent.hash = lttng_event_rule_kprobe_hash;
 end:
        return rule;
 }
index b2feb2c6ecf4c772049d9c41d304544f185959d1..51f22fcc0ff85602d680f5216d790dc48f1c38a8 100644 (file)
@@ -12,6 +12,8 @@
 #include <common/payload.h>
 #include <common/payload-view.h>
 #include <common/runas.h>
+#include <common/hashtable/hashtable.h>
+#include <common/hashtable/utils.h>
 #include <lttng/event-rule/event-rule-internal.h>
 #include <lttng/event-rule/syscall-internal.h>
 
@@ -223,6 +225,25 @@ lttng_event_rule_syscall_generate_exclusions(
        return NULL;
 }
 
+static unsigned long
+lttng_event_rule_syscall_hash(
+               const struct lttng_event_rule *rule)
+{
+       unsigned long hash;
+       struct lttng_event_rule_syscall *syscall_rule =
+                       container_of(rule, typeof(*syscall_rule), parent);
+
+       hash = hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_SYSCALL,
+                       lttng_ht_seed);
+       hash ^= hash_key_str(syscall_rule->pattern, lttng_ht_seed);
+       if (syscall_rule->filter_expression) {
+               hash ^= hash_key_str(syscall_rule->filter_expression,
+                               lttng_ht_seed);
+       }
+
+       return hash;
+}
+
 struct lttng_event_rule *lttng_event_rule_syscall_create()
 {
        struct lttng_event_rule *rule = NULL;
@@ -248,6 +269,7 @@ struct lttng_event_rule *lttng_event_rule_syscall_create()
                        lttng_event_rule_syscall_get_internal_filter_bytecode;
        syscall_rule->parent.generate_exclusions =
                        lttng_event_rule_syscall_generate_exclusions;
+       syscall_rule->parent.hash = lttng_event_rule_syscall_hash;
 end:
        return rule;
 }
index 0d0864719df5425500bb04f11c1665dbeaa1bdc1..a82151a254c6db6d5118754911fef55bfb55b8b4 100644 (file)
@@ -12,6 +12,8 @@
 #include <common/payload.h>
 #include <common/payload-view.h>
 #include <common/runas.h>
+#include <common/hashtable/hashtable.h>
+#include <common/hashtable/utils.h>
 #include <lttng/event-rule/event-rule-internal.h>
 #include <lttng/event-rule/tracepoint-internal.h>
 
@@ -542,6 +544,48 @@ static void destroy_lttng_exclusions_element(void *ptr)
        free(ptr);
 }
 
+static unsigned long lttng_event_rule_tracepoint_hash(
+               const struct lttng_event_rule *rule)
+{
+       unsigned long hash;
+       unsigned int i, exclusion_count;
+       enum lttng_event_rule_status status;
+       struct lttng_event_rule_tracepoint *tp_rule =
+                       container_of(rule, typeof(*tp_rule), parent);
+
+       hash = hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_TRACEPOINT,
+                       lttng_ht_seed);
+       hash ^= hash_key_ulong((void *) tp_rule->domain, lttng_ht_seed);
+       hash ^= hash_key_str(tp_rule->pattern, lttng_ht_seed);
+
+       if (tp_rule->filter_expression) {
+               hash ^= hash_key_str(tp_rule->filter_expression, lttng_ht_seed);
+       }
+
+       hash ^= hash_key_ulong((void *) tp_rule->loglevel.type,
+                              lttng_ht_seed);
+       if (tp_rule->loglevel.type != LTTNG_EVENT_LOGLEVEL_ALL) {
+               hash ^= hash_key_ulong(
+                               (void *) (unsigned long) tp_rule->loglevel.value,
+                               lttng_ht_seed);
+       }
+
+       status = lttng_event_rule_tracepoint_get_exclusions_count(rule,
+                       &exclusion_count);
+       assert(status == LTTNG_EVENT_RULE_STATUS_OK);
+
+       for (i = 0; i < exclusion_count; i++) {
+               const char *exclusion;
+
+               status = lttng_event_rule_tracepoint_get_exclusion_at_index(
+                               rule, i, &exclusion);
+               assert(status == LTTNG_EVENT_RULE_STATUS_OK);
+               hash ^= hash_key_str(exclusion, lttng_ht_seed);
+       }
+
+       return hash;
+}
+
 struct lttng_event_rule *lttng_event_rule_tracepoint_create(
                enum lttng_domain_type domain_type)
 {
@@ -571,6 +615,7 @@ struct lttng_event_rule *lttng_event_rule_tracepoint_create(
                        lttng_event_rule_tracepoint_get_internal_filter_bytecode;
        tp_rule->parent.generate_exclusions =
                        lttng_event_rule_tracepoint_generate_exclusions;
+       tp_rule->parent.hash = lttng_event_rule_tracepoint_hash;
 
        tp_rule->domain = domain_type;
        tp_rule->loglevel.type = LTTNG_EVENT_LOGLEVEL_ALL;
index b02332b61c11202780f64511cb690446791d37d4..2e64eaf898bd69880eaaff0208339b1c154e1665 100644 (file)
@@ -12,6 +12,8 @@
 #include <common/payload.h>
 #include <common/payload-view.h>
 #include <common/runas.h>
+#include <common/hashtable/hashtable.h>
+#include <common/hashtable/utils.h>
 #include <lttng/event-rule/event-rule-internal.h>
 #include <lttng/event-rule/uprobe-internal.h>
 #include <lttng/userspace-probe-internal.h>
@@ -167,6 +169,22 @@ lttng_event_rule_uprobe_generate_exclusions(const struct lttng_event_rule *rule)
        return NULL;
 }
 
+static unsigned long
+lttng_event_rule_uprobe_hash(
+               const struct lttng_event_rule *rule)
+{
+       unsigned long hash;
+       struct lttng_event_rule_uprobe *urule =
+                       container_of(rule, typeof(*urule), parent);
+
+       hash = hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_UPROBE,
+                       lttng_ht_seed);
+       hash ^= hash_key_str(urule->name, lttng_ht_seed);
+       hash ^= lttng_userspace_probe_location_hash(urule->location);
+
+       return hash;
+}
+
 struct lttng_event_rule *lttng_event_rule_uprobe_create()
 {
        struct lttng_event_rule *rule = NULL;
@@ -190,6 +208,7 @@ struct lttng_event_rule *lttng_event_rule_uprobe_create()
                        lttng_event_rule_uprobe_get_filter_bytecode;
        urule->parent.generate_exclusions =
                        lttng_event_rule_uprobe_generate_exclusions;
+       urule->parent.hash = lttng_event_rule_uprobe_hash;
 end:
        return rule;
 }
index 27ca02c99d09ea03212bd7d1489221d17270f50c..d2637f933efa18afb243049353cdab4c089908a2 100644 (file)
@@ -11,6 +11,8 @@
 #include <common/macros.h>
 #include <common/payload.h>
 #include <common/payload-view.h>
+#include <common/hashtable/hashtable.h>
+#include <common/hashtable/utils.h>
 #include <fcntl.h>
 #include <lttng/constant.h>
 #include <lttng/kernel-probe.h>
@@ -39,6 +41,14 @@ bool lttng_kernel_probe_location_symbol_is_equal(
                const struct lttng_kernel_probe_location *a,
                const struct lttng_kernel_probe_location *b);
 
+static
+unsigned long lttng_kernel_probe_location_address_hash(
+               const struct lttng_kernel_probe_location *location);
+
+static
+unsigned long lttng_kernel_probe_location_symbol_hash(
+               const struct lttng_kernel_probe_location *location);
+
 enum lttng_kernel_probe_location_type lttng_kernel_probe_location_get_type(
                const struct lttng_kernel_probe_location *location)
 {
@@ -109,6 +119,7 @@ lttng_kernel_probe_location_address_create(uint64_t address)
        ret->type = LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS;
        ret->equal = lttng_kernel_probe_location_address_is_equal;
        ret->serialize = lttng_kernel_probe_location_address_serialize;
+       ret->hash = lttng_kernel_probe_location_address_hash;
 
 end:
        return ret;
@@ -145,6 +156,7 @@ lttng_kernel_probe_location_symbol_create(const char *symbol_name,
        ret->type = LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET;
        ret->equal = lttng_kernel_probe_location_symbol_is_equal;
        ret->serialize = lttng_kernel_probe_location_symbol_serialize;
+       ret->hash = lttng_kernel_probe_location_symbol_hash;
        goto end;
 
 error:
@@ -489,6 +501,22 @@ end:
        return ret;
 }
 
+static
+unsigned long lttng_kernel_probe_location_address_hash(
+               const struct lttng_kernel_probe_location *location)
+{
+       unsigned long hash = hash_key_ulong(
+                       (void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS,
+                       lttng_ht_seed);
+       struct lttng_kernel_probe_location_address *address_location =
+                       container_of(location, typeof(*address_location),
+                               parent);
+
+       hash ^= hash_key_u64(&address_location->address, lttng_ht_seed);
+
+       return hash;
+}
+
 static
 bool lttng_kernel_probe_location_address_is_equal(
                const struct lttng_kernel_probe_location *_a,
@@ -512,6 +540,23 @@ end:
        return is_equal;
 }
 
+static
+unsigned long lttng_kernel_probe_location_symbol_hash(
+               const struct lttng_kernel_probe_location *location)
+{
+       unsigned long hash = hash_key_ulong(
+                       (void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET,
+                       lttng_ht_seed);
+       struct lttng_kernel_probe_location_symbol *symbol_location =
+                       container_of(location, typeof(*symbol_location),
+                               parent);
+
+       hash ^= hash_key_str(symbol_location->symbol_name, lttng_ht_seed);
+       hash ^= hash_key_u64(&symbol_location->offset, lttng_ht_seed);
+
+       return hash;
+}
+
 static
 bool lttng_kernel_probe_location_symbol_is_equal(
                const struct lttng_kernel_probe_location *_a,
@@ -672,3 +717,10 @@ struct lttng_kernel_probe_location *lttng_kernel_probe_location_copy(
 err:
        return new_location;
 }
+
+LTTNG_HIDDEN
+unsigned long lttng_kernel_probe_location_hash(
+       const struct lttng_kernel_probe_location *location)
+{
+       return location->hash(location);
+}
index 609ffc1ac22874cb5d944a2ced6adcc0cf07e2b2..a1a4d1fb3f3f14a82fefee7c4746773339397be4 100644 (file)
@@ -12,6 +12,8 @@
 #include <common/macros.h>
 #include <common/payload.h>
 #include <common/payload-view.h>
+#include <common/hashtable/hashtable.h>
+#include <common/hashtable/utils.h>
 #include <fcntl.h>
 #include <lttng/constant.h>
 #include <lttng/userspace-probe-internal.h>
@@ -199,6 +201,25 @@ end:
        return is_equal;
 }
 
+static unsigned long lttng_userspace_probe_location_function_hash(
+               const struct lttng_userspace_probe_location *location)
+{
+       unsigned long hash = hash_key_ulong(
+                       (void *) LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION,
+                       lttng_ht_seed);
+       struct lttng_userspace_probe_location_function *function_location =
+                       container_of(location, typeof(*function_location),
+                                       parent);
+
+       hash ^= hash_key_str(function_location->function_name, lttng_ht_seed);
+       hash ^= hash_key_str(function_location->binary_path, lttng_ht_seed);
+       /*
+        * No need to hash on the fd. Worst comes to worse,
+        * the equal function will discriminate.
+        */
+       return hash;
+}
+
 static bool lttng_userspace_probe_location_function_is_equal(
                const struct lttng_userspace_probe_location *_a,
                const struct lttng_userspace_probe_location *_b)
@@ -290,6 +311,7 @@ lttng_userspace_probe_location_function_create_no_check(const char *binary_path,
        ret->lookup_method = lookup_method;
        ret->type = LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION;
        ret->equal = lttng_userspace_probe_location_function_is_equal;
+       ret->hash = lttng_userspace_probe_location_function_hash;
        goto end;
 
 error:
@@ -305,6 +327,25 @@ end:
        return ret;
 }
 
+static unsigned long lttng_userspace_probe_location_tracepoint_hash(
+               const struct lttng_userspace_probe_location *location)
+{
+       unsigned long hash = hash_key_ulong(
+                       (void *) LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT,
+                       lttng_ht_seed);
+       struct lttng_userspace_probe_location_tracepoint *tp_location =
+                       container_of(location, typeof(*tp_location), parent);
+
+       hash ^= hash_key_str(tp_location->probe_name, lttng_ht_seed);
+       hash ^= hash_key_str(tp_location->provider_name, lttng_ht_seed);
+       hash ^= hash_key_str(tp_location->binary_path, lttng_ht_seed);
+       /*
+        * No need to hash on the fd. Worst comes to worse,
+        * the equal function will discriminate.
+        */
+       return hash;
+}
+
 static bool lttng_userspace_probe_location_tracepoint_is_equal(
                const struct lttng_userspace_probe_location *_a,
                const struct lttng_userspace_probe_location *_b)
@@ -406,6 +447,7 @@ lttng_userspace_probe_location_tracepoint_create_no_check(const char *binary_pat
        ret->lookup_method = lookup_method;
        ret->type = LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT;
        ret->equal = lttng_userspace_probe_location_tracepoint_is_equal;
+       ret->hash = lttng_userspace_probe_location_tracepoint_hash;
        goto end;
 
 error:
@@ -1916,3 +1958,10 @@ bool lttng_userspace_probe_location_is_equal(
 end:
        return is_equal;
 }
+
+LTTNG_HIDDEN
+unsigned long lttng_userspace_probe_location_hash(
+               const struct lttng_userspace_probe_location *location)
+{
+       return location->hash(location);
+}
This page took 0.036709 seconds and 4 git commands to generate.