} 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)
#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;
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;
};
/* 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];
};
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
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;
};
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);
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 */
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;
};
lttng-context-procname.c \
ltt-context.c \
ltt-events.c \
+ lttng-filter.c \
tracepoint-internal.h \
clock.h \
compat.h \
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);
}
}
}
*/
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 */
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.
}
cds_list_del(&event->list);
lttng_destroy_context(event->ctx);
+ free(event->filter_bytecode);
+ free(event->filter_data);
free(event);
}
cds_list_del(&wildcard->entry->list);
free(wildcard->entry);
}
+ free(wildcard->filter_bytecode);
free(wildcard);
}
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;
}
}
}
+ lttng_filter_wildcard_link_bytecode(wildcard);
}
--- /dev/null
+/*
+ * 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;
+}
* 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;
}
* 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;
}
* 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,
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;
}
* 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,
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;
}
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,