From 7a3dcaf60e26cbedf0363a6bd0da7116e013bc80 Mon Sep 17 00:00:00 2001 From: Jonathan Rajotte Date: Wed, 11 Mar 2020 13:50:08 -0400 Subject: [PATCH] event-rule: lttng_event_rule base object MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit A lttng_event_rule object is the base object representing an event-rule. We plan on using the event-rule object for compositing with a new condition type. This also paves the way toward further improvement of the lttng_event related APIs. Signed-off-by: Jonathan Rajotte Signed-off-by: Jérémie Galarneau Change-Id: I5bbfa3b75337f040cf7e565447d4a4af590ed043 --- configure.ac | 3 + include/Makefile.am | 4 + .../lttng/event-rule/event-rule-internal.h | 123 ++++++++ include/lttng/event-rule/event-rule.h | 58 ++++ include/lttng/lttng.h | 1 + src/common/Makefile.am | 1 + src/common/event-rule/event-rule.c | 276 ++++++++++++++++++ 7 files changed, 466 insertions(+) create mode 100644 include/lttng/event-rule/event-rule-internal.h create mode 100644 include/lttng/event-rule/event-rule.h create mode 100644 src/common/event-rule/event-rule.c diff --git a/configure.ac b/configure.ac index dd0fb21da..1b6f3fcb0 100644 --- a/configure.ac +++ b/configure.ac @@ -1102,6 +1102,9 @@ AC_SUBST(lttngnotificationincludedir) lttngtriggerincludedir="${includedir}/lttng/trigger" AC_SUBST(lttngtriggerincludedir) +lttngeventruleincludedir="${includedir}/lttng/event-rule" +AC_SUBST(lttngeventruleincludedir) + lttnglibexecdir="${libdir}/lttng/libexec" AC_SUBST(lttnglibexecdir) diff --git a/include/Makefile.am b/include/Makefile.am index cd2877193..fe83588ca 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -143,6 +143,9 @@ lttngnotificationinclude_HEADERS= \ lttngtriggerinclude_HEADERS= \ lttng/trigger/trigger.h +lttngeventruleinclude_HEADERS= \ + lttng/event-rule/event-rule.h + noinst_HEADERS = \ lttng/snapshot-internal.h \ lttng/health-internal.h \ @@ -173,5 +176,6 @@ noinst_HEADERS = \ lttng/session-internal.h \ lttng/session-descriptor-internal.h \ lttng/kernel-probe-internal.h \ + lttng/event-rule/event-rule-internal.h \ version.h \ version.i diff --git a/include/lttng/event-rule/event-rule-internal.h b/include/lttng/event-rule/event-rule-internal.h new file mode 100644 index 000000000..9fb115caf --- /dev/null +++ b/include/lttng/event-rule/event-rule-internal.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2019 Jonathan Rajotte + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_EVENT_RULE_INTERNAL_H +#define LTTNG_EVENT_RULE_INTERNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include + +struct lttng_payload; +struct lttng_payload_view; + +typedef void (*event_rule_destroy_cb)(struct lttng_event_rule *event_rule); +typedef bool (*event_rule_validate_cb)( + const struct lttng_event_rule *event_rule); +typedef int (*event_rule_serialize_cb)( + const struct lttng_event_rule *event_rule, + struct lttng_payload *payload); +typedef bool (*event_rule_equal_cb)(const struct lttng_event_rule *a, + const struct lttng_event_rule *b); +typedef ssize_t (*event_rule_create_from_payload_cb)( + struct lttng_payload_view *view, + struct lttng_event_rule **event_rule); +typedef enum lttng_error_code (*event_rule_generate_filter_bytecode_cb)( + struct lttng_event_rule *event_rule, uid_t uid, gid_t gid); +typedef const char *(*event_rule_get_filter_cb)( + const struct lttng_event_rule *event_rule); +typedef const struct lttng_filter_bytecode *( + *event_rule_get_filter_bytecode_cb)( + const struct lttng_event_rule *event_rule); +typedef struct lttng_event_exclusion *(*event_rule_generate_exclusions_cb)( + const struct lttng_event_rule *event_rule); + +struct lttng_event_rule { + struct urcu_ref ref; + enum lttng_event_rule_type type; + event_rule_validate_cb validate; + event_rule_serialize_cb serialize; + event_rule_equal_cb equal; + event_rule_destroy_cb destroy; + event_rule_generate_filter_bytecode_cb generate_filter_bytecode; + event_rule_get_filter_cb get_filter; + event_rule_get_filter_bytecode_cb get_filter_bytecode; + event_rule_generate_exclusions_cb generate_exclusions; +}; + +struct lttng_event_rule_comm { + /* enum lttng_event_rule_type */ + int8_t event_rule_type; + char payload[]; +}; + +LTTNG_HIDDEN +void lttng_event_rule_init(struct lttng_event_rule *event_rule, + enum lttng_event_rule_type type); + +LTTNG_HIDDEN +bool lttng_event_rule_validate(const struct lttng_event_rule *event_rule); + +LTTNG_HIDDEN +ssize_t lttng_event_rule_create_from_payload( + struct lttng_payload_view *payload, + struct lttng_event_rule **event_rule); + +LTTNG_HIDDEN +int lttng_event_rule_serialize(const struct lttng_event_rule *event_rule, + struct lttng_payload *payload); + +LTTNG_HIDDEN +bool lttng_event_rule_is_equal(const struct lttng_event_rule *a, + const struct lttng_event_rule *b); + +LTTNG_HIDDEN +bool lttng_event_rule_get(struct lttng_event_rule *rule); + +LTTNG_HIDDEN +void lttng_event_rule_put(struct lttng_event_rule *rule); + +LTTNG_HIDDEN +enum lttng_domain_type lttng_event_rule_get_domain_type( + const struct lttng_event_rule *rule); + +LTTNG_HIDDEN +enum lttng_error_code lttng_event_rule_generate_filter_bytecode( + struct lttng_event_rule *rule, uid_t uid, gid_t gid); + +/* + * If not present/implemented returns NULL. + * Caller DOES NOT own the returned object. + */ +LTTNG_HIDDEN +const char *lttng_event_rule_get_filter(const struct lttng_event_rule *rule); + +/* + * If not present/implemented returns NULL. + * Caller DOES NOT own the returned object. + */ +LTTNG_HIDDEN +const struct lttng_filter_bytecode *lttng_event_rule_get_filter_bytecode( + const struct lttng_event_rule *rule); + +/* + * If not present/implemented return NULL. + * Caller OWNS the returned object. + */ +LTTNG_HIDDEN +struct lttng_event_exclusion *lttng_event_rule_generate_exclusions( + const struct lttng_event_rule *rule); + +LTTNG_HIDDEN +const char *lttng_event_rule_type_str(enum lttng_event_rule_type type); + +#endif /* LTTNG_EVENT_RULE_INTERNAL_H */ diff --git a/include/lttng/event-rule/event-rule.h b/include/lttng/event-rule/event-rule.h new file mode 100644 index 000000000..e097dd488 --- /dev/null +++ b/include/lttng/event-rule/event-rule.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2019 Jonathan Rajotte + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_EVENT_RULE_H +#define LTTNG_EVENT_RULE_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct lttng_event_rule; + +enum lttng_event_rule_type { + LTTNG_EVENT_RULE_TYPE_UNKNOWN = -1, + LTTNG_EVENT_RULE_TYPE_TRACEPOINT = 0, + LTTNG_EVENT_RULE_TYPE_SYSCALL = 1, + LTTNG_EVENT_RULE_TYPE_KPROBE = 2, + LTTNG_EVENT_RULE_TYPE_KRETPROBE = 3, + LTTNG_EVENT_RULE_TYPE_UPROBE = 4, +}; + +enum lttng_event_rule_status { + LTTNG_EVENT_RULE_STATUS_OK = 0, + LTTNG_EVENT_RULE_STATUS_ERROR = -1, + LTTNG_EVENT_RULE_STATUS_UNKNOWN = -2, + LTTNG_EVENT_RULE_STATUS_INVALID = -3, + LTTNG_EVENT_RULE_STATUS_UNSET = -4, + LTTNG_EVENT_RULE_STATUS_UNSUPPORTED = -5, +}; + +/** + * An event rule describes a set of criteria to be used as a discriminant in + * regards to a set of events. + */ + +/* + * Get the event rule type. + * + * Returns the type of an event rule on success, LTTNG_EVENT_RULE_UNKNOWN on + * error. + */ +extern enum lttng_event_rule_type lttng_event_rule_get_type( + const struct lttng_event_rule *event_rule); + +/* + * Destroy an event rule object. + */ +extern void lttng_event_rule_destroy(struct lttng_event_rule *rule); + +#ifdef __cplusplus +} +#endif + +#endif /* LTTNG_EVENT_RULE_H */ diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h index 6746d7bbf..bfc3bbd7d 100644 --- a/include/lttng/lttng.h +++ b/include/lttng/lttng.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 0905e899f..c29ce68dd 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -48,6 +48,7 @@ libcommon_la_SOURCES = \ error.c error.h \ evaluation.c \ event.c \ + event-rule/event-rule.c \ filter.c filter.h \ fd-handle.c fd-handle.h \ fs-handle.c fs-handle.h fs-handle-internal.h \ diff --git a/src/common/event-rule/event-rule.c b/src/common/event-rule/event-rule.c new file mode 100644 index 000000000..efeb76539 --- /dev/null +++ b/src/common/event-rule/event-rule.c @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2019 Jonathan Rajotte + * + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#include +#include +#include +#include +#include +#include +#include + +enum lttng_event_rule_type lttng_event_rule_get_type( + const struct lttng_event_rule *event_rule) +{ + return event_rule ? event_rule->type : LTTNG_EVENT_RULE_TYPE_UNKNOWN; +} + +LTTNG_HIDDEN +enum lttng_domain_type lttng_event_rule_get_domain_type( + const struct lttng_event_rule *event_rule) +{ + enum lttng_domain_type domain_type = LTTNG_DOMAIN_NONE; + + switch (lttng_event_rule_get_type(event_rule)) { + case LTTNG_EVENT_RULE_TYPE_TRACEPOINT: + /* TODO */ + domain_type = LTTNG_DOMAIN_NONE; + break; + case LTTNG_EVENT_RULE_TYPE_SYSCALL: + case LTTNG_EVENT_RULE_TYPE_KPROBE: + case LTTNG_EVENT_RULE_TYPE_KRETPROBE: + case LTTNG_EVENT_RULE_TYPE_UPROBE: + domain_type = LTTNG_DOMAIN_KERNEL; + break; + case LTTNG_EVENT_RULE_TYPE_UNKNOWN: + domain_type = LTTNG_DOMAIN_NONE; + break; + } + + return domain_type; +} + +static void lttng_event_rule_release(struct urcu_ref *ref) +{ + struct lttng_event_rule *event_rule = + container_of(ref, typeof(*event_rule), ref); + + assert(event_rule->destroy); + event_rule->destroy(event_rule); +} + +void lttng_event_rule_destroy(struct lttng_event_rule *event_rule) +{ + lttng_event_rule_put(event_rule); +} + +LTTNG_HIDDEN +bool lttng_event_rule_validate(const struct lttng_event_rule *event_rule) +{ + bool valid; + + if (!event_rule) { + valid = false; + goto end; + } + + if (!event_rule->validate) { + /* Sub-class guarantees that it can never be invalid. */ + valid = true; + goto end; + } + + valid = event_rule->validate(event_rule); +end: + return valid; +} + +LTTNG_HIDDEN +int lttng_event_rule_serialize(const struct lttng_event_rule *event_rule, + struct lttng_payload *payload) +{ + int ret; + struct lttng_event_rule_comm event_rule_comm = {}; + + if (!event_rule) { + ret = -1; + goto end; + } + + event_rule_comm.event_rule_type = (int8_t) event_rule->type; + + ret = lttng_dynamic_buffer_append( + &payload->buffer, &event_rule_comm, sizeof(event_rule_comm)); + if (ret) { + goto end; + } + + ret = event_rule->serialize(event_rule, payload); + if (ret) { + goto end; + } +end: + return ret; +} + +LTTNG_HIDDEN +bool lttng_event_rule_is_equal(const struct lttng_event_rule *a, + const struct lttng_event_rule *b) +{ + bool is_equal = false; + + if (!a || !b) { + goto end; + } + + if (a->type != b->type) { + goto end; + } + + if (a == b) { + is_equal = true; + goto end; + } + + is_equal = a->equal ? a->equal(a, b) : true; +end: + return is_equal; +} + +LTTNG_HIDDEN +ssize_t lttng_event_rule_create_from_payload( + struct lttng_payload_view *view, + struct lttng_event_rule **event_rule) +{ + ssize_t ret, consumed = 0; + const struct lttng_event_rule_comm *event_rule_comm; + event_rule_create_from_payload_cb create_from_payload = NULL; + + if (!view || !event_rule) { + ret = -1; + goto end; + } + + DBG("Deserializing event_rule from payload"); + event_rule_comm = (const struct lttng_event_rule_comm *) view->buffer.data; + consumed += sizeof(*event_rule_comm); + + switch ((enum lttng_event_rule_type) event_rule_comm->event_rule_type) { + case LTTNG_EVENT_RULE_TYPE_TRACEPOINT: + /* TODO */ + break; + case LTTNG_EVENT_RULE_TYPE_KPROBE: + /* TODO */ + break; + case LTTNG_EVENT_RULE_TYPE_KRETPROBE: + /* TODO */ + break; + case LTTNG_EVENT_RULE_TYPE_UPROBE: + /* TODO */ + break; + case LTTNG_EVENT_RULE_TYPE_SYSCALL: + /* TODO */ + break; + default: + ERR("Attempted to create event rule of unknown type (%i)", + (int) event_rule_comm->event_rule_type); + ret = -1; + goto end; + } + + assert(create_from_payload); + + { + struct lttng_payload_view child_view = + lttng_payload_view_from_view( + view, consumed, -1); + + ret = create_from_payload(&child_view, event_rule); + if (ret < 0) { + goto end; + } + + consumed += ret; + } + + if (!lttng_event_rule_validate(*event_rule)) { + ret = -1; + goto end; + } + + ret = consumed; +end: + return ret; +} + +LTTNG_HIDDEN +void lttng_event_rule_init(struct lttng_event_rule *event_rule, + enum lttng_event_rule_type type) +{ + urcu_ref_init(&event_rule->ref); + event_rule->type = type; +} + +LTTNG_HIDDEN +bool lttng_event_rule_get(struct lttng_event_rule *event_rule) +{ + return urcu_ref_get_unless_zero(&event_rule->ref); +} + +LTTNG_HIDDEN +void lttng_event_rule_put(struct lttng_event_rule *event_rule) +{ + if (!event_rule) { + return; + } + + assert(event_rule->ref.refcount); + urcu_ref_put(&event_rule->ref, lttng_event_rule_release); +} + +LTTNG_HIDDEN +enum lttng_error_code lttng_event_rule_generate_filter_bytecode( + struct lttng_event_rule *rule, uid_t uid, gid_t gid) +{ + assert(rule->generate_filter_bytecode); + return rule->generate_filter_bytecode(rule, uid, gid); +} + +LTTNG_HIDDEN +const char *lttng_event_rule_get_filter(const struct lttng_event_rule *rule) +{ + assert(rule->get_filter); + return rule->get_filter(rule); +} + +LTTNG_HIDDEN +const struct lttng_filter_bytecode *lttng_event_rule_get_filter_bytecode( + const struct lttng_event_rule *rule) +{ + assert(rule->get_filter_bytecode); + return rule->get_filter_bytecode(rule); +} + +LTTNG_HIDDEN +struct lttng_event_exclusion *lttng_event_rule_generate_exclusions( + const struct lttng_event_rule *rule) +{ + assert(rule->generate_exclusions); + return rule->generate_exclusions(rule); +} + +LTTNG_HIDDEN +const char *lttng_event_rule_type_str(enum lttng_event_rule_type type) +{ + switch (type) { + case LTTNG_EVENT_RULE_TYPE_UNKNOWN: + return "unknown"; + case LTTNG_EVENT_RULE_TYPE_TRACEPOINT: + return "tracepoint"; + case LTTNG_EVENT_RULE_TYPE_SYSCALL: + return "syscall"; + case LTTNG_EVENT_RULE_TYPE_KPROBE: + return "probe"; + case LTTNG_EVENT_RULE_TYPE_KRETPROBE: + return "function"; + case LTTNG_EVENT_RULE_TYPE_UPROBE: + return "userspace-probe"; + default: + abort(); + } +} -- 2.34.1