From 2d78951a159c97fd2bfebb84a9b22ef97674d56a Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 10 Jul 2012 14:49:43 -0400 Subject: [PATCH] Filter: receive, attach and link empty filter Signed-off-by: Mathieu Desnoyers --- include/lttng/ust-abi.h | 10 +++ include/lttng/ust-events.h | 14 +++- include/ust-comm.h | 4 ++ liblttng-ust/Makefile.am | 1 + liblttng-ust/ltt-events.c | 13 ++-- liblttng-ust/ltt-probes.c | 4 +- liblttng-ust/lttng-filter.c | 129 ++++++++++++++++++++++++++++++++++ liblttng-ust/lttng-ust-abi.c | 30 +++++++- liblttng-ust/lttng-ust-comm.c | 50 +++++++++++++ 9 files changed, 241 insertions(+), 14 deletions(-) create mode 100644 liblttng-ust/lttng-filter.c diff --git a/include/lttng/ust-abi.h b/include/lttng/ust-abi.h index 2651fc99..8bcaa380 100644 --- a/include/lttng/ust-abi.h +++ b/include/lttng/ust-abi.h @@ -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; diff --git a/include/lttng/ust-events.h b/include/lttng/ust-events.h index 91d5839b..1e2b349f 100644 --- a/include/lttng/ust-events.h +++ b/include/lttng/ust-events.h @@ -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 */ diff --git a/include/ust-comm.h b/include/ust-comm.h index 9d2643df..b09fcca4 100644 --- a/include/ust-comm.h +++ b/include/ust-comm.h @@ -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; }; diff --git a/liblttng-ust/Makefile.am b/liblttng-ust/Makefile.am index 75a2ba8a..eae0b331 100644 --- a/liblttng-ust/Makefile.am +++ b/liblttng-ust/Makefile.am @@ -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 \ diff --git a/liblttng-ust/ltt-events.c b/liblttng-ust/ltt-events.c index eb6749d9..9ef28c9a 100644 --- a/liblttng-ust/ltt-events.c +++ b/liblttng-ust/ltt-events.c @@ -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); } diff --git a/liblttng-ust/ltt-probes.c b/liblttng-ust/ltt-probes.c index 39fb5716..8ccb6fab 100644 --- a/liblttng-ust/ltt-probes.c +++ b/liblttng-ust/ltt-probes.c @@ -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 index 00000000..b617bc9a --- /dev/null +++ b/liblttng-ust/lttng-filter.c @@ -0,0 +1,129 @@ +/* + * lttng-filter.c + * + * LTTng UST filter code. + * + * Copyright (C) 2010-2012 Mathieu Desnoyers + * + * 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 +#include +#include +#include + +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; +} diff --git a/liblttng-ust/lttng-ust-abi.c b/liblttng-ust/lttng-ust-abi.c index fded1e3a..12b42ea9 100644 --- a/liblttng-ust/lttng-ust-abi.c +++ b/liblttng-ust/lttng-ust-abi.c @@ -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; } diff --git a/liblttng-ust/lttng-ust-comm.c b/liblttng-ust/lttng-ust-comm.c index deca7cbd..69414ebd 100644 --- a/liblttng-ust/lttng-ust-comm.c +++ b/liblttng-ust/lttng-ust-comm.c @@ -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, -- 2.34.1