Filter iteration: iterate on list of filters
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Mon, 12 Nov 2012 20:55:27 +0000 (15:55 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 22 Nov 2012 18:55:04 +0000 (13:55 -0500)
Reviewed-by: David Goulet <dgoulet@efficios.com>
Reviewed-by: Christian Babeux <christian.babeux@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
include/lttng/ust-events.h
include/lttng/ust-tracepoint-event.h
liblttng-ust/ltt-events.c
liblttng-ust/lttng-filter.c
liblttng-ust/lttng-filter.h
liblttng-ust/lttng-ust-abi.c
liblttng-ust/lttng-ust-comm.c

index 0e19ed2229ac9c7b417aee01be5113e0701351fe..1378a350fb867c35871257ae46c585459d8ccac4 100644 (file)
@@ -257,7 +257,8 @@ struct session_wildcard {
        struct cds_list_head list;      /* per-session list of wildcards */
        struct cds_list_head session_list; /* node of session wildcard list */
        struct wildcard_entry *entry;
-       struct lttng_ust_filter_bytecode *filter_bytecode;
+       /* list of struct lttng_ust_filter_bytecode_node */
+       struct cds_list_head filter_bytecode;
        unsigned int enabled:1;
 };
 
@@ -270,7 +271,8 @@ struct wildcard_entry {
        /* head of session list to which this wildcard apply */
        struct cds_list_head session_list;
        enum lttng_ust_loglevel_type loglevel_type;
-       struct lttng_ust_filter_bytecode *filter_bytecode;
+       /* list of struct lttng_ust_filter_bytecode_node */
+       struct cds_list_head filter_bytecode;
        int loglevel;
        char name[0];
 };
@@ -297,7 +299,18 @@ struct lttng_ust_field_list {
 
 struct ust_pending_probe;
 struct ltt_event;
-struct lttng_ust_filter_bytecode;
+
+struct lttng_ust_filter_bytecode_node {
+       struct cds_list_head node;
+       struct lttng_ust_filter_bytecode bc;
+};
+
+struct lttng_bytecode_runtime {
+       /* Associated bytecode */
+       struct lttng_ust_filter_bytecode_node *bc;
+       int (*filter)(void *filter_data, const char *filter_stack_data);
+       struct cds_list_head node;
+};
 
 /*
  * ltt_event structure is referred to by the tracing fast path. It must be
@@ -313,7 +326,7 @@ struct ltt_event {
        struct ltt_channel *chan;
        int enabled;
        const struct lttng_event_desc *desc;
-       int (*filter)(void *filter_data, const char *filter_stack_data);
+       void *filter_unused;
        struct lttng_ctx *ctx;
        enum lttng_ust_instrumentation instrumentation;
        union {
@@ -323,8 +336,10 @@ struct ltt_event {
        struct ust_pending_probe *pending_probe;
        unsigned int metadata_dumped:1;
        /* LTTng-UST 2.1 starts here */
-       struct lttng_ust_filter_bytecode *filter_bytecode;
-       void *filter_data;
+       /* list of struct lttng_ust_filter_bytecode_node */
+       struct cds_list_head filter_bytecode;
+       /* list of struct lttng_bytecode_runtime */
+       struct cds_list_head bytecode_runtime;
 };
 
 struct channel;
@@ -508,11 +523,15 @@ int ltt_loglevel_match(const struct lttng_event_desc *desc,
 void ltt_probes_create_wildcard_events(struct wildcard_entry *entry,
                                struct session_wildcard *wildcard);
 int lttng_filter_event_attach_bytecode(struct ltt_event *event,
-                struct lttng_ust_filter_bytecode *filter);
+                struct lttng_ust_filter_bytecode_node *filter);
 int lttng_filter_wildcard_attach_bytecode(struct session_wildcard *wildcard,
-                struct lttng_ust_filter_bytecode *filter);
-void lttng_filter_event_link_bytecode(struct ltt_event *event,
-               struct lttng_ust_filter_bytecode *filter_bytecode);
+                struct lttng_ust_filter_bytecode_node *filter);
+void lttng_filter_event_link_bytecode(struct ltt_event *event);
+void lttng_filter_event_link_wildcard_bytecode(struct ltt_event *event,
+               struct session_wildcard *wildcard);
 void lttng_filter_wildcard_link_bytecode(struct session_wildcard *wildcard);
+void lttng_free_event_filter_bytecode(struct ltt_event *event);
+void lttng_free_wildcard_filter_bytecode(struct session_wildcard *wildcard);
+void lttng_free_event_filter_runtime(struct ltt_event *event);
 
 #endif /* _LTTNG_UST_EVENTS_H */
index 74d06e19ad182fc5b8b863543116581f6ae12240..3cecec9b06bb021bd1f5e14ae3130d4bc43f9095 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <stdio.h>
 #include <urcu/compiler.h>
+#include <urcu/rculist.h>
 #include <lttng/ust-events.h>
 #include <lttng/ringbuffer-config.h>
 #include <lttng/ust-compiler.h>
@@ -485,11 +486,16 @@ void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args))         \
                return;                                                       \
        if (caa_unlikely(!CMM_ACCESS_ONCE(__event->enabled)))                 \
                return;                                                       \
-       if (caa_unlikely(__event->filter)) {                                  \
+       if (caa_unlikely(!cds_list_empty(&__event->bytecode_runtime))) {      \
+               struct lttng_bytecode_runtime *bc_runtime;                    \
+                                                                             \
                __event_prepare_filter_stack__##_provider##___##_name(__stackvar.__filter_stack_data, \
-                       _TP_ARGS_DATA_VAR(_args));                                    \
-               if (caa_likely(!__event->filter(__event->filter_data, __stackvar.__filter_stack_data))) \
-                       return;                                               \
+                       _TP_ARGS_DATA_VAR(_args));                            \
+               cds_list_for_each_entry_rcu(bc_runtime, &__event->bytecode_runtime, node) { \
+                       if (caa_likely(!bc_runtime->filter(bc_runtime,        \
+                                       __stackvar.__filter_stack_data)))     \
+                               return;                                       \
+               }                                                             \
        }                                                                     \
        __event_len = __event_get_size__##_provider##___##_name(__stackvar.__dynamic_len, \
                 _TP_ARGS_DATA_VAR(_args));                                   \
index 7a7fd7efc07ba54b5baca467f3c82e6d0c23bf2c..ee82413db8f8707b30884287fc5723434227200a 100644 (file)
@@ -235,6 +235,9 @@ int pending_probe_fix_events(const struct lttng_event_desc *desc)
        {
                struct wildcard_entry *wildcard;
 
+               //FIXME: should iterate on all match for filter.
+               //FIXME: should re-use pending event if present rather
+               //than create duplicate.
                wildcard = match_wildcard(desc);
                if (strcmp(desc->name, "lttng_ust:metadata") && wildcard) {
                        struct session_wildcard *sw;
@@ -259,8 +262,8 @@ int pending_probe_fix_events(const struct lttng_event_desc *desc)
                                }
                                cds_list_add(&ev->wildcard_list,
                                        &sw->events);
-                               lttng_filter_event_link_bytecode(ev,
-                                       sw->filter_bytecode);
+                               lttng_filter_event_link_wildcard_bytecode(ev,
+                                       sw);
                        }
                }
        }
@@ -283,6 +286,8 @@ int pending_probe_fix_events(const struct lttng_event_desc *desc)
                if (strncmp(name, e->name, LTTNG_UST_SYM_NAME_LEN - 1)) {
                        continue;
                }
+               /* TODO: wildcard same as pending event: duplicate */
+               /* TODO: Should apply filter though */
                event = e->event;
                chan = event->chan;
                assert(!event->desc);
@@ -297,8 +302,7 @@ int pending_probe_fix_events(const struct lttng_event_desc *desc)
                event->id = chan->free_event_id++;
                ret |= _ltt_event_metadata_statedump(chan->session, chan,
                                event);
-               lttng_filter_event_link_bytecode(event,
-                       event->filter_bytecode);
+               lttng_filter_event_link_bytecode(event);
        }
        return ret;
 }
@@ -514,6 +518,8 @@ int ltt_event_create(struct ltt_channel *chan,
                ret = -ENOMEM;
                goto full;
        }
+       //FIXME: re-use event if already registered by wildcard or
+       //if we have a pending probe.... (CHECK)
        /*
         * This is O(n^2) (for each event, the loop is called at event
         * creation). Might require a hash if we have lots of events.
@@ -557,6 +563,8 @@ int ltt_event_create(struct ltt_channel *chan,
         */
        chan->used_event_id++;
        event->enabled = 1;
+       CDS_INIT_LIST_HEAD(&event->filter_bytecode);
+       CDS_INIT_LIST_HEAD(&event->bytecode_runtime);
        event->instrumentation = event_param->instrumentation;
        /* Populate ltt_event structure before tracepoint registration. */
        cmm_smp_wmb();
@@ -655,8 +663,8 @@ void _ltt_event_destroy(struct ltt_event *event)
        }
        cds_list_del(&event->list);
        lttng_destroy_context(event->ctx);
-       free(event->filter_bytecode);
-       free(event->filter_data);
+       lttng_free_event_filter_runtime(event);
+       lttng_free_event_filter_bytecode(event);
        free(event);
 }
 
@@ -1357,6 +1365,9 @@ struct session_wildcard *add_wildcard(struct ltt_channel *chan,
        size_t name_len = strlen(event_param->name) + 1;
        int found = 0;
 
+       //FIXME: ensure that wildcard re-use pending events, or
+       //re-use actual events, applying its filter on top.
+
        /*
         * Try to find global wildcard entry. Given that this is shared
         * across all sessions, we need to check for exact loglevel
@@ -1386,6 +1397,7 @@ struct session_wildcard *add_wildcard(struct ltt_channel *chan,
                memcpy(&e->name[0], event_param->name, name_len);
                e->loglevel_type = event_param->loglevel_type;
                e->loglevel = event_param->loglevel;
+               CDS_INIT_LIST_HEAD(&e->filter_bytecode);
                cds_list_add(&e->list, &wildcard_list);
                CDS_INIT_LIST_HEAD(&e->session_list);
        }
@@ -1407,6 +1419,7 @@ struct session_wildcard *add_wildcard(struct ltt_channel *chan,
        sw->event_param.instrumentation = LTTNG_UST_TRACEPOINT;
        sw->event_param.loglevel_type = event_param->loglevel_type;
        sw->event_param.loglevel = event_param->loglevel;
+       CDS_INIT_LIST_HEAD(&sw->filter_bytecode);
        CDS_INIT_LIST_HEAD(&sw->events);
        cds_list_add(&sw->list, &chan->session->wildcards);
        cds_list_add(&sw->session_list, &e->session_list);
@@ -1439,7 +1452,7 @@ void _remove_wildcard(struct session_wildcard *wildcard)
                cds_list_del(&wildcard->entry->list);
                free(wildcard->entry);
        }
-       free(wildcard->filter_bytecode);
+       lttng_free_wildcard_filter_bytecode(wildcard);
        free(wildcard);
 }
 
index 1a0921fd72ac0ca78b4cc7c3f08667ab5767c300..6c3eda4ba554a28e692194a71170ae6569d7a824 100644 (file)
@@ -20,6 +20,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <urcu/rculist.h>
 #include "lttng-filter.h"
 
 static const char *opnames[] = {
@@ -213,13 +214,26 @@ int apply_field_reloc(struct ltt_event *event,
        return 0;
 }
 
+static
+int bytecode_is_linked(struct lttng_ust_filter_bytecode_node *filter_bytecode,
+               struct ltt_event *event)
+{
+       struct lttng_bytecode_runtime *bc_runtime;
+
+       cds_list_for_each_entry(bc_runtime, &event->bytecode_runtime, node) {
+               if (bc_runtime->bc == filter_bytecode)
+                       return 1;
+       }
+       return 0;
+}
+
 /*
  * Take a bytecode with reloc table and link it to an event to create a
  * bytecode runtime.
  */
 static
 int _lttng_filter_event_link_bytecode(struct ltt_event *event,
-               struct lttng_ust_filter_bytecode *filter_bytecode)
+               struct lttng_ust_filter_bytecode_node *filter_bytecode)
 {
        int ret, offset, next_offset;
        struct bytecode_runtime *runtime = NULL;
@@ -227,36 +241,37 @@ int _lttng_filter_event_link_bytecode(struct ltt_event *event,
 
        if (!filter_bytecode)
                return 0;
-       /* Even is not connected to any description */
+       /* Event is not connected to any description */
        if (!event->desc)
                return 0;
        /* Bytecode already linked */
-       if (event->filter || event->filter_data)
+       if (bytecode_is_linked(filter_bytecode, event))
                return 0;
 
-       dbg_printf("Linking\n");
+       dbg_printf("Linking...\n");
 
        /* We don't need the reloc table in the runtime */
-       runtime_alloc_len = sizeof(*runtime) + filter_bytecode->reloc_offset;
+       runtime_alloc_len = sizeof(*runtime) + filter_bytecode->bc.reloc_offset;
        runtime = zmalloc(runtime_alloc_len);
        if (!runtime) {
                ret = -ENOMEM;
                goto link_error;
        }
-       runtime->len = filter_bytecode->reloc_offset;
+       runtime->p.bc = filter_bytecode;
+       runtime->len = filter_bytecode->bc.reloc_offset;
        /* copy original bytecode */
-       memcpy(runtime->data, filter_bytecode->data, runtime->len);
+       memcpy(runtime->data, filter_bytecode->bc.data, runtime->len);
        /*
         * apply relocs. Those are a uint16_t (offset in bytecode)
         * followed by a string (field name).
         */
-       for (offset = filter_bytecode->reloc_offset;
-                       offset < filter_bytecode->len;
+       for (offset = filter_bytecode->bc.reloc_offset;
+                       offset < filter_bytecode->bc.len;
                        offset = next_offset) {
                uint16_t reloc_offset =
-                       *(uint16_t *) &filter_bytecode->data[offset];
+                       *(uint16_t *) &filter_bytecode->bc.data[offset];
                const char *field_name =
-                       (const char *) &filter_bytecode->data[offset + sizeof(uint16_t)];
+                       (const char *) &filter_bytecode->bc.data[offset + sizeof(uint16_t)];
 
                ret = apply_field_reloc(event, runtime, runtime->len, reloc_offset, field_name);
                if (ret) {
@@ -274,50 +289,63 @@ int _lttng_filter_event_link_bytecode(struct ltt_event *event,
        if (ret) {
                goto link_error;
        }
-       event->filter_data = runtime;
-       event->filter = lttng_filter_interpret_bytecode;
+       runtime->p.filter = lttng_filter_interpret_bytecode;
+       /* TODO: add with prio */
+       cds_list_add_rcu(&runtime->p.node, &event->bytecode_runtime);
+       dbg_printf("Linking successful.\n");
        return 0;
 
 link_error:
-       event->filter = lttng_filter_false;
-       free(runtime);
+       runtime->p.filter = lttng_filter_false;
+       /* TODO: add with prio */
+       cds_list_add_rcu(&runtime->p.node, &event->bytecode_runtime);
+       dbg_printf("Linking failed.\n");
        return ret;
 }
 
-void lttng_filter_event_link_bytecode(struct ltt_event *event,
-               struct lttng_ust_filter_bytecode *filter_bytecode)
+void lttng_filter_event_link_bytecode(struct ltt_event *event)
 {
+       struct lttng_ust_filter_bytecode_node *filter_bytecode;
        int ret;
 
-       ret = _lttng_filter_event_link_bytecode(event, filter_bytecode);
-       if (ret) {
-               dbg_printf("[lttng filter] warning: cannot link event bytecode\n");
+       cds_list_for_each_entry(filter_bytecode, &event->filter_bytecode, node) {
+               dbg_printf("linking bytecode\n");
+               ret = _lttng_filter_event_link_bytecode(event, filter_bytecode);
+               if (ret) {
+                       dbg_printf("[lttng filter] warning: cannot link event bytecode\n");
+               }
+       }
+}
+
+void lttng_filter_event_link_wildcard_bytecode(struct ltt_event *event,
+               struct session_wildcard *wildcard)
+{
+       struct lttng_ust_filter_bytecode_node *filter_bytecode;
+       int ret;
+
+       cds_list_for_each_entry(filter_bytecode, &wildcard->filter_bytecode, node) {
+               dbg_printf("linking bytecode\n");
+               ret = _lttng_filter_event_link_bytecode(event, filter_bytecode);
+               if (ret) {
+                       dbg_printf("[lttng filter] error linking wildcard bytecode\n");
+               }
        }
 }
 
 /*
- * Link bytecode to all events for a wildcard. Skips events that already
- * have a bytecode linked.
- * We do not set each event's filter_bytecode field, because they do not
- * own the filter_bytecode: the wildcard owns it.
+ * Link bytecode to all events for a wildcard.
+ * The "is_linked" check in _lttng_filter_event_link_bytecode() ensures
+ * that we don't link the same bytecode to an event more than once.
  */
 void lttng_filter_wildcard_link_bytecode(struct session_wildcard *wildcard)
 {
        struct ltt_event *event;
-       int ret;
 
-       if (!wildcard->filter_bytecode)
+       if (cds_list_empty(&wildcard->filter_bytecode))
                return;
-
        cds_list_for_each_entry(event, &wildcard->events, wildcard_list) {
-               if (event->filter)
-                       continue;
-               ret = _lttng_filter_event_link_bytecode(event,
-                               wildcard->filter_bytecode);
-               if (ret) {
-                       dbg_printf("[lttng filter] error linking wildcard bytecode");
-               }
-
+               dbg_printf("linking bytecode\n");
+               lttng_filter_event_link_wildcard_bytecode(event, wildcard);
        }
        return;
 }
@@ -327,13 +355,9 @@ void lttng_filter_wildcard_link_bytecode(struct session_wildcard *wildcard)
  * session. We own the filter_bytecode if we return success.
  */
 int lttng_filter_event_attach_bytecode(struct ltt_event *event,
-               struct lttng_ust_filter_bytecode *filter_bytecode)
+               struct lttng_ust_filter_bytecode_node *filter_bytecode)
 {
-       if (event->chan->session->been_active)
-               return -EPERM;
-       if (event->filter_bytecode)
-               return -EEXIST;
-       event->filter_bytecode = filter_bytecode;
+       cds_list_add(&filter_bytecode->node, &event->filter_bytecode);
        return 0;
 }
 
@@ -342,12 +366,38 @@ int lttng_filter_event_attach_bytecode(struct ltt_event *event,
  * session. We own the filter_bytecode if we return success.
  */
 int lttng_filter_wildcard_attach_bytecode(struct session_wildcard *wildcard,
-               struct lttng_ust_filter_bytecode *filter_bytecode)
+               struct lttng_ust_filter_bytecode_node *filter_bytecode)
 {
-       if (wildcard->chan->session->been_active)
-               return -EPERM;
-       if (wildcard->filter_bytecode)
-               return -EEXIST;
-       wildcard->filter_bytecode = filter_bytecode;
+       cds_list_add(&filter_bytecode->node, &wildcard->filter_bytecode);
        return 0;
 }
+
+void lttng_free_event_filter_bytecode(struct ltt_event *event)
+{
+       struct lttng_ust_filter_bytecode_node *filter_bytecode, *tmp;
+
+       cds_list_for_each_entry_safe(filter_bytecode, tmp,
+                       &event->filter_bytecode, node) {
+               free(filter_bytecode);
+       }
+}
+
+void lttng_free_wildcard_filter_bytecode(struct session_wildcard *wildcard)
+{
+       struct lttng_ust_filter_bytecode_node *filter_bytecode, *tmp;
+
+       cds_list_for_each_entry_safe(filter_bytecode, tmp,
+                       &wildcard->filter_bytecode, node) {
+               free(filter_bytecode);
+       }
+}
+
+void lttng_free_event_filter_runtime(struct ltt_event *event)
+{
+       struct bytecode_runtime *runtime, *tmp;
+
+       cds_list_for_each_entry_safe(runtime, tmp,
+                       &event->bytecode_runtime, p.node) {
+               free(runtime);
+       }
+}
index 8a40d16f740a5f8d75a4d513f789954ab51f0387..7b7213c988162b20398acb0309b63575d17a47c6 100644 (file)
 #endif
 
 #ifdef DEBUG
-#define dbg_printf(fmt, args...)     printf("[debug bytecode] " fmt, ## args)
+#define dbg_printf(fmt, args...)                               \
+       printf("[debug bytecode in %s:%s@%u] " fmt,             \
+               __FILE__, __func__, __LINE__, ## args)
 #else
 #define dbg_printf(fmt, args...)                               \
 do {                                                           \
        /* do nothing but check printf format */                \
        if (0)                                                  \
-               printf("[debug bytecode] " fmt, ## args);       \
+               printf("[debug bytecode in %s:%s@%u] " fmt,     \
+                       __FILE__, __func__, __LINE__, ## args); \
 } while (0)
 #endif
 
-/* Linked bytecode */
+/* Linked bytecode. Child of struct lttng_bytecode_runtime. */
 struct bytecode_runtime {
+       struct lttng_bytecode_runtime p;
        uint16_t len;
        char data[0];
 };
index d0b1e4f9d90a1a04864e8e63297aa68e81781966..56d588a8d246cd74a3662c72c3eacf1663fd0f1d 100644 (file)
@@ -1090,11 +1090,10 @@ long lttng_event_cmd(int objd, unsigned int cmd, unsigned long arg,
        {
                int ret;
                ret = lttng_filter_event_attach_bytecode(event,
-                               (struct lttng_ust_filter_bytecode *) arg);
+                               (struct lttng_ust_filter_bytecode_node *) arg);
                if (ret)
                        return ret;
-               lttng_filter_event_link_bytecode(event,
-                               event->filter_bytecode);
+               lttng_filter_event_link_bytecode(event);
                return 0;
        }
        default:
@@ -1161,7 +1160,7 @@ long lttng_wildcard_cmd(int objd, unsigned int cmd, unsigned long arg,
                int ret;
 
                ret = lttng_filter_wildcard_attach_bytecode(wildcard,
-                               (struct lttng_ust_filter_bytecode *) arg);
+                               (struct lttng_ust_filter_bytecode_node *) arg);
                if (ret)
                        return ret;
                lttng_filter_wildcard_link_bytecode(wildcard);
index 92d0fd70da205ecad68d9da6a963d94eda728422..ef8b6fedcf7b045d197223fdcea1056a530d59a0 100644 (file)
@@ -288,7 +288,7 @@ int handle_message(struct sock_info *sock_info,
        case LTTNG_UST_FILTER:
        {
                /* Receive filter data */
-               struct lttng_ust_filter_bytecode *bytecode;
+               struct lttng_ust_filter_bytecode_node *bytecode;
 
                if (lum->u.filter.data_size > FILTER_BYTECODE_MAX_LEN) {
                        ERR("Filter data size is too large: %u bytes",
@@ -309,7 +309,7 @@ int handle_message(struct sock_info *sock_info,
                        ret = -ENOMEM;
                        goto error;
                }
-               len = ustcomm_recv_unix_sock(sock, bytecode->data,
+               len = ustcomm_recv_unix_sock(sock, bytecode->bc.data,
                                lum->u.filter.data_size);
                switch (len) {
                case 0: /* orderly shutdown */
@@ -337,8 +337,8 @@ int handle_message(struct sock_info *sock_info,
                                goto end;
                        }
                }
-               bytecode->len = lum->u.filter.data_size;
-               bytecode->reloc_offset = lum->u.filter.reloc_offset;
+               bytecode->bc.len = lum->u.filter.data_size;
+               bytecode->bc.reloc_offset = lum->u.filter.reloc_offset;
                if (ops->cmd) {
                        ret = ops->cmd(lum->handle, lum->cmd,
                                        (unsigned long) bytecode,
This page took 0.037087 seconds and 4 git commands to generate.