Filter: receive, attach and link empty filter
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 10 Jul 2012 18:49:43 +0000 (14:49 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 10 Jul 2012 18:49:43 +0000 (14:49 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
include/lttng/ust-abi.h
include/lttng/ust-events.h
include/ust-comm.h
liblttng-ust/Makefile.am
liblttng-ust/ltt-events.c
liblttng-ust/ltt-probes.c
liblttng-ust/lttng-filter.c [new file with mode: 0644]
liblttng-ust/lttng-ust-abi.c
liblttng-ust/lttng-ust-comm.c

index 2651fc99747c698da04b79b784fa8c150ca2b7e9..8bcaa380e10c49fbf9a788bf49cc7f7ed9a2c802 100644 (file)
@@ -165,6 +165,13 @@ struct lttng_ust_calibrate {
        } u;
 };
 
+#define FILTER_BYTECODE_MAX_LEN                65536
+struct lttng_ust_filter_bytecode {
+       uint16_t len;
+       uint16_t reloc_table_offset;
+       char data[0];
+};
+
 #define _UST_CMD(minor)                                (minor)
 #define _UST_CMDR(minor, type)                 (minor)
 #define _UST_CMDW(minor, type)                 (minor)
@@ -210,6 +217,9 @@ struct lttng_ust_calibrate {
 #define LTTNG_UST_TRACEPOINT_LIST_GET          _UST_CMD(0x90)
 #define LTTNG_UST_TRACEPOINT_FIELD_LIST_GET    _UST_CMD(0x91)
 
+/* Event FD commands */
+#define LTTNG_UST_FILTER                       _UST_CMD(0xA0)
+
 #define LTTNG_UST_ROOT_HANDLE  0
 
 struct lttng_ust_obj;
index 91d5839bfa6c1386ea13f9160207e7c27413be3e..1e2b349f1aa29ca9f389f7afac48f9382b013d2f 100644 (file)
@@ -245,6 +245,7 @@ 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;
        unsigned int enabled:1;
 };
 
@@ -257,6 +258,7 @@ 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;
        int loglevel;
        char name[0];
 };
@@ -283,6 +285,7 @@ struct lttng_ust_field_list {
 
 struct ust_pending_probe;
 struct ltt_event;
+struct lttng_ust_filter_bytecode;
 
 /*
  * ltt_event structure is referred to by the tracing fast path. It must be
@@ -302,6 +305,7 @@ struct ltt_event {
        struct cds_list_head list;              /* Event list */
        struct cds_list_head wildcard_list;     /* Event list for wildcard */
        struct ust_pending_probe *pending_probe;
+       struct lttng_ust_filter_bytecode *filter_bytecode;
        unsigned int metadata_dumped:1;
 };
 
@@ -414,9 +418,6 @@ struct ltt_channel *ltt_global_channel_create(struct ltt_session *session,
 
 int ltt_event_create(struct ltt_channel *chan,
                struct lttng_ust_event *event_param,
-               int (*filter)(void *filter_data,
-                       const char *filter_stack_data),
-               void *filter_data,
                struct ltt_event **event);
 
 int ltt_channel_enable(struct ltt_channel *channel);
@@ -473,5 +474,12 @@ int ltt_loglevel_match(const struct lttng_event_desc *desc,
                int req_loglevel);
 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);
+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);
+void lttng_filter_wildcard_link_bytecode(struct session_wildcard *wildcard);
 
 #endif /* _LTTNG_UST_EVENTS_H */
index 9d2643df129c373176f994c4d4131fb6dd1e4036..b09fcca4f379728ab713ab1ec17b7dcb251c3eb0 100644 (file)
@@ -131,6 +131,10 @@ struct ustcomm_ust_msg {
                struct lttng_ust_context context;
                struct lttng_ust_tracer_version version;
                struct lttng_ust_tracepoint_iter tracepoint;
+               struct {
+                       uint16_t data_size;     /* following filter data */
+                       uint16_t reloc_offset;
+               } filter;
        } u;
 };
 
index 75a2ba8ab19932ef4782d37ae48a85f103cceb5f..eae0b33101649589296357f56f1401b0734f7bd0 100644 (file)
@@ -28,6 +28,7 @@ liblttng_ust_runtime_la_SOURCES = \
        lttng-context-procname.c \
        ltt-context.c \
        ltt-events.c \
+       lttng-filter.c \
        tracepoint-internal.h \
        clock.h \
        compat.h \
index eb6749d944628043332e5e1426c5c8fe25a77926..9ef28c9adb144c7cd0d01f43b17590360f8bd3de 100644 (file)
@@ -251,14 +251,15 @@ int pending_probe_fix_events(const struct lttng_event_desc *desc)
                                        sizeof(event_param.name));
                                /* create event */
                                ret = ltt_event_create(sw->chan,
-                                       &event_param, NULL, NULL,
-                                       &ev);
+                                       &event_param, &ev);
                                if (ret) {
                                        DBG("Error creating event");
                                        continue;
                                }
                                cds_list_add(&ev->wildcard_list,
                                        &sw->events);
+                               lttng_filter_event_link_bytecode(ev,
+                                       sw->filter_bytecode);
                        }
                }
        }
@@ -500,9 +501,6 @@ void _ltt_channel_destroy(struct ltt_channel *chan)
  */
 int ltt_event_create(struct ltt_channel *chan,
                struct lttng_ust_event *event_param,
-               int (*filter)(void *filter_data,
-                       const char *filter_stack_data),
-               void *filter_data,
                struct ltt_event **_event)
 {
        const struct lttng_event_desc *desc = NULL;     /* silence gcc */
@@ -550,8 +548,6 @@ int ltt_event_create(struct ltt_channel *chan,
                goto cache_error;
        }
        event->chan = chan;
-       event->filter = filter;
-       event->filter_data = filter_data;
        /*
         * used_event_id counts the maximum number of event IDs that can
         * register if all probes register.
@@ -656,6 +652,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);
        free(event);
 }
 
@@ -1420,6 +1418,7 @@ void _remove_wildcard(struct session_wildcard *wildcard)
                cds_list_del(&wildcard->entry->list);
                free(wildcard->entry);
        }
+       free(wildcard->filter_bytecode);
        free(wildcard);
 }
 
index 39fb571607ad5cd1ff76e99b1d1f2ab2aa51de19..8ccb6fab9d2f32c37e2c14fa945adbcb38a9b54e 100644 (file)
@@ -372,8 +372,7 @@ void ltt_probes_create_wildcard_events(struct wildcard_entry *entry,
                                        sizeof(event_param.name));
                                /* create event */
                                ret = ltt_event_create(wildcard->chan,
-                                       &event_param, NULL, NULL,
-                                       &ev);
+                                       &event_param, &ev);
                                if (ret) {
                                        DBG("Error creating event");
                                        continue;
@@ -383,5 +382,6 @@ void ltt_probes_create_wildcard_events(struct wildcard_entry *entry,
                        }
                }
        }
+       lttng_filter_wildcard_link_bytecode(wildcard);
 }
 
diff --git a/liblttng-ust/lttng-filter.c b/liblttng-ust/lttng-filter.c
new file mode 100644 (file)
index 0000000..b617bc9
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * lttng-filter.c
+ *
+ * LTTng UST filter code.
+ *
+ * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <helper.h>
+#include <lttng/ust-events.h>
+
+static
+int lttng_filter_interpret_bytecode(void *filter_data,
+               const char *filter_stack_data)
+{
+       /* TODO */
+       return 0;
+}
+
+static
+int _lttng_filter_event_link_bytecode(struct ltt_event *event,
+               struct lttng_ust_filter_bytecode *filter_bytecode)
+{
+       if (!filter_bytecode)
+               return 0;
+
+       event->filter = lttng_filter_interpret_bytecode;
+       /* TODO */
+       /* event->filter_data = ; */
+       return 0;
+}
+
+void lttng_filter_event_link_bytecode(struct ltt_event *event,
+               struct lttng_ust_filter_bytecode *filter_bytecode)
+{
+       int ret;
+
+       ret = _lttng_filter_event_link_bytecode(event, event->filter_bytecode);
+       if (ret) {
+               fprintf(stderr, "[lttng filter] error linking event 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.
+ */
+void lttng_filter_wildcard_link_bytecode(struct session_wildcard *wildcard)
+{
+       struct ltt_event *event;
+       int ret;
+
+       if (!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) {
+                       fprintf(stderr, "[lttng filter] error linking wildcard bytecode\n");
+               }
+
+       }
+       return;
+}
+
+/*
+ * Need to attach filter to an event before starting tracing for the
+ * session.
+ */
+int lttng_filter_event_attach_bytecode(struct ltt_event *event,
+               struct lttng_ust_filter_bytecode *filter_bytecode)
+{
+       struct lttng_ust_filter_bytecode *bc;
+
+       if (event->chan->session->been_active)
+               return -EPERM;
+       if (event->filter_bytecode)
+               return -EEXIST;
+
+       bc = zmalloc(sizeof(struct lttng_ust_filter_bytecode)
+                       + filter_bytecode->len);
+       if (!bc)
+               return -ENOMEM;
+       event->filter_bytecode = bc;
+       return 0;
+}
+
+/*
+ * Need to attach filter to a wildcard before starting tracing for the
+ * session.
+ */
+int lttng_filter_wildcard_attach_bytecode(struct session_wildcard *wildcard,
+               struct lttng_ust_filter_bytecode *filter_bytecode)
+{
+       struct lttng_ust_filter_bytecode *bc;
+
+       if (wildcard->chan->session->been_active)
+               return -EPERM;
+       if (wildcard->filter_bytecode)
+               return -EEXIST;
+
+       bc = zmalloc(sizeof(struct lttng_ust_filter_bytecode)
+                       + filter_bytecode->len);
+       if (!bc)
+               return -ENOMEM;
+       wildcard->filter_bytecode = bc;
+       return 0;
+}
index fded1e3a806072c0fe8716a5c13d2ee654a54a8f..12b42ea9b0a1d335b0a937330ab24c4806d11e1d 100644 (file)
@@ -361,7 +361,7 @@ void lttng_metadata_create_events(int channel_objd)
         * We tolerate no failure path after event creation. It will stay
         * invariant for the rest of the session.
         */
-       ret = ltt_event_create(channel, &metadata_params, NULL, NULL, &event);
+       ret = ltt_event_create(channel, &metadata_params, &event);
        if (ret < 0) {
                goto create_error;
        }
@@ -753,7 +753,7 @@ int lttng_abi_create_event(int channel_objd,
         * We tolerate no failure path after event creation. It will stay
         * invariant for the rest of the session.
         */
-       ret = ltt_event_create(channel, event_param, NULL, NULL, &event);
+       ret = ltt_event_create(channel, event_param, &event);
        if (ret < 0) {
                goto event_error;
        }
@@ -1035,6 +1035,8 @@ static const struct lttng_ust_objd_ops lib_ring_buffer_objd_ops = {
  *             Enable recording for this event (weak enable)
  *     LTTNG_UST_DISABLE
  *             Disable recording for this event (strong disable)
+ *     LTTNG_UST_FILTER
+ *             Attach a filter to an event.
  */
 static
 long lttng_event_cmd(int objd, unsigned int cmd, unsigned long arg,
@@ -1051,6 +1053,17 @@ long lttng_event_cmd(int objd, unsigned int cmd, unsigned long arg,
                return ltt_event_enable(event);
        case LTTNG_UST_DISABLE:
                return ltt_event_disable(event);
+       case LTTNG_UST_FILTER:
+       {
+               int ret;
+               ret = lttng_filter_event_attach_bytecode(event,
+                               (struct lttng_ust_filter_bytecode *) arg);
+               if (ret)
+                       return ret;
+               lttng_filter_event_link_bytecode(event,
+                               event->filter_bytecode);
+               return 0;
+       }
        default:
                return -EINVAL;
        }
@@ -1088,6 +1101,8 @@ static const struct lttng_ust_objd_ops lttng_event_ops = {
  *             Enable recording for these wildcard events (weak enable)
  *     LTTNG_UST_DISABLE
  *             Disable recording for these wildcard events (strong disable)
+ *     LTTNG_UST_FILTER
+ *             Attach a filter to a wildcard.
  */
 static
 long lttng_wildcard_cmd(int objd, unsigned int cmd, unsigned long arg,
@@ -1107,6 +1122,17 @@ long lttng_wildcard_cmd(int objd, unsigned int cmd, unsigned long arg,
                return ltt_wildcard_enable(wildcard);
        case LTTNG_UST_DISABLE:
                return ltt_wildcard_disable(wildcard);
+       case LTTNG_UST_FILTER:
+       {
+               int ret;
+
+               ret = lttng_filter_wildcard_attach_bytecode(wildcard,
+                               (struct lttng_ust_filter_bytecode *) arg);
+               if (ret)
+                       return ret;
+               lttng_filter_wildcard_link_bytecode(wildcard);
+               return 0;
+       }
        default:
                return -EINVAL;
        }
index deca7cbd8f3b884e9dd59bb16871cf8a118e6bfa..69414ebd34cc338b4f9f10a3ce02f3af89003239 100644 (file)
@@ -281,6 +281,56 @@ int handle_message(struct sock_info *sock_info,
                else
                        ret = lttng_ust_objd_unref(lum->handle);
                break;
+       case LTTNG_UST_FILTER:
+       {
+               /* Receive filter data */
+               struct {
+                       uint16_t len;
+                       uint16_t reloc_offset;
+                       char data[FILTER_BYTECODE_MAX_LEN];
+               } filter_data;
+
+               if (lum->u.filter.data_size > 65536) {
+                       ERR("Filter data size is too large: %u bytes\n",
+                               lum->u.filter.data_size);
+                       ret = -EINVAL;
+                       goto error;
+               }
+               len = ustcomm_recv_unix_sock(sock, filter_data.data,
+                               lum->u.filter.data_size);
+               switch (len) {
+               case 0: /* orderly shutdown */
+                       ret = 0;
+                       goto error;
+               case -1:
+                       DBG("Receive failed from lttng-sessiond with errno %d", errno);
+                       if (errno == ECONNRESET) {
+                               ERR("%s remote end closed connection\n", sock_info->name);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+                       ret = -EINVAL;
+                       goto end;
+               default:
+                       if (len == lum->u.filter.data_size) {
+                               DBG("filter data received\n");
+                               break;
+                       } else {
+                               ERR("incorrect filter data message size: %zd\n", len);
+                               ret = -EINVAL;
+                               goto end;
+                       }
+               }
+               filter_data.len = lum->u.filter.data_size;
+               filter_data.reloc_offset = lum->u.filter.reloc_offset;
+               if (ops->cmd)
+                       ret = ops->cmd(lum->handle, lum->cmd,
+                                       (unsigned long) &filter_data,
+                                       &args);
+               else
+                       ret = -ENOSYS;
+               break;
+       }
        default:
                if (ops->cmd)
                        ret = ops->cmd(lum->handle, lum->cmd,
This page took 0.032068 seconds and 4 git commands to generate.