From: Jonathan Rajotte Date: Mon, 17 Aug 2020 22:23:27 +0000 (-0400) Subject: Add base support for event rule hit X-Git-Tag: v2.13.0-rc1~397 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=959e3c66727698e58a8788aceeda5820b3c938ba;p=lttng-tools.git Add base support for event rule hit 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 Signed-off-by: Jérémie Galarneau Change-Id: Iab4db4fc7e9f0c5a7206106fa6a4781b6b95d306 --- diff --git a/include/lttng/event-rule/event-rule-internal.h b/include/lttng/event-rule/event-rule-internal.h index 7aca4a02b..ea0f46e48 100644 --- a/include/lttng/event-rule/event-rule-internal.h +++ b/include/lttng/event-rule/event-rule-internal.h @@ -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 */ diff --git a/include/lttng/kernel-probe-internal.h b/include/lttng/kernel-probe-internal.h index 381c6a411..e2889fd78 100644 --- a/include/lttng/kernel-probe-internal.h +++ b/include/lttng/kernel-probe-internal.h @@ -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 */ diff --git a/include/lttng/userspace-probe-internal.h b/include/lttng/userspace-probe-internal.h index e602a64e7..b530e2963 100644 --- a/include/lttng/userspace-probe-internal.h +++ b/include/lttng/userspace-probe-internal.h @@ -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 */ diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index d7c7984d2..d93478edf 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -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); } /* diff --git a/src/bin/lttng-sessiond/kernel.h b/src/bin/lttng-sessiond/kernel.h index 53d480313..1adf69253 100644 --- a/src/bin/lttng-sessiond/kernel.h +++ b/src/bin/lttng-sessiond/kernel.h @@ -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); diff --git a/src/bin/lttng-sessiond/notification-thread-events.c b/src/bin/lttng-sessiond/notification-thread-events.c index a1af9c535..5956d53ca 100644 --- a/src/bin/lttng-sessiond/notification-thread-events.c +++ b/src/bin/lttng-sessiond/notification-thread-events.c @@ -26,8 +26,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -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)); diff --git a/src/common/event-rule/event-rule.c b/src/common/event-rule/event-rule.c index 627674ba9..a42d5555c 100644 --- a/src/common/event-rule/event-rule.c +++ b/src/common/event-rule/event-rule.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include #include @@ -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); +} diff --git a/src/common/event-rule/kprobe.c b/src/common/event-rule/kprobe.c index 6846f0cb1..15dabdde3 100644 --- a/src/common/event-rule/kprobe.c +++ b/src/common/event-rule/kprobe.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -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; } diff --git a/src/common/event-rule/syscall.c b/src/common/event-rule/syscall.c index b2feb2c6e..51f22fcc0 100644 --- a/src/common/event-rule/syscall.c +++ b/src/common/event-rule/syscall.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include @@ -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; } diff --git a/src/common/event-rule/tracepoint.c b/src/common/event-rule/tracepoint.c index 0d0864719..a82151a25 100644 --- a/src/common/event-rule/tracepoint.c +++ b/src/common/event-rule/tracepoint.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include @@ -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; diff --git a/src/common/event-rule/uprobe.c b/src/common/event-rule/uprobe.c index b02332b61..2e64eaf89 100644 --- a/src/common/event-rule/uprobe.c +++ b/src/common/event-rule/uprobe.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -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; } diff --git a/src/common/kernel-probe.c b/src/common/kernel-probe.c index 27ca02c99..d2637f933 100644 --- a/src/common/kernel-probe.c +++ b/src/common/kernel-probe.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include #include @@ -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); +} diff --git a/src/common/userspace-probe.c b/src/common/userspace-probe.c index 609ffc1ac..a1a4d1fb3 100644 --- a/src/common/userspace-probe.c +++ b/src/common/userspace-probe.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -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); +}